// // // 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;