summary refs log tree commit diff stats
path: root/nim/transtmp.pas
blob: 15a07f5a2001d41ec1282121fe5c130bcb6ac50e (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
137
138
139
140
141
142
143
144
145
146
147
148
149
//
//
//           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!

procedure transInto(c: PContext; var dest: PNode; father, src: PNode); forward;
// transforms the expression `src` into the destination `dest`. Uses `father`
// for temorary statements. If dest = nil, the expression is put into a 
// temporary.

function transTmp(c: PContext; father, src: PNode): PNode; 
// convienence proc
begin
  result := nil;
  transInto(c, result, father, src);
end;

function newLabel(c: PContext): PSym;
begin
  inc(gTmpId);
  result := newSym(skLabel, getIdent(genPrefix +{&} ToString(gTmpId), 
                   c.transCon.owner));
end;

function 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
begin
  assert(s.kind in [nkSetConstr, nkConstSetConstr]);
  if (s.typ.size <= platform.intSize) and
      (s.kind = nkConstSetConstr) then
    result := false      // it is better to emit the set generation code
  else if skipRange(s.typ.sons[0]).Kind in [tyInt..tyInt64] then
    result := true       // better not emit the set if int is basetype!
  else
    result := sonsLen(s) <= 8 // 8 seems to be a good value
end;

function transformIn(c: PContext; father, n: PNode): PNode;
var
  a, b, e, setc: PNode;
  destLabel, label2: PSym;
begin
  if (n.sons[1].kind = nkSetConstr) and fewCmps(n.sons[1]) then begin
    // 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 := 0 to sonsLen(setc)-1 do begin
      if setc.sons[i].kind = nkRange then begin
        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));
      end
      else begin
        a := transTmp(c, father, setc.sons[i]);
        addSon(father, newEq(result, e, a));
        addSon(father, newCondJmp(result, destLabel));
      end
    end;
    addSon(father, newLabelNode(destLabel));
  end
  else begin
    result := n;
  end
end;

procedure transformOp2(c: PContext; var dest: PNode; father, n: PNode);
var
  a, b: PNode;
begin
  if dest = nil then 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)));
end;

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

procedure genTypeInfo(c: PContext; initSection: PNode);
begin
  
end;

procedure genNew(c: PContext; father, n: PNode);
begin
  // how do we handle compilerprocs?
  
end;

function transformCase(c: PContext; father, n: PNode): PNode;
var
  ty: PType;
  e: PNode;
begin
  ty := skipGeneric(n.sons[0].typ);
  if ty.kind = tyString then begin
    // transform a string case to a bunch of comparisons:
    result := newNodeI(nkIfStmt, n);
    e := transTmp(c, father, n.sons[0]);
    
  end
  else result := n
end;


procedure transInto(c: PContext; var dest: PNode; father, src: PNode); 
begin
  if src = nil then exit;
  if (src.typ <> nil) and (src.typ.kind = tyGenericInst) then 
    src.typ := skipGeneric(src.typ);
  case src.kind of 
    nkIdent..nkNilLit: begin
      if dest = nil then dest := copyTree(src)
      else begin
        // generate assignment:
        addSon(father, newAsgnStmt(dest, src));
      end
    end;
    nkCall, nkCommand, nkCallStrLit: begin
    
    end;
    
  
  end;
end;