1
1
2
2
import std/ macros
3
- import ./ frame, ./ funcSignature, ./ decorator, ./ tonim, ./ types
3
+ import ./ frame, ./ funcSignature, ./ decorator, ./ types
4
4
import ./ pydef
5
5
6
6
template emptyn : NimNode = newEmptyNode ()
@@ -159,6 +159,9 @@ func remove1[T](s: var seq[T], x: T) =
159
159
return
160
160
s.delete idx
161
161
162
+ proc rmBase (n: var seq [NimNode ]) =
163
+ n.remove1 ident " base"
164
+
162
165
proc tryPreClsBltinDecorater (mparser: var PyAsgnRewriter ,
163
166
args: var seq [NimNode ], procType: var NimNodeKind ,
164
167
pragmas: var seq [NimNode ], methKind: var MethKind
@@ -208,7 +211,7 @@ then you will find it compile but `O.f()` gives `0` instead of `3`
208
211
]#
209
212
warning " There may be a error like: " &
210
213
" `Error: cannot instantiate: '_`gensymXXX:type'`"
211
- pragmas.remove1 ident " base "
214
+ pragmas.rmBase
212
215
template clsType : NimNode =
213
216
nnkBracketExpr.newTree (ident " typedesc" , curClass ())
214
217
@@ -228,13 +231,29 @@ then you will find it compile but `O.f()` gives `0` instead of `3`
228
231
withType (nnkProcDef)
229
232
return true
230
233
231
- template mkPragma (pragmas: seq [NimNode ]): NimNode =
234
+ template mkPragma (pragmas: openArray [NimNode ]): NimNode =
232
235
if pragmas.len == 0 : emptyn
233
236
else : nnkPragma.newNimNode.add pragmas
234
237
235
- proc genNewCls (classId, generics: NimNode , initArgs, initPragmas: seq [NimNode ]): NimNode =
236
- # # returns decl of `newXxx`
237
- let classNewName = ident (" new" & classId.strVal)
238
+ proc newMethAsProc (name, generics: NimNode , params: openArray [NimNode ], body: NimNode , procType = nnkProcDef, pragmas: openArray [NimNode ]): NimNode =
239
+ let procType = (if procType == nnkMethodDef: nnkProcDef else : procType)
240
+ var pragmas = @ pragmas
241
+ pragmas.rmBase
242
+ newProc (name, generics, params, body, procType, pragmas.mkPragma)
243
+
244
+ proc mkExport (n: NimNode ): NimNode = n.postfix " *"
245
+
246
+ proc newMethProc (topLevel: bool , name, generics: NimNode , params: openArray [NimNode ], body: NimNode , procType = nnkProcDef, pragmas: openArray [NimNode ]): NimNode =
247
+ if topLevel:
248
+ var pragmas = @ pragmas
249
+ pragmas.rmBase
250
+ result = newProc (name.mkExport, generics, params, body, procType, pragmas.mkPragma)
251
+ else :
252
+ result = newMethAsProc (name, generics, params, body, procType, pragmas)
253
+ result .addPragma ident " used"
254
+
255
+ proc genNewCls (topLevel: bool , classNewProcName, classId, generics: NimNode , initArgs, initPragmas: openArray [NimNode ]): NimNode =
256
+ # # returns decl of proc
238
257
var newArgs = @ [classId]
239
258
var body = newStmtList ()
240
259
let resId = ident " result"
@@ -253,11 +272,11 @@ proc genNewCls(classId, generics: NimNode, initArgs, initPragmas: seq[NimNode]):
253
272
body.add newAssignment (resId, nnkObjConstr.newTree (callNew))
254
273
if defInit:
255
274
body.add callInit
256
- var pragmas = initPragmas
257
- pragmas.remove1 ident " base "
258
- newProc (classNewName, generics, newArgs, body, pragmas= pragmas.mkPragma )
275
+ var pragmas = @ initPragmas
276
+ pragmas.rmBase
277
+ newMethProc (topLevel, classNewProcName, generics, newArgs, body, pragmas= pragmas)
259
278
260
- proc classImpl * (parser: var PySyntaxProcesser ; obj, body: NimNode ): NimNode =
279
+ proc classImpl * (parser: var PySyntaxProcesser ; obj, body: NimNode , topLevel = true ): NimNode =
261
280
##[ minic Python's `class`.
262
281
263
282
support `def` for method with nested `def/class` supported
@@ -298,7 +317,6 @@ so if wantting the attr inherited from SupCls, just write it as-is (e.g. `self.a
298
317
var
299
318
classId = obj
300
319
supCls = ident " RootObj"
301
- supClsNode = nnkOfInherit.newTree supCls
302
320
defPragmas = @ [ident " base" ]
303
321
generics = emptyn
304
322
template parseGenerics (n: NimNode ) =
@@ -333,13 +351,16 @@ so if wantting the attr inherited from SupCls, just write it as-is (e.g. `self.a
333
351
elif supLen == 1 :
334
352
# class O(SupCls)
335
353
supCls = supClses[0 ]
336
- if supCls.kind != nnkObjectTy: # not `class O(object)`
337
- supClsNode = nnkOfInherit.newTree supCls
338
- defPragmas.remove1 ident " base"
354
+ if not supCls.eqIdent " RootObj" : # not `class O(object)`
355
+ if not topLevel:
356
+ error " non-topLevel class cannot inherit currently " &
357
+ " (as Nim's method must be top-level)" , obj[1 ]
358
+ defPragmas.rmBase
339
359
of nnkBracketExpr:
340
360
parseGenerics obj
341
361
else :
342
362
error " unexpected class syntax, got: " , obj
363
+ let supClsNode = nnkOfInherit.newTree supCls
343
364
344
365
initSubClassArgs[0 ] = classId
345
366
let className = $ classId
@@ -349,7 +370,10 @@ so if wantting the attr inherited from SupCls, just write it as-is (e.g. `self.a
349
370
for i in generics.items ():
350
371
let g = i[0 ] # g.kind == nnkIdentDef
351
372
genericsClassId.add g
352
-
373
+ template exportIfTop (n: NimNode ): NimNode =
374
+ if topLevel: n.mkExport
375
+ else :
376
+ nnkPragmaExpr.newTree (n, nnkPragma.newTree ident " used" )
353
377
result = newStmtList ()
354
378
parser.classes.add classId
355
379
let dunderDirId = ident className & " .dunder.dict.keys()" # `classId.__dict__.keys()`
@@ -391,7 +415,10 @@ so if wantting the attr inherited from SupCls, just write it as-is (e.g. `self.a
391
415
of nnkCommand: # TODO : support async
392
416
# def a(b, c=1).
393
417
# Other stuff than defines: comments, etc
394
- if not def[0 ].eqIdent " def" :
418
+ if def[0 ].eqIdent " class" :
419
+ result .add parser.classImpl (def[1 ], def[2 ], topLevel= false )
420
+ continue
421
+ elif not def[0 ].eqIdent " def" :
395
422
result .add def
396
423
continue
397
424
let signature = def[1 ]
@@ -458,8 +485,8 @@ so if wantting the attr inherited from SupCls, just write it as-is (e.g. `self.a
458
485
initPragmas = pragmas
459
486
initGenerics = generics_cpy
460
487
let nDef = parser.consumeDecorator (
461
- newProc ( procName, generics_cpy, args, body,
462
- procType, pragmas= pragmas.mkPragma )
488
+ newMethProc (topLevel, procName, generics_cpy, args, body,
489
+ procType, pragmas= pragmas)
463
490
)
464
491
addMeth nDef
465
492
@@ -471,10 +498,10 @@ so if wantting the attr inherited from SupCls, just write it as-is (e.g. `self.a
471
498
else :
472
499
result .add def # AS-IS
473
500
474
- addMeth genNewCls (classId, initGenerics, initArgs, initPragmas)
501
+ addMeth genNewCls (topLevel, ident ( " new " & classId.strVal), classId, initGenerics, initArgs, initPragmas)
475
502
476
503
let ty = nnkRefTy.newTree nnkObjectTy.newTree (emptyn, supClsNode, typDefLs)
477
- let typDef = nnkTypeSection.newTree nnkTypeDef.newTree (classId, generics, ty)
504
+ let typDef = nnkTypeSection.newTree nnkTypeDef.newTree (classId.exportIfTop , generics, ty)
478
505
result .add:
479
506
nnkWhenStmt.newTree (
480
507
nnkElifBranch.newTree (
@@ -491,7 +518,7 @@ so if wantting the attr inherited from SupCls, just write it as-is (e.g. `self.a
491
518
result .add defs
492
519
493
520
result .add newConstStmt (
494
- dunderDirId.postfix " * " , dunderDirVal
521
+ dunderDirId.exportIfTop , dunderDirVal
495
522
)
496
523
let initSub = newCall (" init_subclass" ).add initSubClassArgs
497
524
result .add nnkWhenStmt.newTree (
0 commit comments