JS codegen enhancements; still unusable
This commit is contained in:
parent
ee1bcb6414
commit
fe285b354d
9 changed files with 223 additions and 59 deletions
|
|
@ -546,11 +546,12 @@ proc genTryStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
if i > 1: app(epart, '}' & tnl)
|
if i > 1: app(epart, '}' & tnl)
|
||||||
else:
|
else:
|
||||||
orExpr = nil
|
orExpr = nil
|
||||||
|
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, "||")
|
||||||
appf(orExpr, "($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(epart, "else ")
|
if i > 1: app(epart, "else ")
|
||||||
appf(epart, "if ($1.exc && $2) {$n", [safePoint, orExpr])
|
appf(epart, "if ($1.exc && $2) {$n", [safePoint, orExpr])
|
||||||
|
|
@ -791,7 +792,7 @@ proc genSwap(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
gen(p, n.sons[2], b)
|
gen(p, n.sons[2], b)
|
||||||
inc(p.unique)
|
inc(p.unique)
|
||||||
var tmp = ropef("Tmp$1", [toRope(p.unique)])
|
var tmp = ropef("Tmp$1", [toRope(p.unique)])
|
||||||
case mapType(n.sons[1].typ)
|
case mapType(skipTypes(n.sons[1].typ, abstractVar))
|
||||||
of etyBaseIndex:
|
of etyBaseIndex:
|
||||||
inc(p.unique)
|
inc(p.unique)
|
||||||
var tmp2 = ropef("Tmp$1", [toRope(p.unique)])
|
var tmp2 = ropef("Tmp$1", [toRope(p.unique)])
|
||||||
|
|
@ -804,11 +805,20 @@ proc genSwap(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
if b.com != nil: appf(r.com, "$1;$n", [b.com])
|
if b.com != nil: appf(r.com, "$1;$n", [b.com])
|
||||||
appf(r.com, "var $1 = $2; $2 = $3; $3 = $1", [tmp, a.res, b.res])
|
appf(r.com, "var $1 = $2; $2 = $3; $3 = $1", [tmp, a.res, b.res])
|
||||||
|
|
||||||
|
proc getFieldPosition(f: PNode): int =
|
||||||
|
case f.kind
|
||||||
|
of nkIntLit..nkUInt64Lit: result = int(f.intVal)
|
||||||
|
of nkSym: result = f.sym.position
|
||||||
|
else: InternalError(f.info, "genFieldPosition")
|
||||||
|
|
||||||
proc genFieldAddr(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genFieldAddr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
var a: TCompRes
|
var a: TCompRes
|
||||||
r.kind = etyBaseIndex
|
r.kind = etyBaseIndex
|
||||||
var b = if n.kind == nkHiddenAddr: n.sons[0] else: n
|
var b = if n.kind == nkHiddenAddr: n.sons[0] else: n
|
||||||
gen(p, b.sons[0], a)
|
gen(p, b.sons[0], a)
|
||||||
|
if skipTypes(b.sons[0].typ, abstractVarRange).kind == tyTuple:
|
||||||
|
r.res = makeCString("Field" & $getFieldPosition(b.sons[1]))
|
||||||
|
else:
|
||||||
if b.sons[1].kind != nkSym: InternalError(b.sons[1].info, "genFieldAddr")
|
if b.sons[1].kind != nkSym: InternalError(b.sons[1].info, "genFieldAddr")
|
||||||
var f = b.sons[1].sym
|
var f = b.sons[1].sym
|
||||||
if f.loc.r == nil: f.loc.r = mangleName(f)
|
if f.loc.r == nil: f.loc.r = mangleName(f)
|
||||||
|
|
@ -818,6 +828,9 @@ proc genFieldAddr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
proc genFieldAccess(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genFieldAccess(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
r.kind = etyNone
|
r.kind = etyNone
|
||||||
gen(p, n.sons[0], r)
|
gen(p, n.sons[0], r)
|
||||||
|
if skipTypes(n.sons[0].typ, abstractVarRange).kind == tyTuple:
|
||||||
|
r.res = ropef("$1.Field$2", [r.res, getFieldPosition(n.sons[1]).toRope])
|
||||||
|
else:
|
||||||
if n.sons[1].kind != nkSym: InternalError(n.sons[1].info, "genFieldAddr")
|
if n.sons[1].kind != nkSym: InternalError(n.sons[1].info, "genFieldAddr")
|
||||||
var f = n.sons[1].sym
|
var f = n.sons[1].sym
|
||||||
if f.loc.r == nil: f.loc.r = mangleName(f)
|
if f.loc.r == nil: f.loc.r = mangleName(f)
|
||||||
|
|
@ -885,10 +898,16 @@ proc genAddr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
of nkDotExpr:
|
of nkDotExpr:
|
||||||
genFieldAddr(p, n, r)
|
genFieldAddr(p, n, r)
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
|
var ty = skipTypes(n.sons[0].typ, abstractVarRange)
|
||||||
|
if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.sons[0], abstractVarRange)
|
||||||
|
case ty.kind
|
||||||
|
of tyArray, tyArrayConstr, tyOpenArray, tySequence, tyString, tyCString:
|
||||||
genArrayAddr(p, n, r)
|
genArrayAddr(p, n, r)
|
||||||
|
of tyTuple:
|
||||||
|
genFieldAddr(p, n, r)
|
||||||
|
else: InternalError(n.info, "expr(nkBracketExpr, " & $ty.kind & ')')
|
||||||
else: InternalError(n.info, "genAddr")
|
else: InternalError(n.info, "genAddr")
|
||||||
|
|
||||||
|
|
||||||
proc genSym(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genSym(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
var s = n.sym
|
var s = n.sym
|
||||||
case s.kind
|
case s.kind
|
||||||
|
|
@ -956,6 +975,7 @@ proc genCall(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
genArgs(p, n, r)
|
genArgs(p, n, r)
|
||||||
|
|
||||||
proc genEcho(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genEcho(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
|
useMagic(p, "rawEcho")
|
||||||
app(r.res, "rawEcho")
|
app(r.res, "rawEcho")
|
||||||
genArgs(p, n, r)
|
genArgs(p, n, r)
|
||||||
|
|
||||||
|
|
@ -1146,6 +1166,25 @@ proc genRepr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
# XXX:
|
# XXX:
|
||||||
internalError(n.info, "genRepr: Not implemented")
|
internalError(n.info, "genRepr: Not implemented")
|
||||||
|
|
||||||
|
proc genOf(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
|
var x: TCompRes
|
||||||
|
let t = n.sons[2].typ
|
||||||
|
gen(p, n.sons[1], x)
|
||||||
|
if tfFinal in t.flags:
|
||||||
|
r.res = ropef("($1.m_type == $2)", [x.res, genTypeInfo(p, t)])
|
||||||
|
else:
|
||||||
|
useMagic(p, "isObj")
|
||||||
|
r.res = ropef("isObj($1.m_type, $2)", [x.res, genTypeInfo(p, t)])
|
||||||
|
r.com = mergeExpr(r.com, x.com)
|
||||||
|
|
||||||
|
proc genReset(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
|
var x: TCompRes
|
||||||
|
useMagic(p, "genericReset")
|
||||||
|
gen(p, n.sons[1], x)
|
||||||
|
r.res = ropef("$1 = genericReset($1, $2)", [x.res,
|
||||||
|
genTypeInfo(p, n.sons[1].typ)])
|
||||||
|
r.com = mergeExpr(r.com, x.com)
|
||||||
|
|
||||||
proc genMagic(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genMagic(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
var
|
var
|
||||||
a: TCompRes
|
a: TCompRes
|
||||||
|
|
@ -1216,6 +1255,8 @@ proc genMagic(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
of mNLen..mNError:
|
of mNLen..mNError:
|
||||||
localError(n.info, errCannotGenerateCodeForX, n.sons[0].sym.name.s)
|
localError(n.info, errCannotGenerateCodeForX, n.sons[0].sym.name.s)
|
||||||
of mNewSeq: binaryStmt(p, n, r, "", "$1 = new Array($2)")
|
of mNewSeq: binaryStmt(p, n, r, "", "$1 = new Array($2)")
|
||||||
|
of mOf: genOf(p, n, r)
|
||||||
|
of mReset: genReset(p, n, r)
|
||||||
of mEcho: genEcho(p, n, r)
|
of mEcho: genEcho(p, n, r)
|
||||||
of mSlurp, mStaticExec:
|
of mSlurp, mStaticExec:
|
||||||
localError(n.info, errXMustBeCompileTime, n.sons[0].sym.name.s)
|
localError(n.info, errXMustBeCompileTime, n.sons[0].sym.name.s)
|
||||||
|
|
@ -1252,19 +1293,17 @@ proc genArrayConstr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
app(r.res, a.res)
|
app(r.res, a.res)
|
||||||
app(r.res, "]")
|
app(r.res, "]")
|
||||||
|
|
||||||
proc genRecordConstr(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genTupleConstr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
var a: TCompRes
|
var a: TCompRes
|
||||||
var i = 0
|
|
||||||
var length = sonsLen(n)
|
|
||||||
r.res = toRope("{")
|
r.res = toRope("{")
|
||||||
while i < length:
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if i > 0: app(r.res, ", ")
|
if i > 0: app(r.res, ", ")
|
||||||
if (n.sons[i].kind != nkSym):
|
var it = n.sons[i]
|
||||||
internalError(n.sons[i].info, "genRecordConstr")
|
if it.kind == nkExprColonExpr: it = it.sons[1]
|
||||||
gen(p, n.sons[i + 1], a)
|
gen(p, it, a)
|
||||||
r.com = mergeExpr(r.com, a.com)
|
r.com = mergeExpr(r.com, a.com)
|
||||||
appf(r.res, "$1: $2", [mangleName(n.sons[i].sym), a.res])
|
appf(r.res, "Field$1: $2", [i.toRope, a.res])
|
||||||
inc(i, 2)
|
r.res.app("}")
|
||||||
|
|
||||||
proc genConv(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genConv(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
var dest = skipTypes(n.typ, abstractVarRange)
|
var dest = skipTypes(n.typ, abstractVarRange)
|
||||||
|
|
@ -1414,9 +1453,6 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
genSym(p, n.sons[namePos], r2)
|
genSym(p, n.sons[namePos], r2)
|
||||||
else:
|
else:
|
||||||
genLineDir(p, n, r)
|
genLineDir(p, n, r)
|
||||||
if n.sons[0].kind == nkSym:
|
|
||||||
if n.sons[0].sym.loc.r == nil:
|
|
||||||
n.sons[0].sym.loc.r = toRope(n.sons[0].sym.name.s)
|
|
||||||
gen(p, n, r)
|
gen(p, n, r)
|
||||||
app(r.res, ';' & tnl)
|
app(r.res, ';' & tnl)
|
||||||
|
|
||||||
|
|
@ -1460,7 +1496,7 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
genCall(p, n, r)
|
genCall(p, n, r)
|
||||||
of nkCurly: genSetConstr(p, n, r)
|
of nkCurly: genSetConstr(p, n, r)
|
||||||
of nkBracket: genArrayConstr(p, n, r)
|
of nkBracket: genArrayConstr(p, n, r)
|
||||||
of nkPar: genRecordConstr(p, n, r)
|
of nkPar: genTupleConstr(p, n, r)
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r)
|
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r)
|
||||||
of nkAddr, nkHiddenAddr: genAddr(p, n, r)
|
of nkAddr, nkHiddenAddr: genAddr(p, n, r)
|
||||||
of nkDerefExpr, nkHiddenDeref: genDeref(p, n, r)
|
of nkDerefExpr, nkHiddenDeref: genDeref(p, n, r)
|
||||||
|
|
@ -1477,8 +1513,14 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
of nkStmtListExpr: genStmtListExpr(p, n, r)
|
of nkStmtListExpr: genStmtListExpr(p, n, r)
|
||||||
of nkEmpty: nil
|
of nkEmpty: nil
|
||||||
of nkLambdaKinds:
|
of nkLambdaKinds:
|
||||||
# XXX not correct, as we need to put it into the proper scope!
|
let s = n.sons[namePos].sym
|
||||||
gen(p, n.sons[namePos], r)
|
discard mangleName(s)
|
||||||
|
r.res = s.loc.r
|
||||||
|
if lfNoDecl in s.loc.flags or s.magic != mNone or isGenericRoutine(s): nil
|
||||||
|
elif not p.g.generatedSyms.containsOrIncl(s.id):
|
||||||
|
var r2: TCompRes
|
||||||
|
genProc(p, s, r2)
|
||||||
|
app(r.com, mergeStmt(r2))
|
||||||
of nkMetaNode: gen(p, n.sons[0], r)
|
of nkMetaNode: gen(p, n.sons[0], r)
|
||||||
of nkType: r.res = genTypeInfo(p, n.typ)
|
of nkType: r.res = genTypeInfo(p, n.typ)
|
||||||
else: InternalError(n.info, "gen: unknown node type: " & $n.kind)
|
else: InternalError(n.info, "gen: unknown node type: " & $n.kind)
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,9 @@ when has_LLVM_Backend:
|
||||||
proc CommandCompileToEcmaScript =
|
proc CommandCompileToEcmaScript =
|
||||||
incl(gGlobalOptions, optSafeCode)
|
incl(gGlobalOptions, optSafeCode)
|
||||||
setTarget(osEcmaScript, cpuEcmaScript)
|
setTarget(osEcmaScript, cpuEcmaScript)
|
||||||
initDefines()
|
#initDefines()
|
||||||
|
DefineSymbol("nimrod") # 'nimrod' is always defined
|
||||||
|
DefineSymbol("ecmascript")
|
||||||
semanticPasses()
|
semanticPasses()
|
||||||
registerPass(ecmasgenPass())
|
registerPass(ecmasgenPass())
|
||||||
compileProject()
|
compileProject()
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,11 @@ proc HandleCmdLine() =
|
||||||
formatFloat(epochTime() - start, ffDecimal, 3),
|
formatFloat(epochTime() - start, ffDecimal, 3),
|
||||||
formatSize(getTotalMem())])
|
formatSize(getTotalMem())])
|
||||||
if optRun in gGlobalOptions:
|
if optRun in gGlobalOptions:
|
||||||
|
if gCmd == cmdCompileToEcmaScript:
|
||||||
|
var ex = quoteIfContainsWhite(
|
||||||
|
completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir))
|
||||||
|
execExternalProgram("node " & ex & ' ' & arguments)
|
||||||
|
else:
|
||||||
var ex = quoteIfContainsWhite(
|
var ex = quoteIfContainsWhite(
|
||||||
changeFileExt(gProjectFull, exeExt).prependCurDir)
|
changeFileExt(gProjectFull, exeExt).prependCurDir)
|
||||||
execExternalProgram(ex & ' ' & arguments)
|
execExternalProgram(ex & ' ' & arguments)
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,7 @@ Define Effect
|
||||||
``useRealtimeGC`` Enables support of Nimrod's GC for *soft* realtime
|
``useRealtimeGC`` Enables support of Nimrod's GC for *soft* realtime
|
||||||
systems. See the documentation of the `gc <gc.html>`_
|
systems. See the documentation of the `gc <gc.html>`_
|
||||||
for further information.
|
for further information.
|
||||||
|
``nodejs`` The EcmaScript target is actually ``node.js``.
|
||||||
================== =========================================================
|
================== =========================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,10 @@ proc `!$`*(h: THash): THash {.inline.} =
|
||||||
proc hashData*(Data: Pointer, Size: int): THash =
|
proc hashData*(Data: Pointer, Size: int): THash =
|
||||||
## hashes an array of bytes of size `size`
|
## hashes an array of bytes of size `size`
|
||||||
var h: THash = 0
|
var h: THash = 0
|
||||||
|
when defined(ecmascript):
|
||||||
|
var p: cstring
|
||||||
|
asm """`p` = `Data`;"""
|
||||||
|
else:
|
||||||
var p = cast[cstring](Data)
|
var p = cast[cstring](Data)
|
||||||
var i = 0
|
var i = 0
|
||||||
var s = size
|
var s = size
|
||||||
|
|
@ -44,8 +48,23 @@ proc hashData*(Data: Pointer, Size: int): THash =
|
||||||
Dec(s)
|
Dec(s)
|
||||||
result = !$h
|
result = !$h
|
||||||
|
|
||||||
|
when defined(ecmascript):
|
||||||
|
var objectID = 0
|
||||||
|
|
||||||
proc hash*(x: Pointer): THash {.inline.} =
|
proc hash*(x: Pointer): THash {.inline.} =
|
||||||
## efficient hashing of pointers
|
## efficient hashing of pointers
|
||||||
|
when defined(ecmascript):
|
||||||
|
asm """
|
||||||
|
if (typeof `x` == "object") {
|
||||||
|
if ("_NimID" in `x`)
|
||||||
|
`result` = `x`["_NimID"];
|
||||||
|
else {
|
||||||
|
`result` = ++`objectID`;
|
||||||
|
`x`["_NimID"] = `result`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
else:
|
||||||
result = (cast[THash](x)) shr 3 # skip the alignment
|
result = (cast[THash](x)) shr 3 # skip the alignment
|
||||||
|
|
||||||
proc hash*(x: int): THash {.inline.} =
|
proc hash*(x: int): THash {.inline.} =
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,11 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
when defined(nodejs):
|
||||||
|
proc alert*(s: cstring) {.importc: "console.log", nodecl.}
|
||||||
|
else:
|
||||||
proc alert*(s: cstring) {.importc, nodecl.}
|
proc alert*(s: cstring) {.importc, nodecl.}
|
||||||
|
|
||||||
proc log*(s: cstring) {.importc: "console.log", nodecl.}
|
proc log*(s: cstring) {.importc: "console.log", nodecl.}
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -100,7 +104,7 @@ proc raiseException(e: ref E_Base, ename: cstring) {.
|
||||||
alert(buf)
|
alert(buf)
|
||||||
asm """throw `e`;"""
|
asm """throw `e`;"""
|
||||||
|
|
||||||
proc reraiseException() =
|
proc reraiseException() {.compilerproc, noStackFrame.} =
|
||||||
if excHandler == nil:
|
if excHandler == nil:
|
||||||
raise newException(ENoExceptionToReraise, "no exception to reraise")
|
raise newException(ENoExceptionToReraise, "no exception to reraise")
|
||||||
else:
|
else:
|
||||||
|
|
@ -295,6 +299,19 @@ type
|
||||||
setAttribute*: proc (name, value: cstring)
|
setAttribute*: proc (name, value: cstring)
|
||||||
setAttributeNode*: proc (attr: ref TNode)
|
setAttributeNode*: proc (attr: ref TNode)
|
||||||
|
|
||||||
|
when defined(nodejs):
|
||||||
|
proc ewriteln(x: cstring) = log(x)
|
||||||
|
|
||||||
|
proc rawEcho {.compilerproc, nostackframe.} =
|
||||||
|
asm """
|
||||||
|
var buf = "";
|
||||||
|
for (var i = 0; i < arguments.length; ++i) {
|
||||||
|
buf += `toEcmaStr`(arguments[i]);
|
||||||
|
}
|
||||||
|
console.log(buf);
|
||||||
|
"""
|
||||||
|
|
||||||
|
else:
|
||||||
var
|
var
|
||||||
document {.importc, nodecl.}: ref TDocument
|
document {.importc, nodecl.}: ref TDocument
|
||||||
|
|
||||||
|
|
@ -474,7 +491,7 @@ proc isFatPointer(ti: PNimType): bool =
|
||||||
|
|
||||||
proc NimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.}
|
proc NimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.}
|
||||||
|
|
||||||
proc NimCopyAux(dest, src: Pointer, n: ptr TNimNode) {.exportc.} =
|
proc NimCopyAux(dest, src: Pointer, n: ptr TNimNode) {.compilerproc.} =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkNone: sysAssert(false, "NimCopyAux")
|
of nkNone: sysAssert(false, "NimCopyAux")
|
||||||
of nkSlot:
|
of nkSlot:
|
||||||
|
|
@ -525,6 +542,37 @@ proc NimCopy(x: pointer, ti: PNimType): pointer =
|
||||||
else:
|
else:
|
||||||
result = x
|
result = x
|
||||||
|
|
||||||
|
proc genericReset(x: Pointer, ti: PNimType): pointer {.compilerproc.} =
|
||||||
|
case ti.kind
|
||||||
|
of tyPtr, tyRef, tyVar, tyNil:
|
||||||
|
if not isFatPointer(ti):
|
||||||
|
result = nil
|
||||||
|
else:
|
||||||
|
asm """
|
||||||
|
`result` = [null, 0];
|
||||||
|
"""
|
||||||
|
of tySet:
|
||||||
|
asm """
|
||||||
|
`result` = {};
|
||||||
|
"""
|
||||||
|
of tyTuple, tyObject:
|
||||||
|
if ti.kind == tyObject:
|
||||||
|
asm "`result` = {m_type: `ti`};"
|
||||||
|
else:
|
||||||
|
asm "`result` = {};"
|
||||||
|
of tySequence, tyOpenArray:
|
||||||
|
asm """
|
||||||
|
`result` = [];
|
||||||
|
"""
|
||||||
|
of tyArrayConstr, tyArray:
|
||||||
|
asm """
|
||||||
|
`result` = new Array(`x`.length);
|
||||||
|
for (var i = 0; i < `x`.length; ++i) {
|
||||||
|
`result`[i] = genericReset(`x`[i], `ti`.base);
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
else:
|
||||||
|
result = nil
|
||||||
|
|
||||||
proc ArrayConstr(len: int, value: pointer, typ: PNimType): pointer {.
|
proc ArrayConstr(len: int, value: pointer, typ: PNimType): pointer {.
|
||||||
noStackFrame, compilerproc.} =
|
noStackFrame, compilerproc.} =
|
||||||
|
|
@ -552,4 +600,13 @@ proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
|
||||||
raise newException(EInvalidObjectConversion, "invalid object conversion")
|
raise newException(EInvalidObjectConversion, "invalid object conversion")
|
||||||
x = x.base
|
x = x.base
|
||||||
|
|
||||||
|
proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
|
||||||
|
# checks if obj is of type subclass:
|
||||||
|
var x = obj
|
||||||
|
if x == subclass: return true # optimized fast path
|
||||||
|
while x != subclass:
|
||||||
|
if x == nil: return false
|
||||||
|
x = x.base
|
||||||
|
return true
|
||||||
|
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,22 @@ proc compileDebuggerTests(r: var TResults, options: string) =
|
||||||
compileSingleTest(r, "tools/nimgrep", options &
|
compileSingleTest(r, "tools/nimgrep", options &
|
||||||
" --debugger:on")
|
" --debugger:on")
|
||||||
|
|
||||||
|
# ------------------------- JS tests ------------------------------------------
|
||||||
|
|
||||||
|
proc runJsTests(r: var TResults, options: string) =
|
||||||
|
template test(filename: expr): stmt =
|
||||||
|
runSingleTest(r, filename, options & " -d:nodejs", targetJS)
|
||||||
|
runSingleTest(r, filename, options & " -d:nodejs -d:release", targetJS)
|
||||||
|
|
||||||
|
# tactiontable, texceptions, texcpt1, texcsub, tfinally, tfinally2,
|
||||||
|
# tfinally3
|
||||||
|
for t in os.walkFiles("tests/js/t*.nim"):
|
||||||
|
test(t)
|
||||||
|
test "tests/run/tactiontable"
|
||||||
|
test "tests/run/tmultim1"
|
||||||
|
test "tests/run/tmultim3"
|
||||||
|
test "tests/run/tmultim4"
|
||||||
|
|
||||||
# ------------------------- register special tests here -----------------------
|
# ------------------------- register special tests here -----------------------
|
||||||
proc runSpecialTests(r: var TResults, options: string) =
|
proc runSpecialTests(r: var TResults, options: string) =
|
||||||
runRodFiles(r, options)
|
runRodFiles(r, options)
|
||||||
|
|
|
||||||
|
|
@ -261,7 +261,10 @@ proc compileSingleTest(r: var TResults, test, options: string) =
|
||||||
r.addResult(t, given.msg, if given.err: reFailure else: reSuccess)
|
r.addResult(t, given.msg, if given.err: reFailure else: reSuccess)
|
||||||
if not given.err: inc(r.passed)
|
if not given.err: inc(r.passed)
|
||||||
|
|
||||||
proc runSingleTest(r: var TResults, test, options: string) =
|
type
|
||||||
|
TTarget = enum targetC, targetJS
|
||||||
|
|
||||||
|
proc runSingleTest(r: var TResults, test, options: string, target: TTarget) =
|
||||||
var test = test.addFileExt(".nim")
|
var test = test.addFileExt(".nim")
|
||||||
var t = extractFilename(test)
|
var t = extractFilename(test)
|
||||||
echo t
|
echo t
|
||||||
|
|
@ -275,9 +278,16 @@ proc runSingleTest(r: var TResults, test, options: string) =
|
||||||
if given.err:
|
if given.err:
|
||||||
r.addResult(t, "", given.msg, reFailure)
|
r.addResult(t, "", given.msg, reFailure)
|
||||||
else:
|
else:
|
||||||
var exeFile = changeFileExt(test, ExeExt)
|
var exeFile: string
|
||||||
|
if target == targetC:
|
||||||
|
exeFile = changeFileExt(test, ExeExt)
|
||||||
|
else:
|
||||||
|
let (dir, file, ext) = splitFile(test)
|
||||||
|
exeFile = dir / "nimcache" / file & ".js"
|
||||||
|
|
||||||
if existsFile(exeFile):
|
if existsFile(exeFile):
|
||||||
var (buf, exitCode) = execCmdEx(exeFile)
|
var (buf, exitCode) = execCmdEx(
|
||||||
|
(if target==targetJS: "node " else: "") & exeFile)
|
||||||
if exitCode != expected.ExitCode:
|
if exitCode != expected.ExitCode:
|
||||||
r.addResult(t, "exitcode: " & $expected.ExitCode,
|
r.addResult(t, "exitcode: " & $expected.ExitCode,
|
||||||
"exitcode: " & $exitCode, reFailure)
|
"exitcode: " & $exitCode, reFailure)
|
||||||
|
|
@ -291,6 +301,9 @@ proc runSingleTest(r: var TResults, test, options: string) =
|
||||||
else:
|
else:
|
||||||
r.addResult(t, expected.outp, "executable not found", reFailure)
|
r.addResult(t, expected.outp, "executable not found", reFailure)
|
||||||
|
|
||||||
|
proc runSingleTest(r: var TResults, test, options: string) =
|
||||||
|
runSingleTest(r, test, options, targetC)
|
||||||
|
|
||||||
proc run(r: var TResults, dir, options: string) =
|
proc run(r: var TResults, dir, options: string) =
|
||||||
for test in os.walkFiles(dir / "t*.nim"): runSingleTest(r, test, options)
|
for test in os.walkFiles(dir / "t*.nim"): runSingleTest(r, test, options)
|
||||||
|
|
||||||
|
|
@ -350,6 +363,12 @@ proc main() =
|
||||||
run(runRes, "tests/run", p.cmdLineRest.string)
|
run(runRes, "tests/run", p.cmdLineRest.string)
|
||||||
runSpecialTests(runRes, p.cmdLineRest.string)
|
runSpecialTests(runRes, p.cmdLineRest.string)
|
||||||
writeResults(runJson, runRes)
|
writeResults(runJson, runRes)
|
||||||
|
of "js":
|
||||||
|
var runRes = initResults()
|
||||||
|
if existsFile(runJSon):
|
||||||
|
runRes = readResults(runJson)
|
||||||
|
runJsTests(runRes, p.cmdLineRest.string)
|
||||||
|
writeResults(runJson, runRes)
|
||||||
of "merge":
|
of "merge":
|
||||||
var rejectRes = readResults(rejectJson)
|
var rejectRes = readResults(rejectJson)
|
||||||
var compileRes = readResults(compileJson)
|
var compileRes = readResults(compileJson)
|
||||||
|
|
|
||||||
5
todo.txt
5
todo.txt
|
|
@ -42,6 +42,10 @@ Bugs
|
||||||
version 0.9.XX
|
version 0.9.XX
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
- JS gen:
|
||||||
|
- document it
|
||||||
|
- test & fix bugs
|
||||||
|
|
||||||
- document nimdoc properly finally
|
- document nimdoc properly finally
|
||||||
- implement a warning message for shadowed 'result' variable
|
- implement a warning message for shadowed 'result' variable
|
||||||
- implement the high level optimizer
|
- implement the high level optimizer
|
||||||
|
|
@ -51,7 +55,6 @@ version 0.9.XX
|
||||||
- implicit ref/ptr->var conversion; the compiler may store an object
|
- implicit ref/ptr->var conversion; the compiler may store an object
|
||||||
implicitly on the heap for write barrier efficiency; better:
|
implicitly on the heap for write barrier efficiency; better:
|
||||||
proc specialization in the code gen
|
proc specialization in the code gen
|
||||||
- 'of' operator for JS backend
|
|
||||||
- tlastmod returns wrong results on BSD (Linux, MacOS X: works)
|
- tlastmod returns wrong results on BSD (Linux, MacOS X: works)
|
||||||
- nested tuple unpacking; tuple unpacking in non-var-context
|
- nested tuple unpacking; tuple unpacking in non-var-context
|
||||||
- 'nimrod def': does not always work?
|
- 'nimrod def': does not always work?
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue