@jdeighan/coffee-utils 7.0.51 → 7.0.54

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jdeighan/coffee-utils",
3
3
  "type": "module",
4
- "version": "7.0.51",
4
+ "version": "7.0.54",
5
5
  "description": "A set of utility functions for CoffeeScript",
6
6
  "main": "coffee_utils.js",
7
7
  "exports": {
@@ -52,6 +52,6 @@
52
52
  "svelte": "^3.48.0"
53
53
  },
54
54
  "devDependencies": {
55
- "@jdeighan/unit-tester": "^2.0.3"
55
+ "@jdeighan/unit-tester": "^2.0.6"
56
56
  }
57
57
  }
@@ -1,7 +1,7 @@
1
1
  # call_stack.coffee
2
2
 
3
3
  import {
4
- undef, defined, croak, assert, isBoolean, escapeStr,
4
+ undef, defined, croak, assert, OL, isBoolean, escapeStr,
5
5
  } from '@jdeighan/coffee-utils'
6
6
  import {log, LOG} from '@jdeighan/coffee-utils/log'
7
7
  import {getPrefix} from '@jdeighan/coffee-utils/arrow'
@@ -36,14 +36,64 @@ export class CallStack
36
36
 
37
37
  # ........................................................................
38
38
 
39
- enter: (funcName, isLogged=false) ->
39
+ enter: (funcName, oldFlag=undef) ->
40
+ # --- funcName might be <object>.<method>
40
41
 
42
+ assert (oldFlag == undef), "enter() takes only 1 arg"
41
43
  if doDebugStack
42
- LOG "[--> CALL #{funcName}]"
44
+ LOG "[--> ENTER #{funcName}]"
45
+
46
+ lMatches = funcName.match(///^
47
+ ([A-Za-z_][A-Za-z0-9_]*)
48
+ (?:
49
+ \.
50
+ ([A-Za-z_][A-Za-z0-9_]*)
51
+ )?
52
+ $///)
53
+ assert defined(lMatches), "Bad funcName: #{OL(funcName)}"
54
+ [_, ident1, ident2] = lMatches
55
+ if ident2
56
+ @lStack.push({
57
+ fullName: "#{ident1}.#{ident2}"
58
+ funcName: ident2
59
+ isLogged: false
60
+ })
61
+ else
62
+ @lStack.push({
63
+ fullName: ident1
64
+ funcName: ident1
65
+ isLogged: false
66
+ })
67
+ return
68
+
69
+ # ........................................................................
70
+
71
+ isLogging: () ->
72
+
73
+ if (@lStack.length == 0)
74
+ return false
75
+ else
76
+ return @lStack[@lStack.length - 1].isLogged
77
+
78
+ # ........................................................................
79
+
80
+ isLoggingPrev: () ->
81
+
82
+ if (@lStack.length < 2)
83
+ return false
84
+ else
85
+ return @lStack[@lStack.length - 2].isLogged
86
+
87
+ # ........................................................................
88
+
89
+ logCurFunc: () ->
43
90
 
44
- @lStack.push({funcName, isLogged})
45
- if isLogged
46
- @level += 1
91
+ # --- funcName must be the current function
92
+ # and the isLogged flag must currently be false
93
+ cur = @lStack[@lStack.length - 1]
94
+ assert (cur.isLogged == false), "isLogged is already true"
95
+ cur.isLogged = true
96
+ @level += 1
47
97
  return
48
98
 
49
99
  # ........................................................................
@@ -58,18 +108,18 @@ export class CallStack
58
108
  LOG "ERROR: returnFrom('#{funcName}') but stack is empty"
59
109
  return
60
110
 
61
- {funcName, isLogged} = @lStack.pop()
111
+ {fullName, isLogged} = @lStack.pop()
62
112
  if isLogged && (@level > 0)
63
113
  @level -= 1
64
114
 
65
115
  # --- This should do nothing
66
- while (funcName != fName) && (@lStack.length > 0)
67
- LOG "[MISSING RETURN FROM #{funcName} (return from #{fName})]"
68
- {funcName, isLogged} = @lStack.pop()
116
+ while (fullName != fName) && (@lStack.length > 0)
117
+ LOG "[MISSING RETURN FROM #{fullName} (return from #{fName})]"
118
+ {fullName, isLogged} = @lStack.pop()
69
119
  if isLogged && (@level > 0)
70
120
  @level -= 1
71
121
 
72
- if funcName != fName
122
+ if fullName != fName
73
123
  @dump()
74
124
  LOG "BAD BAD BAD BAD returnFrom('#{fName}')"
75
125
  return
@@ -91,22 +141,24 @@ export class CallStack
91
141
 
92
142
  # ........................................................................
93
143
 
94
- isActive: (fName) ->
144
+ isActive: (funcName) ->
145
+ # --- funcName won't be <obj>.<method>
146
+ # but the stack might contain that form
95
147
 
96
148
  for h in @lStack
97
- if (h.funcName == fName)
149
+ if (h.funcName == funcName)
98
150
  return true
99
151
  return false
100
152
 
101
153
  # ........................................................................
102
154
  # ........................................................................
103
155
 
104
- dump: (label='CALL STACK') ->
156
+ dump: (prefix='', label='CALL STACK') ->
105
157
 
106
158
  LOG "#{label}:"
107
159
  if @lStack.length == 0
108
160
  LOG " <EMPTY>"
109
161
  else
110
162
  for item, i in @lStack
111
- LOG " #{i}: #{JSON.stringify(item)}"
163
+ LOG " #{i}: #{item.fullName} #{item.isLogged}"
112
164
  return
package/src/call_stack.js CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  defined,
8
8
  croak,
9
9
  assert,
10
+ OL,
10
11
  isBoolean,
11
12
  escapeStr
12
13
  } from '@jdeighan/coffee-utils';
@@ -44,20 +45,64 @@ export var CallStack = class CallStack {
44
45
  }
45
46
 
46
47
  // ........................................................................
47
- enter(funcName, isLogged = false) {
48
+ enter(funcName, oldFlag = undef) {
49
+ var _, ident1, ident2, lMatches;
50
+ // --- funcName might be <object>.<method>
51
+ assert(oldFlag === undef, "enter() takes only 1 arg");
48
52
  if (doDebugStack) {
49
- LOG(`[--> CALL ${funcName}]`);
53
+ LOG(`[--> ENTER ${funcName}]`);
50
54
  }
51
- this.lStack.push({funcName, isLogged});
52
- if (isLogged) {
53
- this.level += 1;
55
+ lMatches = funcName.match(/^([A-Za-z_][A-Za-z0-9_]*)(?:\.([A-Za-z_][A-Za-z0-9_]*))?$/);
56
+ assert(defined(lMatches), `Bad funcName: ${OL(funcName)}`);
57
+ [_, ident1, ident2] = lMatches;
58
+ if (ident2) {
59
+ this.lStack.push({
60
+ fullName: `${ident1}.${ident2}`,
61
+ funcName: ident2,
62
+ isLogged: false
63
+ });
64
+ } else {
65
+ this.lStack.push({
66
+ fullName: ident1,
67
+ funcName: ident1,
68
+ isLogged: false
69
+ });
70
+ }
71
+ }
72
+
73
+ // ........................................................................
74
+ isLogging() {
75
+ if (this.lStack.length === 0) {
76
+ return false;
77
+ } else {
78
+ return this.lStack[this.lStack.length - 1].isLogged;
54
79
  }
55
80
  }
56
81
 
82
+ // ........................................................................
83
+ isLoggingPrev() {
84
+ if (this.lStack.length < 2) {
85
+ return false;
86
+ } else {
87
+ return this.lStack[this.lStack.length - 2].isLogged;
88
+ }
89
+ }
90
+
91
+ // ........................................................................
92
+ logCurFunc() {
93
+ var cur;
94
+ // --- funcName must be the current function
95
+ // and the isLogged flag must currently be false
96
+ cur = this.lStack[this.lStack.length - 1];
97
+ assert(cur.isLogged === false, "isLogged is already true");
98
+ cur.isLogged = true;
99
+ this.level += 1;
100
+ }
101
+
57
102
  // ........................................................................
58
103
  // --- if stack is empty, log the error, but continue
59
104
  returnFrom(fName) {
60
- var funcName, isLogged;
105
+ var fullName, isLogged;
61
106
  if (doDebugStack) {
62
107
  LOG(`[<-- BACK ${fName}]`);
63
108
  }
@@ -65,19 +110,19 @@ export var CallStack = class CallStack {
65
110
  LOG(`ERROR: returnFrom('${funcName}') but stack is empty`);
66
111
  return;
67
112
  }
68
- ({funcName, isLogged} = this.lStack.pop());
113
+ ({fullName, isLogged} = this.lStack.pop());
69
114
  if (isLogged && (this.level > 0)) {
70
115
  this.level -= 1;
71
116
  }
72
117
  // --- This should do nothing
73
- while ((funcName !== fName) && (this.lStack.length > 0)) {
74
- LOG(`[MISSING RETURN FROM ${funcName} (return from ${fName})]`);
75
- ({funcName, isLogged} = this.lStack.pop());
118
+ while ((fullName !== fName) && (this.lStack.length > 0)) {
119
+ LOG(`[MISSING RETURN FROM ${fullName} (return from ${fName})]`);
120
+ ({fullName, isLogged} = this.lStack.pop());
76
121
  if (isLogged && (this.level > 0)) {
77
122
  this.level -= 1;
78
123
  }
79
124
  }
80
- if (funcName !== fName) {
125
+ if (fullName !== fName) {
81
126
  this.dump();
82
127
  LOG(`BAD BAD BAD BAD returnFrom('${fName}')`);
83
128
  }
@@ -98,12 +143,14 @@ export var CallStack = class CallStack {
98
143
  }
99
144
 
100
145
  // ........................................................................
101
- isActive(fName) {
146
+ isActive(funcName) {
102
147
  var h, j, len, ref;
103
148
  ref = this.lStack;
149
+ // --- funcName won't be <obj>.<method>
150
+ // but the stack might contain that form
104
151
  for (j = 0, len = ref.length; j < len; j++) {
105
152
  h = ref[j];
106
- if (h.funcName === fName) {
153
+ if (h.funcName === funcName) {
107
154
  return true;
108
155
  }
109
156
  }
@@ -112,7 +159,7 @@ export var CallStack = class CallStack {
112
159
 
113
160
  // ........................................................................
114
161
  // ........................................................................
115
- dump(label = 'CALL STACK') {
162
+ dump(prefix = '', label = 'CALL STACK') {
116
163
  var i, item, j, len, ref;
117
164
  LOG(`${label}:`);
118
165
  if (this.lStack.length === 0) {
@@ -121,7 +168,7 @@ export var CallStack = class CallStack {
121
168
  ref = this.lStack;
122
169
  for (i = j = 0, len = ref.length; j < len; i = ++j) {
123
170
  item = ref[i];
124
- LOG(` ${i}: ${JSON.stringify(item)}`);
171
+ LOG(` ${i}: ${item.fullName} ${item.isLogged}`);
125
172
  }
126
173
  }
127
174
  }
@@ -18,7 +18,130 @@ import {
18
18
 
19
19
  callStack = new CallStack()
20
20
  doDebugDebug = false
21
- shouldLog = undef # set in resetDebugging() and setDebugging()
21
+
22
+ export shouldLog = undef # set in resetDebugging() and setDebugging()
23
+ export lFuncList = []
24
+
25
+ # ---------------------------------------------------------------------------
26
+
27
+ export debug = (label, lObjects...) ->
28
+
29
+ assert isString(label), "1st arg #{OL(label)} should be a string"
30
+
31
+ # --- We want to allow objects to be undef. Therefore, we need to
32
+ # distinguish between 1 arg sent vs. 2 or more args sent
33
+ nObjects = lObjects.length
34
+
35
+ # --- funcName is only set for types 'enter' and 'return'
36
+ [type, funcName] = getType(label, nObjects)
37
+ if doDebugDebug
38
+ LOG "debug(): type = #{OL(type)}"
39
+ LOG "debug(): funcName = #{OL(funcName)}"
40
+
41
+ switch type
42
+ when 'enter'
43
+ callStack.enter funcName
44
+ label = shouldLog(label, type, funcName, callStack)
45
+ when 'return'
46
+ label = shouldLog(label, type, funcName, callStack)
47
+ when 'string'
48
+ label = shouldLog(label, type, undef, callStack)
49
+ assert (nObjects == 0),
50
+ "multiple objects only not allowed for #{OL(type)}"
51
+ when 'objects'
52
+ label = shouldLog(label, type, undef, callStack)
53
+ assert (nObjects > 0),
54
+ "multiple objects only not allowed for #{OL(type)}"
55
+ doLog = defined(label)
56
+
57
+ if doDebugDebug
58
+ if nObjects == 0
59
+ LOG "debug(#{OL(label)}) - 1 arg"
60
+ else
61
+ LOG "debug(#{OL(label)}), #{nObjects} args"
62
+ LOG "doLog = #{OL(doLog)}"
63
+
64
+ if doLog
65
+ level = callStack.getLevel()
66
+ prefix = getPrefix(level)
67
+
68
+ if doDebugDebug
69
+ LOG "callStack", callStack
70
+ LOG "level = #{OL(level)}"
71
+ LOG "prefix = #{OL(prefix)}"
72
+
73
+ switch type
74
+ when 'enter'
75
+ log label, {prefix}
76
+ for obj,i in lObjects
77
+ if (i > 0)
78
+ log sep_dash, {prefix: removeLastVbar(prefix)}
79
+ logItem undef, obj, {prefix: removeLastVbar(prefix)}
80
+ when 'return'
81
+ log label, {prefix: addArrow(prefix)}
82
+ for obj,i in lObjects
83
+ if (i > 0)
84
+ log sep_dash, {prefix: removeLastVbar(prefix)}
85
+ logItem undef, obj, {prefix: removeLastVbar(prefix)}
86
+ when 'string'
87
+ log label, {prefix}
88
+ when 'objects'
89
+ if (nObjects==1) && shortEnough(label, lObjects[0])
90
+ logItem label, lObjects[0], {prefix}
91
+ else
92
+ if (label.indexOf(':') != label.length - 1)
93
+ label += ':'
94
+ log label, {prefix}
95
+ for obj in lObjects
96
+ logItem undef, obj, {prefix}
97
+
98
+ if (type == 'enter') && doLog && (label.indexOf('call') == -1)
99
+ callStack.logCurFunc()
100
+ else if (type == 'return')
101
+ callStack.returnFrom funcName
102
+
103
+ return true # allow use in boolean expressions
104
+
105
+ # ---------------------------------------------------------------------------
106
+
107
+ export stdShouldLog = (label, type, funcName, stack) ->
108
+ # --- if type is 'enter', then funcName won't be on the stack yet
109
+ # returns the (possibly modified) label to log
110
+
111
+ # --- If we're logging now,
112
+ # but we won't be logging when funcName is activated
113
+ # then change 'enter' to 'call'
114
+
115
+ assert isString(label), "label #{OL(label)} not a string"
116
+ assert isString(type), "type #{OL(type)} not a string"
117
+ if (type == 'enter') || (type == 'return')
118
+ assert isString(funcName), "func name #{OL(funcName)} not a string"
119
+ else
120
+ assert funcName == undef, "func name #{OL(funcName)} not undef"
121
+ assert stack instanceof CallStack, "not a call stack object"
122
+
123
+ if doDebugDebug
124
+ LOG "stdShouldLog(#{OL(label)}, #{OL(type)}, #{OL(funcName)}, stack)"
125
+ LOG "stack", stack
126
+ LOG "lFuncList", lFuncList
127
+
128
+ switch type
129
+ when 'enter'
130
+ if funcMatch(stack, lFuncList)
131
+ return label
132
+
133
+ else
134
+ # --- As a special case, if we enter a function where we will not
135
+ # be logging, but we were logging in the calling function,
136
+ # we'll log out the call itself
137
+
138
+ prevLogged = stack.isLoggingPrev()
139
+ if prevLogged
140
+ return label.replace('enter', 'call')
141
+ else
142
+ if funcMatch(stack, lFuncList)
143
+ return label
144
+ return undef
22
145
 
23
146
  # ---------------------------------------------------------------------------
24
147
 
@@ -36,7 +159,7 @@ resetDebugging = () ->
36
159
  if doDebugDebug
37
160
  LOG "resetDebugging()"
38
161
  callStack.reset()
39
- shouldLog = (type, str, stack) -> false
162
+ shouldLog = (label, type, funcName, stack) -> undef
40
163
  return
41
164
 
42
165
  # ---------------------------------------------------------------------------
@@ -45,44 +168,82 @@ export setDebugging = (option) ->
45
168
 
46
169
  resetDebugging()
47
170
  if isBoolean(option)
48
- shouldLog = (type, str, stack) -> option
171
+ if option
172
+ shouldLog = (label, type, funcName, stack) -> label
173
+ else
174
+ shouldLog = (label, type, funcName, stack) -> undef
175
+ if doDebugDebug
176
+ LOG "setDebugging = #{option}"
49
177
  else if isString(option)
50
- shouldLog = (type, str, stack) ->
51
- lFuncs = words(option)
52
- switch type
53
- when 'enter'
54
- return funcMatch(stack, lFuncs, str)
55
- else
56
- return funcMatch(stack, lFuncs)
178
+ lFuncList = getFuncList(option)
179
+ shouldLog = stdShouldLog
57
180
  if doDebugDebug
58
181
  LOG "setDebugging FUNCS: #{option}"
182
+ LOG 'lFuncList', lFuncList
59
183
  else if isFunction(option)
60
184
  shouldLog = option
61
185
  if doDebugDebug
62
186
  LOG "setDebugging to custom func"
63
187
  else
64
- croak "setDebugging(): bad parameter #{OL(option)}"
188
+ croak "bad parameter #{OL(option)}"
65
189
  return
66
190
 
67
191
  # ---------------------------------------------------------------------------
68
192
  # --- export only to allow unit tests
69
193
 
70
- export funcMatch = (stack, lFuncNames, enteringFunc=undef) ->
194
+ export getFuncList = (str) ->
195
+
196
+ lFuncList = []
197
+ for word in words(str)
198
+ if lMatches = word.match(///^
199
+ ([A-Za-z_][A-Za-z0-9_]*)
200
+ (?:
201
+ \.
202
+ ([A-Za-z_][A-Za-z0-9_]*)
203
+ )?
204
+ (\+)?
205
+ $///)
206
+ [_, ident1, ident2, plus] = lMatches
207
+ if ident2
208
+ lFuncList.push {
209
+ name: ident2
210
+ object: ident1
211
+ plus: (plus == '+')
212
+ }
213
+ else
214
+ lFuncList.push {
215
+ name: ident1
216
+ plus: (plus == '+')
217
+ }
218
+ else
219
+ croak "Bad word in func list: #{OL(word)}"
220
+ return lFuncList
221
+
222
+ # ---------------------------------------------------------------------------
223
+ # --- export only to allow unit tests
71
224
 
72
- if defined(enteringFunc) && (enteringFunc in lFuncNames)
73
- return true
225
+ export funcMatch = (stack, lFuncList) ->
226
+
227
+ assert isArray(lFuncList), "not an array #{OL(lFuncList)}"
74
228
 
75
229
  curFunc = stack.curFunc()
76
- assert isString(curFunc), "funcMatch(): not a string #{OL(curFunc)}"
77
- assert isArray(lFuncNames), "funcMatch(): bad array #{lFuncNames}"
78
- if lFuncNames.includes(curFunc)
79
- return true
80
- else if (lMatches = curFunc.match(reMethod)) \
81
- && ([_, cls, meth] = lMatches) \
82
- && lFuncNames.includes(meth)
83
- return true
84
- else
85
- return false
230
+ if doDebugDebug
231
+ LOG "funcMatch(): curFunc = #{OL(curFunc)}"
232
+ stack.dump(' ')
233
+ LOG 'lFuncList', lFuncList
234
+ for h in lFuncList
235
+ {name, object, plus} = h
236
+ if (name == curFunc)
237
+ if doDebugDebug
238
+ LOG " curFunc in lFuncList - match successful"
239
+ return true
240
+ if plus && stack.isActive(name)
241
+ if doDebugDebug
242
+ LOG " func #{OL(name)} is active - match successful"
243
+ return true
244
+ if doDebugDebug
245
+ LOG " - no match"
246
+ return false
86
247
 
87
248
  # ---------------------------------------------------------------------------
88
249
  # --- type is one of: 'enter', 'return', 'string', 'object'
@@ -116,89 +277,6 @@ export getType = (str, nObjects) ->
116
277
 
117
278
  # ---------------------------------------------------------------------------
118
279
 
119
- export debug = (label, lObjects...) ->
120
-
121
- assert isString(label), "1st arg #{OL(label)} should be a string"
122
-
123
- # --- We want to allow objects to be undef. Therefore, we need to
124
- # distinguish between 1 arg sent vs. 2 or more args sent
125
- nObjects = lObjects.length
126
-
127
- # --- funcName is only set for types 'enter' and 'return'
128
- [type, funcName] = getType(label, nObjects)
129
- switch type
130
- when 'enter'
131
- doLog = shouldLog(type, funcName, callStack)
132
-
133
- # --- If we won't be logging when funcName is activated
134
- # then change 'enter' to 'call'
135
- callStack.enter funcName # add to call stack
136
- if ! shouldLog('string', 'abc', callStack)
137
- label = label.replace('enter', 'call')
138
- callStack.returnFrom funcName # remove from call stack
139
- when 'return'
140
- doLog = shouldLog(type, funcName, callStack)
141
- when 'string'
142
- doLog = shouldLog(type, label, callStack)
143
- assert (nObjects == 0),
144
- "multiple objects only not allowed for #{OL(type)}"
145
- when 'objects'
146
- doLog = shouldLog(type, label, callStack)
147
- assert (nObjects > 0),
148
- "multiple objects only not allowed for #{OL(type)}"
149
-
150
- if doDebugDebug
151
- if nObjects == 0
152
- LOG "debug(#{OL(label)}) - 1 arg"
153
- else
154
- LOG "debug(#{OL(label)}), #{nObjects} args"
155
- LOG "doLog = #{OL(doLog)}"
156
- LOG "type = #{OL(type)}"
157
- LOG "funcName = #{OL(funcName)}"
158
-
159
- if doLog
160
- level = callStack.getLevel()
161
- prefix = getPrefix(level)
162
-
163
- if doDebugDebug
164
- LOG "callStack", callStack
165
- LOG "level = #{OL(level)}"
166
- LOG "prefix = #{OL(prefix)}"
167
-
168
- switch type
169
- when 'enter'
170
- log label, {prefix}
171
- for obj,i in lObjects
172
- if (i > 0)
173
- log sep_dash, {prefix: removeLastVbar(prefix)}
174
- logItem undef, obj, {prefix: removeLastVbar(prefix)}
175
- when 'return'
176
- log label, {prefix: addArrow(prefix)}
177
- for obj,i in lObjects
178
- if (i > 0)
179
- log sep_dash, {prefix: removeLastVbar(prefix)}
180
- logItem undef, obj, {prefix: removeLastVbar(prefix)}
181
- when 'string'
182
- log label, {prefix}
183
- when 'objects'
184
- if (nObjects==1) && shortEnough(label, lObjects[0])
185
- logItem label, lObjects[0], {prefix}
186
- else
187
- if (label.indexOf(':') != label.length - 1)
188
- label += ':'
189
- log label, {prefix}
190
- for obj in lObjects
191
- logItem undef, obj, {prefix}
192
-
193
- if (type == 'enter')
194
- callStack.enter funcName, doLog
195
- else if (type == 'return')
196
- callStack.returnFrom funcName
197
-
198
- return true # allow use in boolean expressions
199
-
200
- # ---------------------------------------------------------------------------
201
-
202
280
  reMethod = ///^
203
281
  ([A-Za-z_][A-Za-z0-9_]*)
204
282
  \.
@@ -1,7 +1,6 @@
1
1
  // Generated by CoffeeScript 2.7.0
2
- // debug_utils.coffee
3
- var callStack, doDebugDebug, reMethod, resetDebugging, shouldLog,
4
- indexOf = [].indexOf;
2
+ // debug_utils.coffee
3
+ var callStack, doDebugDebug, reMethod, resetDebugging;
5
4
 
6
5
  import {
7
6
  assert,
@@ -55,93 +54,9 @@ callStack = new CallStack();
55
54
 
56
55
  doDebugDebug = false;
57
56
 
58
- shouldLog = undef; // set in resetDebugging() and setDebugging()
57
+ export var shouldLog = undef; // set in resetDebugging() and setDebugging()
59
58
 
60
-
61
- // ---------------------------------------------------------------------------
62
- export var debugDebug = function(flag = true) {
63
- doDebugDebug = flag;
64
- if (doDebugDebug) {
65
- LOG(`doDebugDebug = ${flag}`);
66
- }
67
- };
68
-
69
- // ---------------------------------------------------------------------------
70
- resetDebugging = function() {
71
- if (doDebugDebug) {
72
- LOG("resetDebugging()");
73
- }
74
- callStack.reset();
75
- shouldLog = function(type, str, stack) {
76
- return false;
77
- };
78
- };
79
-
80
- // ---------------------------------------------------------------------------
81
- export var setDebugging = function(option) {
82
- resetDebugging();
83
- if (isBoolean(option)) {
84
- shouldLog = function(type, str, stack) {
85
- return option;
86
- };
87
- } else if (isString(option)) {
88
- shouldLog = function(type, str, stack) {
89
- var lFuncs;
90
- lFuncs = words(option);
91
- switch (type) {
92
- case 'enter':
93
- return funcMatch(stack, lFuncs, str);
94
- default:
95
- return funcMatch(stack, lFuncs);
96
- }
97
- };
98
- if (doDebugDebug) {
99
- LOG(`setDebugging FUNCS: ${option}`);
100
- }
101
- } else if (isFunction(option)) {
102
- shouldLog = option;
103
- if (doDebugDebug) {
104
- LOG("setDebugging to custom func");
105
- }
106
- } else {
107
- croak(`setDebugging(): bad parameter ${OL(option)}`);
108
- }
109
- };
110
-
111
- // ---------------------------------------------------------------------------
112
- // --- export only to allow unit tests
113
- export var funcMatch = function(stack, lFuncNames, enteringFunc = undef) {
114
- var _, cls, curFunc, lMatches, meth;
115
- if (defined(enteringFunc) && (indexOf.call(lFuncNames, enteringFunc) >= 0)) {
116
- return true;
117
- }
118
- curFunc = stack.curFunc();
119
- assert(isString(curFunc), `funcMatch(): not a string ${OL(curFunc)}`);
120
- assert(isArray(lFuncNames), `funcMatch(): bad array ${lFuncNames}`);
121
- if (lFuncNames.includes(curFunc)) {
122
- return true;
123
- } else if ((lMatches = curFunc.match(reMethod)) && ([_, cls, meth] = lMatches) && lFuncNames.includes(meth)) {
124
- return true;
125
- } else {
126
- return false;
127
- }
128
- };
129
-
130
- // ---------------------------------------------------------------------------
131
- // --- type is one of: 'enter', 'return', 'string', 'object'
132
- export var getType = function(str, nObjects) {
133
- var lMatches;
134
- if (lMatches = str.match(/^\s*enter\s+([A-Za-z_][A-Za-z0-9_\.]*)/)) {
135
- // --- We are entering function curFunc
136
- return ['enter', lMatches[1]];
137
- } else if (lMatches = str.match(/^\s*return.+from\s+([A-Za-z_][A-Za-z0-9_\.]*)/)) {
138
- return ['return', lMatches[1]];
139
- } else if (nObjects > 0) {
140
- return ['objects', undef];
141
- } else {
142
- return ['string', undef];
143
- }
144
- };
59
+ export var lFuncList = [];
145
60
 
146
61
  // ---------------------------------------------------------------------------
147
62
  export var debug = function(label, ...lObjects) {
@@ -152,28 +67,27 @@ export var debug = function(label, ...lObjects) {
152
67
  nObjects = lObjects.length;
153
68
  // --- funcName is only set for types 'enter' and 'return'
154
69
  [type, funcName] = getType(label, nObjects);
70
+ if (doDebugDebug) {
71
+ LOG(`debug(): type = ${OL(type)}`);
72
+ LOG(`debug(): funcName = ${OL(funcName)}`);
73
+ }
155
74
  switch (type) {
156
75
  case 'enter':
157
- doLog = shouldLog(type, funcName, callStack);
158
- // --- If we won't be logging when funcName is activated
159
- // then change 'enter' to 'call'
160
- callStack.enter(funcName); // add to call stack
161
- if (!shouldLog('string', 'abc', callStack)) {
162
- label = label.replace('enter', 'call');
163
- }
164
- callStack.returnFrom(funcName); // remove from call stack
76
+ callStack.enter(funcName);
77
+ label = shouldLog(label, type, funcName, callStack);
165
78
  break;
166
79
  case 'return':
167
- doLog = shouldLog(type, funcName, callStack);
80
+ label = shouldLog(label, type, funcName, callStack);
168
81
  break;
169
82
  case 'string':
170
- doLog = shouldLog(type, label, callStack);
83
+ label = shouldLog(label, type, undef, callStack);
171
84
  assert(nObjects === 0, `multiple objects only not allowed for ${OL(type)}`);
172
85
  break;
173
86
  case 'objects':
174
- doLog = shouldLog(type, label, callStack);
87
+ label = shouldLog(label, type, undef, callStack);
175
88
  assert(nObjects > 0, `multiple objects only not allowed for ${OL(type)}`);
176
89
  }
90
+ doLog = defined(label);
177
91
  if (doDebugDebug) {
178
92
  if (nObjects === 0) {
179
93
  LOG(`debug(${OL(label)}) - 1 arg`);
@@ -181,8 +95,6 @@ export var debug = function(label, ...lObjects) {
181
95
  LOG(`debug(${OL(label)}), ${nObjects} args`);
182
96
  }
183
97
  LOG(`doLog = ${OL(doLog)}`);
184
- LOG(`type = ${OL(type)}`);
185
- LOG(`funcName = ${OL(funcName)}`);
186
98
  }
187
99
  if (doLog) {
188
100
  level = callStack.getLevel();
@@ -241,8 +153,8 @@ export var debug = function(label, ...lObjects) {
241
153
  }
242
154
  }
243
155
  }
244
- if (type === 'enter') {
245
- callStack.enter(funcName, doLog);
156
+ if ((type === 'enter') && doLog && (label.indexOf('call') === -1)) {
157
+ callStack.logCurFunc();
246
158
  } else if (type === 'return') {
247
159
  callStack.returnFrom(funcName);
248
160
  }
@@ -250,6 +162,180 @@ export var debug = function(label, ...lObjects) {
250
162
  };
251
163
 
252
164
 
165
+ // ---------------------------------------------------------------------------
166
+ export var stdShouldLog = function(label, type, funcName, stack) {
167
+ var prevLogged;
168
+ // --- if type is 'enter', then funcName won't be on the stack yet
169
+ // returns the (possibly modified) label to log
170
+
171
+ // --- If we're logging now,
172
+ // but we won't be logging when funcName is activated
173
+ // then change 'enter' to 'call'
174
+ assert(isString(label), `label ${OL(label)} not a string`);
175
+ assert(isString(type), `type ${OL(type)} not a string`);
176
+ if ((type === 'enter') || (type === 'return')) {
177
+ assert(isString(funcName), `func name ${OL(funcName)} not a string`);
178
+ } else {
179
+ assert(funcName === undef, `func name ${OL(funcName)} not undef`);
180
+ }
181
+ assert(stack instanceof CallStack, "not a call stack object");
182
+ if (doDebugDebug) {
183
+ LOG(`stdShouldLog(${OL(label)}, ${OL(type)}, ${OL(funcName)}, stack)`);
184
+ LOG("stack", stack);
185
+ LOG("lFuncList", lFuncList);
186
+ }
187
+ switch (type) {
188
+ case 'enter':
189
+ if (funcMatch(stack, lFuncList)) {
190
+ return label;
191
+ } else {
192
+ // --- As a special case, if we enter a function where we will not
193
+ // be logging, but we were logging in the calling function,
194
+ // we'll log out the call itself
195
+ prevLogged = stack.isLoggingPrev();
196
+ if (prevLogged) {
197
+ return label.replace('enter', 'call');
198
+ }
199
+ }
200
+ break;
201
+ default:
202
+ if (funcMatch(stack, lFuncList)) {
203
+ return label;
204
+ }
205
+ }
206
+ return undef;
207
+ };
208
+
209
+ // ---------------------------------------------------------------------------
210
+ export var debugDebug = function(flag = true) {
211
+ doDebugDebug = flag;
212
+ if (doDebugDebug) {
213
+ LOG(`doDebugDebug = ${flag}`);
214
+ }
215
+ };
216
+
217
+ // ---------------------------------------------------------------------------
218
+ resetDebugging = function() {
219
+ if (doDebugDebug) {
220
+ LOG("resetDebugging()");
221
+ }
222
+ callStack.reset();
223
+ shouldLog = function(label, type, funcName, stack) {
224
+ return undef;
225
+ };
226
+ };
227
+
228
+ // ---------------------------------------------------------------------------
229
+ export var setDebugging = function(option) {
230
+ resetDebugging();
231
+ if (isBoolean(option)) {
232
+ if (option) {
233
+ shouldLog = function(label, type, funcName, stack) {
234
+ return label;
235
+ };
236
+ } else {
237
+ shouldLog = function(label, type, funcName, stack) {
238
+ return undef;
239
+ };
240
+ }
241
+ if (doDebugDebug) {
242
+ LOG(`setDebugging = ${option}`);
243
+ }
244
+ } else if (isString(option)) {
245
+ lFuncList = getFuncList(option);
246
+ shouldLog = stdShouldLog;
247
+ if (doDebugDebug) {
248
+ LOG(`setDebugging FUNCS: ${option}`);
249
+ LOG('lFuncList', lFuncList);
250
+ }
251
+ } else if (isFunction(option)) {
252
+ shouldLog = option;
253
+ if (doDebugDebug) {
254
+ LOG("setDebugging to custom func");
255
+ }
256
+ } else {
257
+ croak(`bad parameter ${OL(option)}`);
258
+ }
259
+ };
260
+
261
+ // ---------------------------------------------------------------------------
262
+ // --- export only to allow unit tests
263
+ export var getFuncList = function(str) {
264
+ var _, ident1, ident2, j, lMatches, len1, plus, ref, word;
265
+ lFuncList = [];
266
+ ref = words(str);
267
+ for (j = 0, len1 = ref.length; j < len1; j++) {
268
+ word = ref[j];
269
+ if (lMatches = word.match(/^([A-Za-z_][A-Za-z0-9_]*)(?:\.([A-Za-z_][A-Za-z0-9_]*))?(\+)?$/)) {
270
+ [_, ident1, ident2, plus] = lMatches;
271
+ if (ident2) {
272
+ lFuncList.push({
273
+ name: ident2,
274
+ object: ident1,
275
+ plus: plus === '+'
276
+ });
277
+ } else {
278
+ lFuncList.push({
279
+ name: ident1,
280
+ plus: plus === '+'
281
+ });
282
+ }
283
+ } else {
284
+ croak(`Bad word in func list: ${OL(word)}`);
285
+ }
286
+ }
287
+ return lFuncList;
288
+ };
289
+
290
+ // ---------------------------------------------------------------------------
291
+ // --- export only to allow unit tests
292
+ export var funcMatch = function(stack, lFuncList) {
293
+ var curFunc, h, j, len1, name, object, plus;
294
+ assert(isArray(lFuncList), `not an array ${OL(lFuncList)}`);
295
+ curFunc = stack.curFunc();
296
+ if (doDebugDebug) {
297
+ LOG(`funcMatch(): curFunc = ${OL(curFunc)}`);
298
+ stack.dump(' ');
299
+ LOG('lFuncList', lFuncList);
300
+ }
301
+ for (j = 0, len1 = lFuncList.length; j < len1; j++) {
302
+ h = lFuncList[j];
303
+ ({name, object, plus} = h);
304
+ if (name === curFunc) {
305
+ if (doDebugDebug) {
306
+ LOG(" curFunc in lFuncList - match successful");
307
+ }
308
+ return true;
309
+ }
310
+ if (plus && stack.isActive(name)) {
311
+ if (doDebugDebug) {
312
+ LOG(` func ${OL(name)} is active - match successful`);
313
+ }
314
+ return true;
315
+ }
316
+ }
317
+ if (doDebugDebug) {
318
+ LOG(" - no match");
319
+ }
320
+ return false;
321
+ };
322
+
323
+ // ---------------------------------------------------------------------------
324
+ // --- type is one of: 'enter', 'return', 'string', 'object'
325
+ export var getType = function(str, nObjects) {
326
+ var lMatches;
327
+ if (lMatches = str.match(/^\s*enter\s+([A-Za-z_][A-Za-z0-9_\.]*)/)) {
328
+ // --- We are entering function curFunc
329
+ return ['enter', lMatches[1]];
330
+ } else if (lMatches = str.match(/^\s*return.+from\s+([A-Za-z_][A-Za-z0-9_\.]*)/)) {
331
+ return ['return', lMatches[1]];
332
+ } else if (nObjects > 0) {
333
+ return ['objects', undef];
334
+ } else {
335
+ return ['string', undef];
336
+ }
337
+ };
338
+
253
339
  // ---------------------------------------------------------------------------
254
340
  reMethod = /^([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)$/;
255
341
 
@@ -36,9 +36,9 @@ export LOG = (lArgs...) ->
36
36
  if lArgs.length > 1
37
37
  # --- There's both a label and an item
38
38
  if (item == undef)
39
- console.log "#{label}: UNDEFINED"
39
+ console.log "#{label} = undef"
40
40
  else if (item == null)
41
- console.log "#{label}: NULL"
41
+ console.log "#{label} = null"
42
42
  else
43
43
  console.log sep_dash
44
44
  console.log "#{label}:"
package/src/log_utils.js CHANGED
@@ -55,9 +55,9 @@ export var LOG = function(...lArgs) {
55
55
  if (lArgs.length > 1) {
56
56
  // --- There's both a label and an item
57
57
  if (item === undef) {
58
- console.log(`${label}: UNDEFINED`);
58
+ console.log(`${label} = undef`);
59
59
  } else if (item === null) {
60
- console.log(`${label}: NULL`);
60
+ console.log(`${label} = null`);
61
61
  } else {
62
62
  console.log(sep_dash);
63
63
  console.log(`${label}:`);