summary refs log tree commit diff stats
path: root/rod/transtmp.nim
blob: 44a462feaa7d8bcd89f292477829290f1bdbf71a (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
#
#
#           The Nimrod Compiler
#        (c) Copyright 2008 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#
# This module implements a transformator. It transforms the syntax tree 
# to ease the work of the code generators. Does the transformation to 
# introduce temporaries to split up complex expressions.
# THIS MODULE IS NOT USED!

proc transInto(c: PContext, dest: var PNode, father, src: PNode)
  # transforms the expression `src` into the destination `dest`. Uses `father`
  # for temorary statements. If dest = nil, the expression is put into a 
  # temporary.
proc transTmp(c: PContext, father, src: PNode): PNode = 
  # convienence proc
  result = nil
  transInto(c, result, father, src)

proc newLabel(c: PContext): PSym = 
  inc(gTmpId)
  result = newSym(skLabel, getIdent(genPrefix & $(gTmpId), c.transCon.owner))

proc fewCmps(s: PNode): bool = 
  # this function estimates whether it is better to emit code
  # for constructing the set or generating a bunch of comparisons directly
  assert(s.kind in {nkSetConstr, nkConstSetConstr})
  if (s.typ.size <= platform.intSize) and (s.kind == nkConstSetConstr): 
    result = false            # it is better to emit the set generation code
  elif skipRange(s.typ.sons[0]).Kind in {tyInt..tyInt64}: 
    result = true             # better not emit the set if int is basetype!
  else: 
    result = sonsLen(s) <=
        8                     # 8 seems to be a good value
  
proc transformIn(c: PContext, father, n: PNode): PNode = 
  var 
    a, b, e, setc: PNode
    destLabel, label2: PSym
  if (n.sons[1].kind == nkSetConstr) and fewCmps(n.sons[1]): 
    # a set constructor but not a constant set:
    # do not emit the set, but generate a bunch of comparisons
    result = newSymNode(newTemp(c, n.typ, n.info))
    e = transTmp(c, father, n.sons[2])
    setc = n.sons[1]
    destLabel = newLabel(c)
    for i in countup(0, sonsLen(setc) - 1): 
      if setc.sons[i].kind == nkRange: 
        a = transTmp(c, father, setc.sons[i].sons[0])
        b = transTmp(c, father, setc.sons[i].sons[1])
        label2 = newLabel(c)
        addSon(father, newLt(result, e, a)) # e < a? --> goto end
        addSon(father, newCondJmp(result, label2))
        addSon(father, newLe(result, e, b)) # e <= b? --> goto set end
        addSon(father, newCondJmp(result, destLabel))
        addSon(father, newLabelNode(label2))
      else: 
        a = transTmp(c, father, setc.sons[i])
        addSon(father, newEq(result, e, a))
        addSon(father, newCondJmp(result, destLabel))
    addSon(father, newLabelNode(destLabel))
  else: 
    result = n

proc transformOp2(c: PContext, dest: var PNode, father, n: PNode) = 
  var a, b: PNode
  if dest == nil: dest = newSymNode(newTemp(c, n.typ, n.info))
  a = transTmp(c, father, n.sons[1])
  b = transTmp(c, father, n.sons[2])
  addSon(father, newAsgnStmt(dest, newOp2(n, a, b)))

proc transformOp1(c: PContext, dest: var PNode, father, n: PNode) = 
  var a: PNode
  if dest == nil: dest = newSymNode(newTemp(c, n.typ, n.info))
  a = transTmp(c, father, n.sons[1])
  addSon(father, newAsgnStmt(dest, newOp1(n, a)))

proc genTypeInfo(c: PContext, initSection: PNode) = 
  nil

proc genNew(c: PContext, father, n: PNode) = 
  # how do we handle compilerprocs?
  
proc transformCase(c: PContext, father, n: PNode): PNode = 
  var 
    ty: PType
    e: PNode
  ty = skipGeneric(n.sons[0].typ)
  if ty.kind == tyString: 
    # transform a string case to a bunch of comparisons:
    result = newNodeI(nkIfStmt, n)
    e = transTmp(c, father, n.sons[0])
  else: 
    result = n
  
proc transInto(c: PContext, dest: var PNode, father, src: PNode) = 
  if src == nil: return 
  if (src.typ != nil) and (src.typ.kind == tyGenericInst): 
    src.typ = skipGeneric(src.typ)
  case src.kind
  of nkIdent..nkNilLit: 
    if dest == nil: 
      dest = copyTree(src)
    else: 
      # generate assignment:
      addSon(father, newAsgnStmt(dest, src))
  of nkCall, nkCommand, nkCallStrLit: 
    nil