diff options
Diffstat (limited to 'rod/transtmp.nim')
-rwxr-xr-x | rod/transtmp.nim | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/rod/transtmp.nim b/rod/transtmp.nim new file mode 100755 index 000000000..44a462fea --- /dev/null +++ b/rod/transtmp.nim @@ -0,0 +1,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 |