Fixes problems with JS code gen.

--out for JS backend now works. setLen now works, this also fixes the base64
module. getCurrentExceptionMsg now also works with exceptions thrown by
JS. log() supports a variable number of args now. Fixed some case
sensitivity issues with arrayConstr and other functions.
This commit is contained in:
Dominik Picheta
2014-04-11 21:36:02 +01:00
parent dcfc7a8896
commit b0a16fb619
3 changed files with 51 additions and 26 deletions

View File

@@ -564,7 +564,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
moveInto(p, a, r)
var i = 1
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 lastJSError = EXC;$n")
elif p.target == targetLua:
appf(p.body, "end)$n")
while i < length and n.sons[i].kind == nkExceptBranch:
@@ -1114,6 +1114,8 @@ proc createVar(p: PProc, typ: PType, indirect: bool): PRope =
var e = elemType(t)
if length > 32:
useMagic(p, "arrayConstr")
# XXX: arrayConstr depends on nimCopy. This line shouldn't be necessary.
useMagic(p, "nimCopy")
result = ropef("arrayConstr($1, $2, $3)", [toRope(length),
createVar(p, e, false), genTypeInfo(p, e)])
else:
@@ -1314,7 +1316,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
if skipTypes(n.sons[1].typ, abstractVarRange).kind == tyCString:
binaryExpr(p, n, r, "", "$1 += $2")
else:
binaryExpr(p, n, r, "", "$1 = ($1.slice(0,-1)).concat($2)")
binaryExpr(p, n, r, "", "$1 = ($1.slice(0, -1)).concat($2)")
# XXX: make a copy of $2, because of Javascript's sucking semantics
of mAppendSeqElem: binaryExpr(p, n, r, "", "$1.push($2)")
of mConStrStr: genConStrStr(p, n, r)
@@ -1341,7 +1343,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
of ast.mDec:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2")
else: binaryExpr(p, n, r, "subInt", "$1 = subInt($1, $2)")
of mSetLengthStr: binaryExpr(p, n, r, "", "$1.length = ($2)-1")
of mSetLengthStr: binaryExpr(p, n, r, "", "$1.length = $2+1; $1[$1.length-1] = 0")
of mSetLengthSeq: binaryExpr(p, n, r, "", "$1.length = $2")
of mCard: unaryExpr(p, n, r, "SetCard", "SetCard($1)")
of mLtSet: binaryExpr(p, n, r, "SetLt", "SetLt($1, $2)")
@@ -1698,7 +1700,12 @@ proc myClose(b: PPassContext, n: PNode): PNode =
var m = BModule(b)
if sfMainModule in m.module.flags:
let code = wholeCode(m)
var outfile = changeFileExt(completeCFilePath(m.module.filename), "js")
let outfile =
if options.outFile.len > 0:
if options.outFile.isAbsolute: options.outFile
else: getCurrentDir() / options.outFile
else:
changeFileExt(completeCFilePath(m.module.filename), "js")
discard writeRopeIfNotEqual(con(genHeader(), code), outfile)
proc myOpenCached(s: PSym, rd: PRodReader): PPassContext =

View File

@@ -61,8 +61,12 @@ proc handleCmdLine() =
tccgen.run()
if optRun in gGlobalOptions:
if gCmd == cmdCompileToJS:
var ex = quoteShell(
completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir))
var ex: string
if options.outFile.len > 0:
ex = options.outFile.prependCurDir.quoteShell
else:
ex = quoteShell(
completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir))
execExternalProgram("node " & ex & ' ' & service.arguments)
else:
var binPath: string

View File

@@ -12,7 +12,7 @@ when defined(nodejs):
else:
proc alert*(s: cstring) {.importc, nodecl.}
proc log*(s: cstring) {.importc: "console.log", nodecl.}
proc log*(s: cstring) {.importc: "console.log", varargs, nodecl.}
type
PSafePoint = ptr TSafePoint
@@ -27,11 +27,19 @@ type
line: int # current line number
filename: cstring
PJSError = ref object
columnNumber {.importc.}: int
fileName {.importc.}: cstring
lineNumber {.importc.}: int
message {.importc.}: cstring
stack {.importc.}: cstring
var
framePtr {.importc, nodecl, volatile.}: PCallFrame
excHandler {.importc, nodecl, volatile.}: PSafePoint = nil
# list of exception handlers
# a global variable for the root of all try blocks
lastJSError {.importc, nodecl, volatile.}: PJSError = nil
{.push stacktrace: off, profiler:off.}
proc nimBoolToStr(x: bool): string {.compilerproc.} =
@@ -43,8 +51,12 @@ proc nimCharToStr(x: char): string {.compilerproc.} =
result[0] = x
proc getCurrentExceptionMsg*(): string =
if excHandler != nil: return $excHandler.exc.msg
return ""
if excHandler != nil and excHandler.exc != nil:
return $excHandler.exc.msg
elif lastJSError != nil:
return $lastJSError.message
else:
return ""
proc auxWriteStackTrace(f: PCallFrame): string =
type
@@ -77,11 +89,13 @@ proc auxWriteStackTrace(f: PCallFrame): string =
add(result, "\n")
proc rawWriteStackTrace(): string =
if framePtr == nil:
result = "No stack traceback available\n"
else:
result = "Traceback (most recent call last)\n"& auxWriteStackTrace(framePtr)
if framePtr != nil:
result = "Traceback (most recent call last)\n" & auxWriteStackTrace(framePtr)
framePtr = nil
elif lastJSError != nil:
result = $lastJSError.stack
else:
result = "No stack traceback available\n"
proc raiseException(e: ref E_Base, ename: cstring) {.
compilerproc, asmNoStackFrame.} =
@@ -472,17 +486,17 @@ proc ze*(a: int): int {.compilerproc.} =
proc ze64*(a: int64): int64 {.compilerproc.} =
result = a
proc ToU8(a: int): int8 {.asmNoStackFrame, compilerproc.} =
proc toU8*(a: int): int8 {.asmNoStackFrame, compilerproc.} =
asm """
return `a`;
"""
proc ToU16(a: int): int16 {.asmNoStackFrame, compilerproc.} =
proc toU16*(a: int): int16 {.asmNoStackFrame, compilerproc.} =
asm """
return `a`;
"""
proc ToU32(a: int): int32 {.asmNoStackFrame, compilerproc.} =
proc toU32*(a: int64): int32 {.asmNoStackFrame, compilerproc.} =
asm """
return `a`;
"""
@@ -503,17 +517,17 @@ proc nimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.}
proc nimCopyAux(dest, src: Pointer, n: ptr TNimNode) {.compilerproc.} =
case n.kind
of nkNone: sysAssert(false, "NimCopyAux")
of nkNone: sysAssert(false, "nimCopyAux")
of nkSlot:
asm "`dest`[`n`.offset] = NimCopy(`src`[`n`.offset], `n`.typ);"
asm "`dest`[`n`.offset] = nimCopy(`src`[`n`.offset], `n`.typ);"
of nkList:
for i in 0..n.len-1:
NimCopyAux(dest, src, n.sons[i])
nimCopyAux(dest, src, n.sons[i])
of nkCase:
asm """
`dest`[`n`.offset] = NimCopy(`src`[`n`.offset], `n`.typ);
`dest`[`n`.offset] = nimCopy(`src`[`n`.offset], `n`.typ);
for (var i = 0; i < `n`.sons.length; ++i) {
NimCopyAux(`dest`, `src`, `n`.sons[i][1]);
nimCopyAux(`dest`, `src`, `n`.sons[i][1]);
}
"""
@@ -534,17 +548,17 @@ proc nimCopy(x: pointer, ti: PNimType): pointer =
for (var key in `x`) { `result`[key] = `x`[key]; }
"""
of tyTuple, tyObject:
if ti.base != nil: result = NimCopy(x, ti.base)
if ti.base != nil: result = nimCopy(x, ti.base)
elif ti.kind == tyObject:
asm "`result` = {m_type: `ti`};"
else:
asm "`result` = {};"
NimCopyAux(result, x, ti.node)
nimCopyAux(result, x, ti.node)
of tySequence, tyArrayConstr, tyOpenArray, tyArray:
asm """
`result` = new Array(`x`.length);
for (var i = 0; i < `x`.length; ++i) {
`result`[i] = NimCopy(`x`[i], `ti`.base);
`result`[i] = nimCopy(`x`[i], `ti`.base);
}
"""
of tyString:
@@ -584,12 +598,12 @@ proc genericReset(x: Pointer, ti: PNimType): pointer {.compilerproc.} =
else:
result = nil
proc ArrayConstr(len: int, value: pointer, typ: PNimType): pointer {.
proc arrayConstr(len: int, value: pointer, typ: PNimType): pointer {.
asmNoStackFrame, compilerproc.} =
# types are fake
asm """
var result = new Array(`len`);
for (var i = 0; i < `len`; ++i) result[i] = NimCopy(`value`, `typ`);
for (var i = 0; i < `len`; ++i) result[i] = nimCopy(`value`, `typ`);
return result;
"""