new js codegen: bugfixes

This commit is contained in:
Araq 2013-04-30 09:48:21 +02:00
commit d64d6a70d4

View file

@ -161,7 +161,7 @@ proc makeJSString(s: string): PRope = strutils.escape(s).toRope
include jstypes include jstypes
proc gen(p: PProc, n: PNode, r: var TCompRes) proc gen(p: PProc, n: PNode, r: var TCompRes)
proc genStmt(p: PProc, n: PNode, r: var TCompRes) proc genStmt(p: PProc, n: PNode)
proc genProc(oldProc: PProc, prc: PSym): PRope proc genProc(oldProc: PProc, prc: PSym): PRope
proc genConstant(p: PProc, c: PSym) proc genConstant(p: PProc, c: PSym)
@ -387,7 +387,7 @@ proc genLineDir(p: PProc, n: PNode) =
proc genWhileStmt(p: PProc, n: PNode) = proc genWhileStmt(p: PProc, n: PNode) =
var var
cond, stmt: TCompRes cond: TCompRes
internalAssert isEmptyType(n.typ) internalAssert isEmptyType(n.typ)
genLineDir(p, n) genLineDir(p, n)
inc(p.unique) inc(p.unique)
@ -400,15 +400,16 @@ proc genWhileStmt(p: PProc, n: PNode) =
gen(p, n.sons[0], cond) gen(p, n.sons[0], cond)
appf(p.body, "if (!$1) break L$2;$n" | "if not $1 then goto ::L$2:: end;$n", appf(p.body, "if (!$1) break L$2;$n" | "if not $1 then goto ::L$2:: end;$n",
[cond.res, labl]) [cond.res, labl])
genStmt(p, n.sons[1], stmt) genStmt(p, n.sons[1])
internalAssert stmt.res.isNil
appf(p.body, "}$n" | "end$n", []) appf(p.body, "}$n" | "end$n", [])
setlen(p.blocks, length) setlen(p.blocks, length)
proc moveInto(p: PProc, src: var TCompRes, dest: TCompRes) = proc moveInto(p: PProc, src: var TCompRes, dest: TCompRes) =
if src.kind != resNone: if src.kind != resNone:
assert dest.kind != resNone if dest.kind != resNone:
p.body.appf("$1 = $2;$n", dest.rdLoc, src.rdLoc) p.body.appf("$1 = $2;$n", dest.rdLoc, src.rdLoc)
else:
p.body.appf("$1;$n", src.rdLoc)
src.kind = resNone src.kind = resNone
src.res = nil src.res = nil
@ -442,11 +443,11 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
app(p.body, "try {" & tnl) app(p.body, "try {" & tnl)
var length = sonsLen(n) var length = sonsLen(n)
var a: TCompRes var a: TCompRes
genStmt(p, n.sons[0], a) gen(p, n.sons[0], a)
if not isEmptyType(n.typ): if not isEmptyType(n.typ):
r.kind = resVal r.kind = resVal
r.res = getTemp(p) r.res = getTemp(p)
moveInto(p, a, r) moveInto(p, a, r)
var i = 1 var i = 1
if length > 1 and n.sons[i].kind == nkExceptBranch: if length > 1 and n.sons[i].kind == nkExceptBranch:
appf(p.body, "} catch (EXC) {$n") appf(p.body, "} catch (EXC) {$n")
@ -455,7 +456,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
if blen == 1: if blen == 1:
# general except section: # general except section:
if i > 1: app(p.body, "else {" & tnl) if i > 1: app(p.body, "else {" & tnl)
genStmt(p, n.sons[i].sons[0], a) gen(p, n.sons[i].sons[0], a)
moveInto(p, a, r) moveInto(p, a, r)
if i > 1: app(p.body, '}' & tnl) if i > 1: app(p.body, '}' & tnl)
else: else:
@ -469,13 +470,13 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
[safePoint, genTypeInfo(p, n.sons[i].sons[j].typ)]) [safePoint, genTypeInfo(p, n.sons[i].sons[j].typ)])
if i > 1: app(p.body, "else ") if i > 1: app(p.body, "else ")
appf(p.body, "if ($1.exc && ($2)) {$n", [safePoint, orExpr]) appf(p.body, "if ($1.exc && ($2)) {$n", [safePoint, orExpr])
genStmt(p, n.sons[i].sons[blen - 1], a) gen(p, n.sons[i].sons[blen - 1], a)
moveInto(p, a, r) moveInto(p, a, r)
appf(p.body, "}$n") appf(p.body, "}$n")
inc(i) inc(i)
app(p.body, "} finally {" & tnl & "excHandler = excHandler.prev;" & tnl) app(p.body, "} finally {" & tnl & "excHandler = excHandler.prev;" & tnl)
if i < length and n.sons[i].kind == nkFinally: if i < length and n.sons[i].kind == nkFinally:
genStmt(p, n.sons[i].sons[0], a) gen(p, n.sons[i].sons[0], a)
moveInto(p, a, r) moveInto(p, a, r)
app(p.body, '}' & tnl) app(p.body, '}' & tnl)
@ -527,12 +528,12 @@ proc genCase(p: PProc, n: PNode, r: var TCompRes) =
else: else:
gen(p, e, cond) gen(p, e, cond)
appf(p.body, "case $1: ", [cond.rdLoc]) appf(p.body, "case $1: ", [cond.rdLoc])
genStmt(p, lastSon(it), stmt) gen(p, lastSon(it), stmt)
moveInto(p, stmt, r) moveInto(p, stmt, r)
appf(p.body, "$nbreak;$n") appf(p.body, "$nbreak;$n")
of nkElse: of nkElse:
appf(p.body, "default: $n") appf(p.body, "default: $n")
genStmt(p, it.sons[0], stmt) gen(p, it.sons[0], stmt)
moveInto(p, stmt, r) moveInto(p, stmt, r)
appf(p.body, "break;$n") appf(p.body, "break;$n")
else: internalError(it.info, "jsgen.genCaseStmt") else: internalError(it.info, "jsgen.genCaseStmt")
@ -554,7 +555,7 @@ proc genBlock(p: PProc, n: PNode, r: var TCompRes) =
p.blocks[idx].id = - p.unique # negative because it isn't used yet p.blocks[idx].id = - p.unique # negative because it isn't used yet
labl = p.unique labl = p.unique
appf(p.body, "L$1: do {$n", toRope(labl)) appf(p.body, "L$1: do {$n", toRope(labl))
genStmt(p, n.sons[1], r) gen(p, n.sons[1], r)
appf(p.body, "} while(false);$n") appf(p.body, "} while(false);$n")
setlen(p.blocks, idx) setlen(p.blocks, idx)
@ -599,11 +600,11 @@ proc genIf(p: PProc, n: PNode, r: var TCompRes) =
inc(toClose) inc(toClose)
gen(p, it.sons[0], cond) gen(p, it.sons[0], cond)
appf(p.body, "if ($1) {$n", cond.rdLoc) appf(p.body, "if ($1) {$n", cond.rdLoc)
genStmt(p, it.sons[1], stmt) gen(p, it.sons[1], stmt)
else: else:
# else part: # else part:
appf(p.body, "else {$n") appf(p.body, "else {$n")
genStmt(p, it.sons[0], stmt) gen(p, it.sons[0], stmt)
moveInto(p, stmt, r) moveInto(p, stmt, r)
appf(p.body, "}$n") appf(p.body, "}$n")
app(p.body, repeatChar(toClose, '}') & tnl) app(p.body, repeatChar(toClose, '}') & tnl)
@ -1284,11 +1285,10 @@ proc convCStrToStr(p: PProc, n: PNode, r: var TCompRes) =
r.kind = resExpr r.kind = resExpr
proc genReturnStmt(p: PProc, n: PNode) = proc genReturnStmt(p: PProc, n: PNode) =
var a: TCompRes
if p.procDef == nil: InternalError(n.info, "genReturnStmt") if p.procDef == nil: InternalError(n.info, "genReturnStmt")
p.BeforeRetNeeded = true p.BeforeRetNeeded = true
if (n.sons[0].kind != nkEmpty): if (n.sons[0].kind != nkEmpty):
genStmt(p, n.sons[0], a) genStmt(p, n.sons[0])
else: else:
genLineDir(p, n) genLineDir(p, n)
app(p.body, "break BeforeRet;" & tnl) app(p.body, "break BeforeRet;" & tnl)
@ -1314,7 +1314,7 @@ proc genProc(oldProc: PProc, prc: PSym): PRope =
var var
resultSym: PSym resultSym: PSym
name, returnStmt, resultAsgn, header: PRope name, returnStmt, resultAsgn, header: PRope
a, r: TCompRes a: TCompRes
#if gVerbosity >= 3: #if gVerbosity >= 3:
# echo "BEGIN generating code for: " & prc.name.s # echo "BEGIN generating code for: " & prc.name.s
var p = newProc(oldProc.g, oldProc.module, prc.ast, prc.options) var p = newProc(oldProc.g, oldProc.module, prc.ast, prc.options)
@ -1330,16 +1330,17 @@ proc genProc(oldProc: PProc, prc: PSym): PRope =
createVar(p, resultSym.typ, isIndirect(resultSym))]) createVar(p, resultSym.typ, isIndirect(resultSym))])
gen(p, prc.ast.sons[resultPos], a) gen(p, prc.ast.sons[resultPos], a)
returnStmt = ropef("return $#;$n", [a.res]) returnStmt = ropef("return $#;$n", [a.res])
genStmt(p, prc.getBody, r) genStmt(p, prc.getBody)
if r.res != nil: app(p.body, r.res)
result = ropef("function $#($#) {$n$#$#$#$#}$n", result = ropef("function $#($#) {$n$#$#$#$#}$n",
[name, header, p.locals, resultAsgn, [name, header, p.locals, resultAsgn,
genProcBody(p, prc), returnStmt]) genProcBody(p, prc), returnStmt])
#if gVerbosity >= 3: #if gVerbosity >= 3:
# echo "END generated code for: " & prc.name.s # echo "END generated code for: " & prc.name.s
proc genStmt(p: PProc, n: PNode, r: var TCompRes) = proc genStmt(p: PProc, n: PNode) =
var r: TCompRes
gen(p, n, r) gen(p, n, r)
if r.res != nil: appf(p.body, "$#;$n", r.res)
proc gen(p: PProc, n: PNode, r: var TCompRes) = proc gen(p: PProc, n: PNode, r: var TCompRes) =
r.typ = etyNone r.typ = etyNone
@ -1415,15 +1416,10 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
# this shows the distinction is nice for backends and should be kept # this shows the distinction is nice for backends and should be kept
# in the frontend # in the frontend
let isExpr = not isEmptyType(n.typ) let isExpr = not isEmptyType(n.typ)
var a: TCompRes
for i in countup(0, sonsLen(n) - 1 - isExpr.ord): for i in countup(0, sonsLen(n) - 1 - isExpr.ord):
a.res = nil genStmt(p, n.sons[i])
genStmt(p, n.sons[i], a)
if a.res != nil:
app(p.body, a.res)
app(p.body, ";" & tnl)
if isExpr: if isExpr:
genStmt(p, lastSon(n), r) gen(p, lastSon(n), r)
of nkBlockStmt, nkBlockExpr: genBlock(p, n, r) of nkBlockStmt, nkBlockExpr: genBlock(p, n, r)
of nkIfStmt, nkIfExpr: genIf(p, n, r) of nkIfStmt, nkIfExpr: genIf(p, n, r)
of nkWhileStmt: genWhileStmt(p, n) of nkWhileStmt: genWhileStmt(p, n)
@ -1474,10 +1470,7 @@ proc genModule(p: PProc, n: PNode) =
"framePtr = F;$n", [ "framePtr = F;$n", [
makeJSString("module " & p.module.module.name.s), makeJSString("module " & p.module.module.name.s),
makeJSString(toFilename(p.module.module.info))]) makeJSString(toFilename(p.module.module.info))])
var r: TCompRes genStmt(p, n)
genStmt(p, n, r)
if r.res != nil:
appf(p.body, "$#;$n", r.res)
if optStackTrace in p.options: if optStackTrace in p.options:
appf(p.body, "framePtr = framePtr.prev;$n") appf(p.body, "framePtr = framePtr.prev;$n")