summary refs log tree commit diff stats
path: root/compiler/expanddefaults.nim
blob: c520d8849f2dbeee7901ce235b2eb9bdb58b5724 (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
#
#
#           The Nim Compiler
#        (c) Copyright 2023 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

import lineinfos, ast, types

proc caseObjDefaultBranch*(obj: PNode; branch: Int128): int =
  result = 0
  for i in 1 ..< obj.len:
    for j in 0 .. obj[i].len - 2:
      if obj[i][j].kind == nkRange:
        let x = getOrdValue(obj[i][j][0])
        let y = getOrdValue(obj[i][j][1])
        if branch >= x and branch <= y:
          return i
      elif getOrdValue(obj[i][j]) == branch:
        return i
    if obj[i].len == 1:
      # else branch
      return i
  return 1

template newZero(t: PType; info: TLineInfo; k = nkIntLit): PNode = newNodeIT(k, info, t)

proc expandDefault*(t: PType; info: TLineInfo): PNode

proc expandField(s: PSym; info: TLineInfo): PNode =
  result = newNodeIT(nkExprColonExpr, info, s.typ)
  result.add newSymNode(s)
  result.add expandDefault(s.typ, info)

proc expandDefaultN(n: PNode; info: TLineInfo; res: PNode) =
  case n.kind
  of nkRecList:
    for i in 0..<n.len:
      expandDefaultN(n[i], info, res)
  of nkRecCase:
    res.add expandField(n[0].sym, info)
    var branch = Zero
    let constOrNil = n[0].sym.astdef
    if constOrNil != nil:
      branch = getOrdValue(constOrNil)

    let selectedBranch = caseObjDefaultBranch(n, branch)
    let b = lastSon(n[selectedBranch])
    expandDefaultN b, info, res
  of nkSym:
    res.add expandField(n.sym, info)
  else:
    discard

proc expandDefaultObj(t: PType; info: TLineInfo; res: PNode) =
  if t.baseClass != nil:
    expandDefaultObj(t.baseClass, info, res)
  expandDefaultN(t.n, info, res)

proc expandDefault(t: PType; info: TLineInfo): PNode =
  case t.kind
  of tyInt:     result = newZero(t, info, nkIntLit)
  of tyInt8:    result = newZero(t, info, nkInt8Lit)
  of tyInt16:   result = newZero(t, info, nkInt16Lit)
  of tyInt32:   result = newZero(t, info, nkInt32Lit)
  of tyInt64:   result = newZero(t, info, nkInt64Lit)
  of tyUInt:    result = newZero(t, info, nkUIntLit)
  of tyUInt8:   result = newZero(t, info, nkUInt8Lit)
  of tyUInt16:  result = newZero(t, info, nkUInt16Lit)
  of tyUInt32:  result = newZero(t, info, nkUInt32Lit)
  of tyUInt64:  result = newZero(t, info, nkUInt64Lit)
  of tyFloat:   result = newZero(t, info, nkFloatLit)
  of tyFloat32: result = newZero(t, info, nkFloat32Lit)
  of tyFloat64: result = newZero(t, info, nkFloat64Lit)
  of tyFloat128: result = newZero(t, info, nkFloat64Lit)
  of tyChar:    result = newZero(t, info, nkCharLit)
  of tyBool:    result = newZero(t, info, nkIntLit)
  of tyEnum:
    # Could use low(T) here to finally fix old language quirks
    result = newZero(t, info, nkIntLit)
  of tyRange:
    # Could use low(T) here to finally fix old language quirks
    result = expandDefault(skipModifier t, info)
  of tyVoid: result = newZero(t, info, nkEmpty)
  of tySink, tyGenericInst, tyDistinct, tyAlias, tyOwned:
    result = expandDefault(t.skipModifier, info)
  of tyOrdinal, tyGenericBody, tyGenericParam, tyInferred, tyStatic:
    if t.hasElementType:
      result = expandDefault(t.skipModifier, info)
    else:
      result = newZero(t, info, nkEmpty)
  of tyFromExpr:
    if t.n != nil and t.n.typ != nil:
      result = expandDefault(t.n.typ, info)
    else:
      result = newZero(t, info, nkEmpty)
  of tyArray:
    result = newZero(t, info, nkBracket)
    let n = toInt64(lengthOrd(nil, t))
    for i in 0..<n:
      result.add expandDefault(t.elementType, info)
  of tyPtr, tyRef, tyProc, tyPointer, tyCstring:
    result = newZero(t, info, nkNilLit)
  of tyVar, tyLent:
    let e = t.elementType
    if e.skipTypes(abstractInst).kind in {tyOpenArray, tyVarargs}:
      # skip the modifier, `var openArray` is a (ptr, len) pair too:
      result = expandDefault(e, info)
    else:
      result = newZero(e, info, nkNilLit)
  of tySet:
    result = newZero(t, info, nkCurly)
  of tyObject:
    result = newNodeIT(nkObjConstr, info, t)
    result.add newNodeIT(nkType, info, t)
    expandDefaultObj(t, info, result)
  of tyTuple:
    result = newZero(t, info, nkTupleConstr)
    for it in t.kids:
      result.add expandDefault(it, info)
  of tyVarargs, tyOpenArray, tySequence, tyUncheckedArray:
    result = newZero(t, info, nkBracket)
  of tyString:
    result = newZero(t, info, nkStrLit)
  of tyNone, tyEmpty, tyUntyped, tyTyped, tyTypeDesc,
     tyNil, tyGenericInvocation, tyError, tyBuiltInTypeClass,
     tyUserTypeClass, tyUserTypeClassInst, tyCompositeTypeClass,
     tyAnd, tyOr, tyNot, tyAnything, tyConcept, tyIterable, tyForward:
    result = newZero(t, info, nkEmpty) # bug indicator