3
3
strutils,
4
4
sequtils,
5
5
os,
6
+ nre,
6
7
osproc,
7
8
critbits,
8
9
json,
12
13
import
13
14
baseutils,
14
15
value,
15
- scope,
16
16
parser
17
17
18
18
type
@@ -27,7 +27,8 @@ var COMPILEDMINFILES* {.threadvar.}: CritBitTree[MinOperatorProc]
27
27
var COMPILEDASSETS * {.threadvar .}: CritBitTree [string ]
28
28
var CACHEDMODULES * {.threadvar .}: CritBitTree [MinValue ]
29
29
30
- const USER_SYMBOL_REGEX * = " ^[a-zA-Z_][a-zA-Z0-9/!?+*._-]*$"
30
+ const USER_SYMBOL_REGEX * = " ^[a-zA-Z_][a-zA-Z0-9/!?+*_-]*$"
31
+ const USER_PATH_SYMBOL_REGEX * = " ^[a-zA-Z_][a-zA-Z0-9/.!?+*_-]*$"
31
32
32
33
proc diff * (a, b: seq [MinValue ]): seq [MinValue ] =
33
34
result = newSeq [MinValue ](0 )
@@ -193,7 +194,20 @@ proc copyDict*(i: In, val: MinValue): MinValue =
193
194
194
195
proc apply * (i: In , op: MinOperator , sym = " " ) {.effectsOf : op.} =
195
196
if op.kind == minProcOp:
196
- op.prc (i)
197
+ if not op.mdl.isNil and not op.mdl.scope.isNil and not i.scope.hasParent op.mdl.scope:
198
+ # Capture closures at module level
199
+ let origScope = i.scope
200
+ let origParentScope = i.scope.parent
201
+ let origMdlParentScope = op.mdl.scope.parent
202
+ i.scope = op.mdl.scope
203
+ i.scope.parent = origScope
204
+ i.scope.parent.parent = origParentScope
205
+ op.prc (i)
206
+ i.scope = origScope
207
+ i.scope.parent = origParentScope
208
+ op.mdl.scope.parent = origMdlParentScope
209
+ else :
210
+ op.prc (i)
197
211
else :
198
212
if op.val.kind == minQuotation:
199
213
var newscope = newScopeRef (i.scope)
@@ -237,6 +251,7 @@ proc pop*(i: In): MinValue =
237
251
if i.stack.len > 0 :
238
252
return i.stack.pop
239
253
else :
254
+ debug " pop - empty stack!"
240
255
raiseEmptyStack ()
241
256
242
257
# Inherit file/line/column from current symbol
@@ -262,27 +277,38 @@ proc push*(i: In, val: MinValue) =
262
277
let symbol = val.symVal
263
278
if symbol == " return" :
264
279
raise MinReturnException (msg: " return symbol found" )
265
- if i.scope.hasSymbol (symbol):
266
- i.apply i.scope.getSymbol (symbol), symbol
280
+ i.debug (" push: $#" % [symbol])
281
+ let op = i.scope.getSymbol (symbol)
282
+ if not op.isNull:
283
+ i.debug (" push: symbol found: $#" % [symbol])
284
+ i.apply op, symbol
267
285
else :
268
286
# Check if symbol ends with ! (auto-popping)
269
287
if symbol.len > 1 and symbol[symbol.len- 1 ] == '!' :
288
+ i.debug (" push - checking auto-popping symbol: $#" % [symbol])
270
289
let apSymbol = symbol[0 .. symbol.len- 2 ]
271
- if i.scope.hasSymbol (apSymbol):
272
- i.apply i.scope.getSymbol (apSymbol)
290
+ let apOp = i.scope.getSymbol (apSymbol)
291
+ if not apOp.isNull:
292
+ i.apply apOp
273
293
discard i.pop
274
294
else :
295
+ i.debug (" push - checking sigil: $#" % [symbol])
296
+ # Check user-defined sigil
275
297
var qIndex = symbol.find ('"' )
276
298
if qIndex > 0 :
277
299
let sigil = symbol[0 .. qIndex- 1 ]
300
+ i.debug (" push - checking user sigil: $#" % [sigil])
278
301
if not i.scope.hasSigil (sigil):
279
302
raiseUndefined (" Undefined sigil '$1'" % sigil)
280
303
i.stack.add (MinValue (kind: minString, strVal: symbol[
281
304
qIndex+ 1 .. symbol.len- 2 ]))
282
305
i.apply (i.scope.getSigil (sigil))
283
306
else :
307
+ # Check system sigil
284
308
let sigil = " " & symbol[0 ]
309
+ i.debug (" push - checking system sigil: $#" % [sigil])
285
310
if symbol.len > 1 and i.scope.hasSigil (sigil):
311
+ i.debug (" Processing sigil: $# ($#)" % [sigil, symbol])
286
312
i.stack.add (MinValue (kind: minString, strVal: symbol[
287
313
1 .. symbol.len- 1 ]))
288
314
i.apply (i.scope.getSigil (sigil))
@@ -304,6 +330,7 @@ proc peek*(i: MinInterpreter): MinValue =
304
330
if i.stack.len > 0 :
305
331
return i.stack[i.stack.len- 1 ]
306
332
else :
333
+ debug " peek - empty stack!"
307
334
raiseEmptyStack ()
308
335
309
336
template handleErrors * (i: In , body: untyped ) =
@@ -369,6 +396,8 @@ proc initCompiledFile*(i: In, files: seq[string]): seq[string] {.discardable.} =
369
396
result .add " import critbits"
370
397
if ASSETPATH != " " :
371
398
result .add " import base64"
399
+ result .add " import logging"
400
+ result .add " logging.setLogFilter(logging.lvlNotice)"
372
401
result .add " MINCOMPILED = true"
373
402
result .add " var i = newMinInterpreter(\" $#\" )" % i.filename
374
403
result .add " i.stdLib()"
@@ -436,7 +465,10 @@ proc require*(i: In, s: string, parseOnly = false): MinValue {.discardable.} =
436
465
result = newDict (i2.scope)
437
466
result .objType = " module"
438
467
for key, value in i2.scope.symbols.pairs:
439
- result .scope.symbols[key] = value
468
+ var v = value
469
+ if v.kind == minProcOp:
470
+ v.mdl = result
471
+ result .scope.symbols[key] = v
440
472
CACHEDMODULES [s] = result
441
473
442
474
proc parse * (i: In , s: string , name = " <parse>" ): MinValue =
0 commit comments