next steps to a luajit codegen
This commit is contained in:
parent
2ec3e6b49e
commit
fa062ca0c4
1 changed files with 252 additions and 75 deletions
|
|
@ -7,7 +7,7 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
# This is the EMCAScript (also known as JavaScript) code generator.
|
# This is the JavaScript code generator.
|
||||||
# Soon also a Luajit code generator. ;-)
|
# Soon also a Luajit code generator. ;-)
|
||||||
|
|
||||||
import
|
import
|
||||||
|
|
@ -70,7 +70,7 @@ type
|
||||||
blocks: seq[TBlock]
|
blocks: seq[TBlock]
|
||||||
up: PProc # up the call chain; required for closure support
|
up: PProc # up the call chain; required for closure support
|
||||||
|
|
||||||
template `|`(a, b: expr): expr {.immediate.} =
|
template `|`(a, b: expr): expr {.immediate, dirty.} =
|
||||||
(if p.target == targetJS: a else: b)
|
(if p.target == targetJS: a else: b)
|
||||||
|
|
||||||
proc newGlobals(): PGlobals =
|
proc newGlobals(): PGlobals =
|
||||||
|
|
@ -241,9 +241,10 @@ proc genOr(p: PProc, a, b: PNode, r: var TCompRes) =
|
||||||
|
|
||||||
type
|
type
|
||||||
TMagicFrmt = array[0..3, string]
|
TMagicFrmt = array[0..3, string]
|
||||||
|
TMagicOps = array[mAddi..mStrToStr, TMagicFrmt]
|
||||||
|
|
||||||
const # magic checked op; magic unchecked op; checked op; unchecked op
|
const # magic checked op; magic unchecked op; checked op; unchecked op
|
||||||
ops: array[mAddi..mStrToStr, TMagicFrmt] = [
|
jsOps: TMagicOps = [
|
||||||
["addInt", "", "addInt($1, $2)", "($1 + $2)"], # AddI
|
["addInt", "", "addInt($1, $2)", "($1 + $2)"], # AddI
|
||||||
["subInt", "", "subInt($1, $2)", "($1 - $2)"], # SubI
|
["subInt", "", "subInt($1, $2)", "($1 - $2)"], # SubI
|
||||||
["mulInt", "", "mulInt($1, $2)", "($1 * $2)"], # MulI
|
["mulInt", "", "mulInt($1, $2)", "($1 * $2)"], # MulI
|
||||||
|
|
@ -343,6 +344,106 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
|
||||||
["cstrToNimstr", "cstrToNimstr", "cstrToNimstr($1)", "cstrToNimstr($1)"],
|
["cstrToNimstr", "cstrToNimstr", "cstrToNimstr($1)", "cstrToNimstr($1)"],
|
||||||
["", "", "$1", "$1"]]
|
["", "", "$1", "$1"]]
|
||||||
|
|
||||||
|
luaOps: TMagicOps = [
|
||||||
|
["addInt", "", "addInt($1, $2)", "($1 + $2)"], # AddI
|
||||||
|
["subInt", "", "subInt($1, $2)", "($1 - $2)"], # SubI
|
||||||
|
["mulInt", "", "mulInt($1, $2)", "($1 * $2)"], # MulI
|
||||||
|
["divInt", "", "divInt($1, $2)", "Math.floor($1 / $2)"], # DivI
|
||||||
|
["modInt", "", "modInt($1, $2)", "Math.floor($1 % $2)"], # ModI
|
||||||
|
["addInt64", "", "addInt64($1, $2)", "($1 + $2)"], # AddI64
|
||||||
|
["subInt64", "", "subInt64($1, $2)", "($1 - $2)"], # SubI64
|
||||||
|
["mulInt64", "", "mulInt64($1, $2)", "($1 * $2)"], # MulI64
|
||||||
|
["divInt64", "", "divInt64($1, $2)", "Math.floor($1 / $2)"], # DivI64
|
||||||
|
["modInt64", "", "modInt64($1, $2)", "Math.floor($1 % $2)"], # ModI64
|
||||||
|
["", "", "($1 + $2)", "($1 + $2)"], # AddF64
|
||||||
|
["", "", "($1 - $2)", "($1 - $2)"], # SubF64
|
||||||
|
["", "", "($1 * $2)", "($1 * $2)"], # MulF64
|
||||||
|
["", "", "($1 / $2)", "($1 / $2)"], # DivF64
|
||||||
|
["", "", "($1 >>> $2)", "($1 >>> $2)"], # ShrI
|
||||||
|
["", "", "($1 << $2)", "($1 << $2)"], # ShlI
|
||||||
|
["", "", "($1 & $2)", "($1 & $2)"], # BitandI
|
||||||
|
["", "", "($1 | $2)", "($1 | $2)"], # BitorI
|
||||||
|
["", "", "($1 ^ $2)", "($1 ^ $2)"], # BitxorI
|
||||||
|
["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinI
|
||||||
|
["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI
|
||||||
|
["", "", "($1 >>> $2)", "($1 >>> $2)"], # ShrI64
|
||||||
|
["", "", "($1 << $2)", "($1 << $2)"], # ShlI64
|
||||||
|
["", "", "($1 & $2)", "($1 & $2)"], # BitandI64
|
||||||
|
["", "", "($1 | $2)", "($1 | $2)"], # BitorI64
|
||||||
|
["", "", "($1 ^ $2)", "($1 ^ $2)"], # BitxorI64
|
||||||
|
["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinI64
|
||||||
|
["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI64
|
||||||
|
["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinF64
|
||||||
|
["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxF64
|
||||||
|
["AddU", "AddU", "AddU($1, $2)", "AddU($1, $2)"], # AddU
|
||||||
|
["SubU", "SubU", "SubU($1, $2)", "SubU($1, $2)"], # SubU
|
||||||
|
["MulU", "MulU", "MulU($1, $2)", "MulU($1, $2)"], # MulU
|
||||||
|
["DivU", "DivU", "DivU($1, $2)", "DivU($1, $2)"], # DivU
|
||||||
|
["ModU", "ModU", "ModU($1, $2)", "ModU($1, $2)"], # ModU
|
||||||
|
["", "", "($1 == $2)", "($1 == $2)"], # EqI
|
||||||
|
["", "", "($1 <= $2)", "($1 <= $2)"], # LeI
|
||||||
|
["", "", "($1 < $2)", "($1 < $2)"], # LtI
|
||||||
|
["", "", "($1 == $2)", "($1 == $2)"], # EqI64
|
||||||
|
["", "", "($1 <= $2)", "($1 <= $2)"], # LeI64
|
||||||
|
["", "", "($1 < $2)", "($1 < $2)"], # LtI64
|
||||||
|
["", "", "($1 == $2)", "($1 == $2)"], # EqF64
|
||||||
|
["", "", "($1 <= $2)", "($1 <= $2)"], # LeF64
|
||||||
|
["", "", "($1 < $2)", "($1 < $2)"], # LtF64
|
||||||
|
["LeU", "LeU", "LeU($1, $2)", "LeU($1, $2)"], # LeU
|
||||||
|
["LtU", "LtU", "LtU($1, $2)", "LtU($1, $2)"], # LtU
|
||||||
|
["LeU64", "LeU64", "LeU64($1, $2)", "LeU64($1, $2)"], # LeU64
|
||||||
|
["LtU64", "LtU64", "LtU64($1, $2)", "LtU64($1, $2)"], # LtU64
|
||||||
|
["", "", "($1 == $2)", "($1 == $2)"], # EqEnum
|
||||||
|
["", "", "($1 <= $2)", "($1 <= $2)"], # LeEnum
|
||||||
|
["", "", "($1 < $2)", "($1 < $2)"], # LtEnum
|
||||||
|
["", "", "($1 == $2)", "($1 == $2)"], # EqCh
|
||||||
|
["", "", "($1 <= $2)", "($1 <= $2)"], # LeCh
|
||||||
|
["", "", "($1 < $2)", "($1 < $2)"], # LtCh
|
||||||
|
["", "", "($1 == $2)", "($1 == $2)"], # EqB
|
||||||
|
["", "", "($1 <= $2)", "($1 <= $2)"], # LeB
|
||||||
|
["", "", "($1 < $2)", "($1 < $2)"], # LtB
|
||||||
|
["", "", "($1 == $2)", "($1 == $2)"], # EqRef
|
||||||
|
["", "", "($1 == $2)", "($1 == $2)"], # EqProc
|
||||||
|
["", "", "($1 == $2)", "($1 == $2)"], # EqUntracedRef
|
||||||
|
["", "", "($1 <= $2)", "($1 <= $2)"], # LePtr
|
||||||
|
["", "", "($1 < $2)", "($1 < $2)"], # LtPtr
|
||||||
|
["", "", "($1 == $2)", "($1 == $2)"], # EqCString
|
||||||
|
["", "", "($1 != $2)", "($1 != $2)"], # Xor
|
||||||
|
["NegInt", "", "NegInt($1)", "-($1)"], # UnaryMinusI
|
||||||
|
["NegInt64", "", "NegInt64($1)", "-($1)"], # UnaryMinusI64
|
||||||
|
["AbsInt", "", "AbsInt($1)", "Math.abs($1)"], # AbsI
|
||||||
|
["AbsInt64", "", "AbsInt64($1)", "Math.abs($1)"], # AbsI64
|
||||||
|
["", "", "not ($1)", "not ($1)"], # Not
|
||||||
|
["", "", "+($1)", "+($1)"], # UnaryPlusI
|
||||||
|
["", "", "~($1)", "~($1)"], # BitnotI
|
||||||
|
["", "", "+($1)", "+($1)"], # UnaryPlusI64
|
||||||
|
["", "", "~($1)", "~($1)"], # BitnotI64
|
||||||
|
["", "", "+($1)", "+($1)"], # UnaryPlusF64
|
||||||
|
["", "", "-($1)", "-($1)"], # UnaryMinusF64
|
||||||
|
["", "", "Math.abs($1)", "Math.abs($1)"], # AbsF64
|
||||||
|
["Ze8ToI", "Ze8ToI", "Ze8ToI($1)", "Ze8ToI($1)"], # mZe8ToI
|
||||||
|
["Ze8ToI64", "Ze8ToI64", "Ze8ToI64($1)", "Ze8ToI64($1)"], # mZe8ToI64
|
||||||
|
["Ze16ToI", "Ze16ToI", "Ze16ToI($1)", "Ze16ToI($1)"], # mZe16ToI
|
||||||
|
["Ze16ToI64", "Ze16ToI64", "Ze16ToI64($1)", "Ze16ToI64($1)"], # mZe16ToI64
|
||||||
|
["Ze32ToI64", "Ze32ToI64", "Ze32ToI64($1)", "Ze32ToI64($1)"], # mZe32ToI64
|
||||||
|
["ZeIToI64", "ZeIToI64", "ZeIToI64($1)", "ZeIToI64($1)"], # mZeIToI64
|
||||||
|
["ToU8", "ToU8", "ToU8($1)", "ToU8($1)"], # ToU8
|
||||||
|
["ToU16", "ToU16", "ToU16($1)", "ToU16($1)"], # ToU16
|
||||||
|
["ToU32", "ToU32", "ToU32($1)", "ToU32($1)"], # ToU32
|
||||||
|
["", "", "$1", "$1"], # ToFloat
|
||||||
|
["", "", "$1", "$1"], # ToBiggestFloat
|
||||||
|
["", "", "Math.floor($1)", "Math.floor($1)"], # ToInt
|
||||||
|
["", "", "Math.floor($1)", "Math.floor($1)"], # ToBiggestInt
|
||||||
|
["nimCharToStr", "nimCharToStr", "nimCharToStr($1)", "nimCharToStr($1)"],
|
||||||
|
["nimBoolToStr", "nimBoolToStr", "nimBoolToStr($1)", "nimBoolToStr($1)"], [
|
||||||
|
"cstrToNimstr", "cstrToNimstr", "cstrToNimstr(($1)+\"\")",
|
||||||
|
"cstrToNimstr(($1)+\"\")"], ["cstrToNimstr", "cstrToNimstr",
|
||||||
|
"cstrToNimstr(($1)+\"\")",
|
||||||
|
"cstrToNimstr(($1)+\"\")"], ["cstrToNimstr",
|
||||||
|
"cstrToNimstr", "cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")"],
|
||||||
|
["cstrToNimstr", "cstrToNimstr", "cstrToNimstr($1)", "cstrToNimstr($1)"],
|
||||||
|
["", "", "$1", "$1"]]
|
||||||
|
|
||||||
proc binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
|
proc binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
|
||||||
var x, y: TCompRes
|
var x, y: TCompRes
|
||||||
useMagic(p, magic)
|
useMagic(p, magic)
|
||||||
|
|
@ -357,7 +458,7 @@ proc unaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
|
||||||
r.res = ropef(frmt, [r.rdLoc])
|
r.res = ropef(frmt, [r.rdLoc])
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
|
|
||||||
proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic, ops: TMagicOps) =
|
||||||
var
|
var
|
||||||
x, y: TCompRes
|
x, y: TCompRes
|
||||||
let i = ord(optOverflowCheck notin p.options)
|
let i = ord(optOverflowCheck notin p.options)
|
||||||
|
|
@ -371,10 +472,13 @@ proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
||||||
r.res = ropef(ops[op][i + 2], [r.rdLoc])
|
r.res = ropef(ops[op][i + 2], [r.rdLoc])
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
|
|
||||||
|
proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
||||||
|
arithAux(p, n, r, op, jsOps | luaOps)
|
||||||
|
|
||||||
proc genLineDir(p: PProc, n: PNode) =
|
proc genLineDir(p: PProc, n: PNode) =
|
||||||
let line = toLinenumber(n.info)
|
let line = toLinenumber(n.info)
|
||||||
if optLineDir in p.Options:
|
if optLineDir in p.Options:
|
||||||
appf(p.body, "// line $2 \"$1\"$n",
|
appf(p.body, "// line $2 \"$1\"$n" | "-- line $2 \"$1\"$n",
|
||||||
[toRope(toFilename(n.info)), toRope(line)])
|
[toRope(toFilename(n.info)), toRope(line)])
|
||||||
if {optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb} and
|
if {optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb} and
|
||||||
((p.prc == nil) or sfPure notin p.prc.flags):
|
((p.prc == nil) or sfPure notin p.prc.flags):
|
||||||
|
|
@ -393,7 +497,7 @@ proc genWhileStmt(p: PProc, n: PNode) =
|
||||||
inc(p.unique)
|
inc(p.unique)
|
||||||
var length = len(p.blocks)
|
var length = len(p.blocks)
|
||||||
setlen(p.blocks, length + 1)
|
setlen(p.blocks, length + 1)
|
||||||
p.blocks[length].id = - p.unique
|
p.blocks[length].id = -p.unique
|
||||||
p.blocks[length].isLoop = true
|
p.blocks[length].isLoop = true
|
||||||
let labl = p.unique.toRope
|
let labl = p.unique.toRope
|
||||||
appf(p.body, "L$1: while (true) {$n" | "while true do$n", labl)
|
appf(p.body, "L$1: while (true) {$n" | "while true do$n", labl)
|
||||||
|
|
@ -401,7 +505,7 @@ proc genWhileStmt(p: PProc, n: PNode) =
|
||||||
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])
|
genStmt(p, n.sons[1])
|
||||||
appf(p.body, "}$n" | "end$n", [])
|
appf(p.body, "}$n" | "end ::L$#::$n", [labl])
|
||||||
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) =
|
||||||
|
|
@ -434,51 +538,62 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
# excHandler = excHandler.prev;
|
# excHandler = excHandler.prev;
|
||||||
# }
|
# }
|
||||||
genLineDir(p, n)
|
genLineDir(p, n)
|
||||||
inc(p.unique)
|
|
||||||
var safePoint = ropef("Tmp$1", [toRope(p.unique)])
|
|
||||||
appf(p.body,
|
|
||||||
"var $1 = {prev: excHandler, exc: null};$n" & "excHandler = $1;$n",
|
|
||||||
[safePoint])
|
|
||||||
if optStackTrace in p.Options: app(p.body, "framePtr = F;" & tnl)
|
|
||||||
app(p.body, "try {" & tnl)
|
|
||||||
var length = sonsLen(n)
|
|
||||||
var a: TCompRes
|
|
||||||
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)
|
||||||
|
inc(p.unique)
|
||||||
|
var safePoint = ropef("Tmp$1", [toRope(p.unique)])
|
||||||
|
appf(p.body,
|
||||||
|
"var $1 = {prev: excHandler, exc: null};$nexcHandler = $1;$n" |
|
||||||
|
"local $1 = pcall(",
|
||||||
|
[safePoint])
|
||||||
|
if optStackTrace in p.Options: app(p.body, "framePtr = F;" & tnl)
|
||||||
|
appf(p.body, "try {$n" | "function()$n")
|
||||||
|
var length = sonsLen(n)
|
||||||
|
var a: TCompRes
|
||||||
|
gen(p, n.sons[0], a)
|
||||||
moveInto(p, a, r)
|
moveInto(p, a, r)
|
||||||
var i = 1
|
var i = 1
|
||||||
if length > 1 and n.sons[i].kind == nkExceptBranch:
|
if p.target == targetJS and length > 1 and n.sons[i].kind == nkExceptBranch:
|
||||||
appf(p.body, "} catch (EXC) {$n")
|
appf(p.body, "} catch (EXC) {$n")
|
||||||
|
elif p.target == targetLua:
|
||||||
|
appf(p.body, "end)$n")
|
||||||
while i < length and n.sons[i].kind == nkExceptBranch:
|
while i < length and n.sons[i].kind == nkExceptBranch:
|
||||||
let blen = sonsLen(n.sons[i])
|
let blen = sonsLen(n.sons[i])
|
||||||
if blen == 1:
|
if blen == 1:
|
||||||
# general except section:
|
# general except section:
|
||||||
if i > 1: app(p.body, "else {" & tnl)
|
if i > 1: appf(p.body, "else {$n" | "else$n")
|
||||||
gen(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: appf(p.body, "}$n" | "end$n")
|
||||||
else:
|
else:
|
||||||
var orExpr: PRope = nil
|
var orExpr: PRope = nil
|
||||||
useMagic(p, "isObj")
|
useMagic(p, "isObj")
|
||||||
for j in countup(0, blen - 2):
|
for j in countup(0, blen - 2):
|
||||||
if n.sons[i].sons[j].kind != nkType:
|
if n.sons[i].sons[j].kind != nkType:
|
||||||
InternalError(n.info, "genTryStmt")
|
InternalError(n.info, "genTryStmt")
|
||||||
if orExpr != nil: app(orExpr, "||")
|
if orExpr != nil: app(orExpr, "||" | " or ")
|
||||||
appf(orExpr, "isObj($1.exc.m_type, $2)",
|
appf(orExpr, "isObj($1.exc.m_type, $2)",
|
||||||
[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" | "if $1.exc and ($2) then$n",
|
||||||
|
[safePoint, orExpr])
|
||||||
gen(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" | "end$n")
|
||||||
inc(i)
|
inc(i)
|
||||||
|
if p.target == targetJS:
|
||||||
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:
|
||||||
gen(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)
|
if p.target == targetJS:
|
||||||
|
app(p.body, "}" & tnl)
|
||||||
|
if p.target == targetLua:
|
||||||
|
# we need to repeat the finally block for Lua ...
|
||||||
|
if i < length and n.sons[i].kind == nkFinally:
|
||||||
|
gen(p, n.sons[i].sons[0], a)
|
||||||
|
moveInto(p, a, r)
|
||||||
|
|
||||||
proc genRaiseStmt(p: PProc, n: PNode) =
|
proc genRaiseStmt(p: PProc, n: PNode) =
|
||||||
genLineDir(p, n)
|
genLineDir(p, n)
|
||||||
|
|
@ -493,7 +608,7 @@ proc genRaiseStmt(p: PProc, n: PNode) =
|
||||||
useMagic(p, "reraiseException")
|
useMagic(p, "reraiseException")
|
||||||
app(p.body, "reraiseException();" & tnl)
|
app(p.body, "reraiseException();" & tnl)
|
||||||
|
|
||||||
proc genCase(p: PProc, n: PNode, r: var TCompRes) =
|
proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
var
|
var
|
||||||
cond, stmt: TCompRes
|
cond, stmt: TCompRes
|
||||||
genLineDir(p, n)
|
genLineDir(p, n)
|
||||||
|
|
@ -539,24 +654,67 @@ proc genCase(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
else: internalError(it.info, "jsgen.genCaseStmt")
|
else: internalError(it.info, "jsgen.genCaseStmt")
|
||||||
appf(p.body, "}$n")
|
appf(p.body, "}$n")
|
||||||
|
|
||||||
proc genBlock(p: PProc, n: PNode, r: var TCompRes) =
|
proc genCaseLua(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
var
|
var
|
||||||
idx, labl: int
|
cond, stmt: TCompRes
|
||||||
sym: PSym
|
genLineDir(p, n)
|
||||||
|
gen(p, n.sons[0], cond)
|
||||||
|
let stringSwitch = skipTypes(n.sons[0].typ, abstractVar).kind == tyString
|
||||||
|
if stringSwitch:
|
||||||
|
useMagic(p, "eqStr")
|
||||||
|
let tmp = getTemp(p)
|
||||||
|
appf(p.body, "$1 = $2;$n", [tmp, cond.rdLoc])
|
||||||
|
if not isEmptyType(n.typ):
|
||||||
|
r.kind = resVal
|
||||||
|
r.res = getTemp(p)
|
||||||
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
|
let it = n.sons[i]
|
||||||
|
case it.kind
|
||||||
|
of nkOfBranch:
|
||||||
|
if i != 1: appf(p.body, "$nelsif ")
|
||||||
|
else: appf(p.body, "if ")
|
||||||
|
for j in countup(0, sonsLen(it) - 2):
|
||||||
|
if j != 0: app(p.body, " or ")
|
||||||
|
let e = it.sons[j]
|
||||||
|
if e.kind == nkRange:
|
||||||
|
var ia, ib: TCompRes
|
||||||
|
gen(p, e.sons[0], ia)
|
||||||
|
gen(p, e.sons[1], ib)
|
||||||
|
appf(p.body, "$1 >= $2 and $1 <= $3", [tmp, ia.rdLoc, ib.rdLoc])
|
||||||
|
else:
|
||||||
|
if stringSwitch:
|
||||||
|
case e.kind
|
||||||
|
of nkStrLit..nkTripleStrLit: appf(p.body, "eqStr($1, $2)",
|
||||||
|
[tmp, makeJSString(e.strVal)])
|
||||||
|
else: InternalError(e.info, "jsgen.genCaseStmt: 2")
|
||||||
|
else:
|
||||||
|
gen(p, e, cond)
|
||||||
|
appf(p.body, "$1 == $2", [tmp, cond.rdLoc])
|
||||||
|
appf(p.body, " then$n")
|
||||||
|
gen(p, lastSon(it), stmt)
|
||||||
|
moveInto(p, stmt, r)
|
||||||
|
of nkElse:
|
||||||
|
appf(p.body, "else$n")
|
||||||
|
gen(p, it.sons[0], stmt)
|
||||||
|
moveInto(p, stmt, r)
|
||||||
|
else: internalError(it.info, "jsgen.genCaseStmt")
|
||||||
|
appf(p.body, "$nend$n")
|
||||||
|
|
||||||
|
proc genBlock(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
inc(p.unique)
|
inc(p.unique)
|
||||||
idx = len(p.blocks)
|
let idx = len(p.blocks)
|
||||||
if n.sons[0].kind != nkEmpty:
|
if n.sons[0].kind != nkEmpty:
|
||||||
# named block?
|
# named block?
|
||||||
if (n.sons[0].kind != nkSym): InternalError(n.info, "genBlock")
|
if (n.sons[0].kind != nkSym): InternalError(n.info, "genBlock")
|
||||||
sym = n.sons[0].sym
|
var sym = n.sons[0].sym
|
||||||
sym.loc.k = locOther
|
sym.loc.k = locOther
|
||||||
sym.loc.a = idx
|
sym.loc.a = idx
|
||||||
setlen(p.blocks, idx + 1)
|
setlen(p.blocks, idx + 1)
|
||||||
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
|
let labl = p.unique
|
||||||
appf(p.body, "L$1: do {$n", toRope(labl))
|
appf(p.body, "L$1: do {$n" | "", labl.toRope)
|
||||||
gen(p, n.sons[1], r)
|
gen(p, n.sons[1], r)
|
||||||
appf(p.body, "} while(false);$n")
|
appf(p.body, "} while(false);$n" | "$n::L$#::$n", labl.toRope)
|
||||||
setlen(p.blocks, idx)
|
setlen(p.blocks, idx)
|
||||||
|
|
||||||
proc genBreakStmt(p: PProc, n: PNode) =
|
proc genBreakStmt(p: PProc, n: PNode) =
|
||||||
|
|
@ -575,7 +733,7 @@ proc genBreakStmt(p: PProc, n: PNode) =
|
||||||
if idx < 0 or not p.blocks[idx].isLoop:
|
if idx < 0 or not p.blocks[idx].isLoop:
|
||||||
InternalError(n.info, "no loop to break")
|
InternalError(n.info, "no loop to break")
|
||||||
p.blocks[idx].id = abs(p.blocks[idx].id) # label is used
|
p.blocks[idx].id = abs(p.blocks[idx].id) # label is used
|
||||||
appf(p.body, "break L$1;$n", [toRope(p.blocks[idx].id)])
|
appf(p.body, "break L$1;$n" | "goto ::L$1::;$n", [toRope(p.blocks[idx].id)])
|
||||||
|
|
||||||
proc genAsmStmt(p: PProc, n: PNode) =
|
proc genAsmStmt(p: PProc, n: PNode) =
|
||||||
genLineDir(p, n)
|
genLineDir(p, n)
|
||||||
|
|
@ -596,18 +754,21 @@ proc genIf(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
let it = n.sons[i]
|
let it = n.sons[i]
|
||||||
if sonsLen(it) != 1:
|
if sonsLen(it) != 1:
|
||||||
if i > 0:
|
if i > 0:
|
||||||
appf(p.body, "else {$n", [])
|
appf(p.body, "else {$n" | "else$n", [])
|
||||||
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" | "if $# then$n", cond.rdLoc)
|
||||||
gen(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" | "else$n")
|
||||||
gen(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" | "end$n")
|
||||||
|
if p.target == targetJS:
|
||||||
app(p.body, repeatChar(toClose, '}') & tnl)
|
app(p.body, repeatChar(toClose, '}') & tnl)
|
||||||
|
else:
|
||||||
|
for i in 1..toClose: appf(p.body, "end$n")
|
||||||
|
|
||||||
proc generateHeader(p: PProc, typ: PType): PRope =
|
proc generateHeader(p: PProc, typ: PType): PRope =
|
||||||
result = nil
|
result = nil
|
||||||
|
|
@ -957,23 +1118,26 @@ proc createVar(p: PProc, typ: PType, indirect: bool): PRope =
|
||||||
result = toRope("{")
|
result = toRope("{")
|
||||||
for i in 0.. <t.sonslen:
|
for i in 0.. <t.sonslen:
|
||||||
if i > 0: app(result, ", ")
|
if i > 0: app(result, ", ")
|
||||||
appf(result, "Field$1: $2", i.toRope, createVar(p, t.sons[i], false))
|
appf(result, "Field$1: $2" | "Field$# = $#", i.toRope,
|
||||||
|
createVar(p, t.sons[i], false))
|
||||||
app(result, "}")
|
app(result, "}")
|
||||||
of tyObject:
|
of tyObject:
|
||||||
result = toRope("{")
|
result = toRope("{")
|
||||||
var c = 0
|
var c = 0
|
||||||
if tfFinal notin t.flags or t.sons[0] != nil:
|
if tfFinal notin t.flags or t.sons[0] != nil:
|
||||||
inc(c)
|
inc(c)
|
||||||
appf(result, "m_type: $1", [genTypeInfo(p, t)])
|
appf(result, "m_type: $1" | "m_type = $#", [genTypeInfo(p, t)])
|
||||||
while t != nil:
|
while t != nil:
|
||||||
app(result, createRecordVarAux(p, t.n, c))
|
app(result, createRecordVarAux(p, t.n, c))
|
||||||
t = t.sons[0]
|
t = t.sons[0]
|
||||||
app(result, "}")
|
app(result, "}")
|
||||||
of tyVar, tyPtr, tyRef:
|
of tyVar, tyPtr, tyRef:
|
||||||
if mapType(t) == etyBaseIndex: result = putToSeq("[null, 0]", indirect)
|
if mapType(t) == etyBaseIndex:
|
||||||
else: result = putToSeq("null", indirect)
|
result = putToSeq("[null, 0]" | "{nil, 0}", indirect)
|
||||||
|
else:
|
||||||
|
result = putToSeq("null" | "nil", indirect)
|
||||||
of tySequence, tyString, tyCString, tyPointer, tyProc:
|
of tySequence, tyString, tyCString, tyPointer, tyProc:
|
||||||
result = putToSeq("null", indirect)
|
result = putToSeq("null" | "nil", indirect)
|
||||||
else:
|
else:
|
||||||
internalError("createVar: " & $t.kind)
|
internalError("createVar: " & $t.kind)
|
||||||
result = nil
|
result = nil
|
||||||
|
|
@ -987,7 +1151,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
|
||||||
a: TCompRes
|
a: TCompRes
|
||||||
s: PRope
|
s: PRope
|
||||||
if n.kind == nkEmpty:
|
if n.kind == nkEmpty:
|
||||||
appf(p.body, "var $1 = $2;$n",
|
appf(p.body, "var $1 = $2;$n" | "local $1 = $2;$n",
|
||||||
[mangleName(v), createVar(p, v.typ, isIndirect(v))])
|
[mangleName(v), createVar(p, v.typ, isIndirect(v))])
|
||||||
else:
|
else:
|
||||||
discard mangleName(v)
|
discard mangleName(v)
|
||||||
|
|
@ -1002,15 +1166,19 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
|
||||||
of etyBaseIndex:
|
of etyBaseIndex:
|
||||||
if (a.typ != etyBaseIndex): InternalError(n.info, "genVarInit")
|
if (a.typ != etyBaseIndex): InternalError(n.info, "genVarInit")
|
||||||
if {sfAddrTaken, sfGlobal} * v.flags != {}:
|
if {sfAddrTaken, sfGlobal} * v.flags != {}:
|
||||||
appf(p.body, "var $1 = [$2, $3];$n", [v.loc.r, a.address, a.res])
|
appf(p.body, "var $1 = [$2, $3];$n" | "local $1 = {$2, $3};$n",
|
||||||
|
[v.loc.r, a.address, a.res])
|
||||||
else:
|
else:
|
||||||
appf(p.body, "var $1 = $2; var $1_Idx = $3;$n", [
|
appf(p.body, "var $1 = $2; var $1_Idx = $3;$n" |
|
||||||
|
"local $1 = $2; local $1_Idx = $3;$n", [
|
||||||
v.loc.r, a.address, a.res])
|
v.loc.r, a.address, a.res])
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
s = a.res
|
s = a.res
|
||||||
if isIndirect(v): appf(p.body, "var $1 = [$2];$n", [v.loc.r, s])
|
if isIndirect(v):
|
||||||
else: appf(p.body, "var $1 = $2;$n", [v.loc.r, s])
|
appf(p.body, "var $1 = [$2];$n" | "local $1 = {$2};$n", [v.loc.r, s])
|
||||||
|
else:
|
||||||
|
appf(p.body, "var $1 = $2;$n" | "local $1 = $2;$n", [v.loc.r, s])
|
||||||
|
|
||||||
proc genVarStmt(p: PProc, n: PNode) =
|
proc genVarStmt(p: PProc, n: PNode) =
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
|
|
@ -1049,7 +1217,7 @@ proc genNewSeq(p: PProc, n: PNode) =
|
||||||
proc genOrd(p: PProc, n: PNode, r: var TCompRes) =
|
proc genOrd(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
case skipTypes(n.sons[1].typ, abstractVar).kind
|
case skipTypes(n.sons[1].typ, abstractVar).kind
|
||||||
of tyEnum, tyInt..tyInt64, tyChar: gen(p, n.sons[1], r)
|
of tyEnum, tyInt..tyInt64, tyChar: gen(p, n.sons[1], r)
|
||||||
of tyBool: unaryExpr(p, n, r, "", "($1 ? 1:0)")
|
of tyBool: unaryExpr(p, n, r, "", "($1 ? 1:0)" | "toBool($#)")
|
||||||
else: InternalError(n.info, "genOrd")
|
else: InternalError(n.info, "genOrd")
|
||||||
|
|
||||||
proc genConStrStr(p: PProc, n: PNode, r: var TCompRes) =
|
proc genConStrStr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
|
|
@ -1224,7 +1392,7 @@ proc genTupleConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
var it = n.sons[i]
|
var it = n.sons[i]
|
||||||
if it.kind == nkExprColonExpr: it = it.sons[1]
|
if it.kind == nkExprColonExpr: it = it.sons[1]
|
||||||
gen(p, it, a)
|
gen(p, it, a)
|
||||||
appf(r.res, "Field$1: $2", [i.toRope, a.res])
|
appf(r.res, "Field$#: $#" | "Field$# = $#", [i.toRope, a.res])
|
||||||
r.res.app("}")
|
r.res.app("}")
|
||||||
|
|
||||||
proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) =
|
proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
|
|
@ -1239,7 +1407,7 @@ proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
gen(p, it.sons[1], a)
|
gen(p, it.sons[1], a)
|
||||||
var f = it.sons[0].sym
|
var f = it.sons[0].sym
|
||||||
if f.loc.r == nil: f.loc.r = mangleName(f)
|
if f.loc.r == nil: f.loc.r = mangleName(f)
|
||||||
appf(r.res, "$1: $2", [f.loc.r, a.res])
|
appf(r.res, "$#: $#" | "$# = $#" , [f.loc.r, a.res])
|
||||||
r.res.app("}")
|
r.res.app("}")
|
||||||
|
|
||||||
proc genConv(p: PProc, n: PNode, r: var TCompRes) =
|
proc genConv(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
|
|
@ -1247,7 +1415,7 @@ proc genConv(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
var src = skipTypes(n.sons[1].typ, abstractVarRange)
|
var src = skipTypes(n.sons[1].typ, abstractVarRange)
|
||||||
gen(p, n.sons[1], r)
|
gen(p, n.sons[1], r)
|
||||||
if (dest.kind != src.kind) and (src.kind == tyBool):
|
if (dest.kind != src.kind) and (src.kind == tyBool):
|
||||||
r.res = ropef("(($1)? 1:0)", [r.res])
|
r.res = ropef("(($1)? 1:0)" | "toBool($#)", [r.res])
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
|
|
||||||
proc upConv(p: PProc, n: PNode, r: var TCompRes) =
|
proc upConv(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
|
|
@ -1294,20 +1462,23 @@ proc genReturnStmt(p: PProc, n: PNode) =
|
||||||
genStmt(p, n.sons[0])
|
genStmt(p, n.sons[0])
|
||||||
else:
|
else:
|
||||||
genLineDir(p, n)
|
genLineDir(p, n)
|
||||||
app(p.body, "break BeforeRet;" & tnl)
|
appf(p.body, "break BeforeRet;$n" | "goto ::BeforeRet::;$n")
|
||||||
|
|
||||||
proc genProcBody(p: PProc, prc: PSym): PRope =
|
proc genProcBody(p: PProc, prc: PSym): PRope =
|
||||||
if optStackTrace in prc.options:
|
if optStackTrace in prc.options:
|
||||||
result = ropef("var F={procname:$1,prev:framePtr,filename:$2,line:0};$n" &
|
result = ropef(("var F={procname:$1,prev:framePtr,filename:$2,line:0};$n" |
|
||||||
"framePtr = F;$n", [makeJSString(prc.owner.name.s & '.' & prc.name.s),
|
"local F={procname=$#,prev=framePtr,filename=$#,line=0};$n") &
|
||||||
|
"framePtr = F;$n", [
|
||||||
|
makeJSString(prc.owner.name.s & '.' & prc.name.s),
|
||||||
makeJSString(toFilename(prc.info))])
|
makeJSString(toFilename(prc.info))])
|
||||||
else:
|
else:
|
||||||
result = nil
|
result = nil
|
||||||
if p.beforeRetNeeded:
|
if p.beforeRetNeeded:
|
||||||
appf(result, "BeforeRet: do {$n$1} while (false); $n", [p.body])
|
appf(result, "BeforeRet: do {$n$1} while (false); $n" |
|
||||||
|
"$#;::BeforeRet::$n", [p.body])
|
||||||
else:
|
else:
|
||||||
app(result, p.body)
|
app(result, p.body)
|
||||||
if prc.typ.callConv == ccSysCall:
|
if prc.typ.callConv == ccSysCall and p.target == targetJS:
|
||||||
result = ropef("try {$n$1} catch (e) {$n" &
|
result = ropef("try {$n$1} catch (e) {$n" &
|
||||||
" alert(\"Unhandled exception:\\n\" + e.message + \"\\n\"$n}", [result])
|
" alert(\"Unhandled exception:\\n\" + e.message + \"\\n\"$n}", [result])
|
||||||
if optStackTrace in prc.options:
|
if optStackTrace in prc.options:
|
||||||
|
|
@ -1329,12 +1500,14 @@ proc genProc(oldProc: PProc, prc: PSym): PRope =
|
||||||
header = generateHeader(p, prc.typ)
|
header = generateHeader(p, prc.typ)
|
||||||
if prc.typ.sons[0] != nil and sfPure notin prc.flags:
|
if prc.typ.sons[0] != nil and sfPure notin prc.flags:
|
||||||
resultSym = prc.ast.sons[resultPos].sym
|
resultSym = prc.ast.sons[resultPos].sym
|
||||||
resultAsgn = ropef("var $# = $#;$n", [mangleName(resultSym),
|
resultAsgn = ropef("var $# = $#;$n" | "local $# = $#;$n", [
|
||||||
|
mangleName(resultSym),
|
||||||
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)
|
genStmt(p, prc.getBody)
|
||||||
result = ropef("function $#($#) {$n$#$#$#$#}$n",
|
result = ropef("function $#($#) {$n$#$#$#$#}$n" |
|
||||||
|
"function $#($#) $n$#$#$#$#$nend$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:
|
||||||
|
|
@ -1360,10 +1533,10 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
nil
|
nil
|
||||||
elif mapType(n.typ) == etyBaseIndex:
|
elif mapType(n.typ) == etyBaseIndex:
|
||||||
r.typ = etyBaseIndex
|
r.typ = etyBaseIndex
|
||||||
r.address = toRope"null"
|
r.address = toRope"null" | toRope"nil"
|
||||||
r.res = toRope"0"
|
r.res = toRope"0"
|
||||||
else:
|
else:
|
||||||
r.res = toRope"null"
|
r.res = toRope"null" | toRope"nil"
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
if skipTypes(n.typ, abstractVarRange).kind == tyString:
|
if skipTypes(n.typ, abstractVarRange).kind == tyString:
|
||||||
useMagic(p, "cstrToNimstr")
|
useMagic(p, "cstrToNimstr")
|
||||||
|
|
@ -1430,7 +1603,9 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
of nkConstSection: nil
|
of nkConstSection: nil
|
||||||
of nkForStmt, nkParForStmt:
|
of nkForStmt, nkParForStmt:
|
||||||
internalError(n.info, "for statement not eliminated")
|
internalError(n.info, "for statement not eliminated")
|
||||||
of nkCaseStmt: genCase(p, n, r)
|
of nkCaseStmt:
|
||||||
|
if p.target == targetJS: genCaseJS(p, n, r)
|
||||||
|
else: genCaseLua(p, n, r)
|
||||||
of nkReturnStmt: genReturnStmt(p, n)
|
of nkReturnStmt: genReturnStmt(p, n)
|
||||||
of nkBreakStmt: genBreakStmt(p, n)
|
of nkBreakStmt: genBreakStmt(p, n)
|
||||||
of nkAsgn: genAsgn(p, n)
|
of nkAsgn: genAsgn(p, n)
|
||||||
|
|
@ -1463,8 +1638,10 @@ proc newModule(module: PSym): BModule =
|
||||||
|
|
||||||
proc genHeader(): PRope =
|
proc genHeader(): PRope =
|
||||||
result = ropef("/* Generated by the Nimrod Compiler v$1 */$n" &
|
result = ropef("/* Generated by the Nimrod Compiler v$1 */$n" &
|
||||||
"/* (c) 2013 Andreas Rumpf */$n$n" & "$nvar Globals = this;$n" &
|
"/* (c) 2013 Andreas Rumpf */$n$n" &
|
||||||
"var framePtr = null;$n" & "var excHandler = null;$n",
|
"$nvar Globals = this;$n" &
|
||||||
|
"var framePtr = null;$n" &
|
||||||
|
"var excHandler = null;$n",
|
||||||
[toRope(versionAsString)])
|
[toRope(versionAsString)])
|
||||||
|
|
||||||
proc genModule(p: PProc, n: PNode) =
|
proc genModule(p: PProc, n: PNode) =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue