summary refs log tree commit diff stats
path: root/compiler/plugins/customast.nim
blob: 87461ae39222f887a08abb03881a0f5d1eefe633 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# This file exists to make it overridable via
# patchFile("plugins", "customast.nim", "customast.nim")

## This also serves as a blueprint for a possible implementation.

import "$nim" / compiler / [lineinfos, idents]

when defined(nimPreviewSlimSystem):
  import std/assertions

import "$nim" / compiler / nodekinds
export nodekinds

type
  PNode* = ref TNode
  TNode*{.final, acyclic.} = object
    case kind*: TNodeKind
    of nkCharLit..nkUInt64Lit:
      intVal: BiggestInt
    of nkFloatLit..nkFloat128Lit:
      floatVal: BiggestFloat
    of nkStrLit..nkTripleStrLit:
      strVal: string
    of nkSym:
      discard
    of nkIdent:
      ident: PIdent
    else:
      son, next, last: PNode # linked structure instead of a `seq`
    info*: TLineInfo

const
  bodyPos* = 6
  paramsPos* = 3

proc comment*(n: PNode): string =
  result = ""

proc `comment=`*(n: PNode, a: string) =
  discard "XXX implement me"

proc add*(father, son: PNode) =
  assert son != nil
  if father.son == nil:
    father.son = son
    father.last = son
  else:
    father.last.next = son
    father.last = son

template firstSon*(n: PNode): PNode = n.son
template secondSon*(n: PNode): PNode = n.son.next

proc replaceFirstSon*(n, newson: PNode) {.inline.} =
  let old = n.son
  n.son = newson
  newson.next = old

proc replaceSon*(n: PNode; i: int; newson: PNode) =
  assert i > 0
  assert newson.next == nil
  var i = i
  var it = n.son
  while i > 0:
    it = it.next
    dec i
  let old = it.next
  it.next = newson
  newson.next = old

template newNodeImpl(info2) =
  result = PNode(kind: kind, info: info2)

proc newNode*(kind: TNodeKind): PNode =
  ## new node with unknown line info, no type, and no children
  newNodeImpl(unknownLineInfo)

proc newNode*(kind: TNodeKind, info: TLineInfo): PNode =
  ## new node with line info, no type, and no children
  newNodeImpl(info)

proc newTree*(kind: TNodeKind; info: TLineInfo; child: PNode): PNode =
  result = newNode(kind, info)
  result.son = child

proc newAtom*(ident: PIdent, info: TLineInfo): PNode =
  result = newNode(nkIdent)
  result.ident = ident
  result.info = info

proc newAtom*(kind: TNodeKind, intVal: BiggestInt, info: TLineInfo): PNode =
  result = newNode(kind, info)
  result.intVal = intVal

proc newAtom*(kind: TNodeKind, floatVal: BiggestFloat, info: TLineInfo): PNode =
  result = newNode(kind, info)
  result.floatVal = floatVal

proc newAtom*(kind: TNodeKind; strVal: sink string; info: TLineInfo): PNode =
  result = newNode(kind, info)
  result.strVal = strVal

proc lastSon*(n: PNode): PNode {.inline.} = n.last
proc setLastSon*(n: PNode, s: PNode) =
  assert s.next == nil
  n.last = s
  if n.son == nil: n.son = s

proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
                 params,
                 name, pattern, genericParams,
                 pragmas, exceptions: PNode): PNode =
  result = newNode(kind, info)
  result.add name
  result.add pattern
  result.add genericParams
  result.add params
  result.add pragmas
  result.add exceptions
  result.add body

template transitionNodeKindCommon(k: TNodeKind) =
  let obj {.inject.} = n[]
  n[] = TNode(kind: k, info: obj.info)
  # n.comment = obj.comment # shouldn't be needed, the address doesnt' change

proc transitionSonsKind*(n: PNode, kind: range[nkComesFrom..nkTupleConstr]) =
  transitionNodeKindCommon(kind)
  n.son = obj.son

template hasSon*(n: PNode): bool = n.son != nil
template has2Sons*(n: PNode): bool = n.son != nil and n.son.next != nil

proc isNewStyleConcept*(n: PNode): bool {.inline.} =
  assert n.kind == nkTypeClassTy
  result = n.firstSon.kind == nkEmpty