JS codegen improvements; barely usable now
This commit is contained in:
parent
fe285b354d
commit
f2af2fb478
4 changed files with 71 additions and 25 deletions
|
|
@ -22,8 +22,8 @@ proc ecmasgenPass*(): TPass
|
||||||
|
|
||||||
type
|
type
|
||||||
TEcmasGen = object of TPassContext
|
TEcmasGen = object of TPassContext
|
||||||
filename*: string
|
filename: string
|
||||||
module*: PSym
|
module: PSym
|
||||||
|
|
||||||
BModule = ref TEcmasGen
|
BModule = ref TEcmasGen
|
||||||
TEcmasTypeKind = enum # necessary JS "types"
|
TEcmasTypeKind = enum # necessary JS "types"
|
||||||
|
|
@ -37,16 +37,16 @@ type
|
||||||
etyObject, # Ecmascript's reference to an object
|
etyObject, # Ecmascript's reference to an object
|
||||||
etyBaseIndex # base + index needed
|
etyBaseIndex # base + index needed
|
||||||
TCompRes{.final.} = object
|
TCompRes{.final.} = object
|
||||||
kind*: TEcmasTypeKind
|
kind: TEcmasTypeKind
|
||||||
com*: PRope # computation part
|
com: PRope # computation part
|
||||||
# address if this is a (address, index)-tuple
|
# address if this is a (address, index)-tuple
|
||||||
res*: PRope # result part; index if this is an
|
res: PRope # result part; index if this is an
|
||||||
# (address, index)-tuple
|
# (address, index)-tuple
|
||||||
|
|
||||||
TBlock{.final.} = object
|
TBlock{.final.} = object
|
||||||
id*: int # the ID of the label; positive means that it
|
id: int # the ID of the label; positive means that it
|
||||||
# has been used (i.e. the label should be emitted)
|
# has been used (i.e. the label should be emitted)
|
||||||
nestedTryStmts*: int # how many try statements is it nested into
|
nestedTryStmts: int # how many try statements is it nested into
|
||||||
isLoop: bool # whether it's a 'block' or 'while'
|
isLoop: bool # whether it's a 'block' or 'while'
|
||||||
|
|
||||||
TGlobals{.final.} = object
|
TGlobals{.final.} = object
|
||||||
|
|
@ -863,7 +863,14 @@ proc genArrayAddr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
r.res = mergeExpr(b)
|
r.res = mergeExpr(b)
|
||||||
|
|
||||||
proc genArrayAccess(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genArrayAccess(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
|
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 & ')')
|
||||||
r.kind = etyNone
|
r.kind = etyNone
|
||||||
r.res = ropef("$1[$2]", [r.com, r.res])
|
r.res = ropef("$1[$2]", [r.com, r.res])
|
||||||
r.com = nil
|
r.com = nil
|
||||||
|
|
@ -936,6 +943,9 @@ proc genSym(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
discard mangleName(s)
|
discard mangleName(s)
|
||||||
r.res = s.loc.r
|
r.res = s.loc.r
|
||||||
if lfNoDecl in s.loc.flags or s.magic != mNone or isGenericRoutine(s): nil
|
if lfNoDecl in s.loc.flags or s.magic != mNone or isGenericRoutine(s): nil
|
||||||
|
elif s.kind == skMethod and s.getBody.kind == nkEmpty:
|
||||||
|
# we cannot produce code for the dispatcher yet:
|
||||||
|
nil
|
||||||
elif sfForward in s.flags:
|
elif sfForward in s.flags:
|
||||||
p.g.forwarded.add(s)
|
p.g.forwarded.add(s)
|
||||||
elif not p.g.generatedSyms.containsOrIncl(s.id):
|
elif not p.g.generatedSyms.containsOrIncl(s.id):
|
||||||
|
|
@ -1032,8 +1042,9 @@ proc createVar(p: var TProc, typ: PType, indirect: bool): PRope =
|
||||||
app(result, "]")
|
app(result, "]")
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
result = toRope("{")
|
result = toRope("{")
|
||||||
var c = 0
|
for i in 0.. <t.sonslen:
|
||||||
app(result, createRecordVarAux(p, t.n, c))
|
if i > 0: app(result, ", ")
|
||||||
|
appf(result, "Field$1: $2", i.toRope, createVar(p, t.sons[i], false))
|
||||||
app(result, "}")
|
app(result, "}")
|
||||||
of tyObject:
|
of tyObject:
|
||||||
result = toRope("{")
|
result = toRope("{")
|
||||||
|
|
@ -1123,6 +1134,16 @@ proc genNew(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
if a.com != nil: appf(r.com, "$1;$n", [a.com])
|
if a.com != nil: appf(r.com, "$1;$n", [a.com])
|
||||||
appf(r.com, "$1 = $2;$n", [a.res, createVar(p, t, true)])
|
appf(r.com, "$1 = $2;$n", [a.res, createVar(p, t, true)])
|
||||||
|
|
||||||
|
proc genNewSeq(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
|
var x, y: TCompRes
|
||||||
|
gen(p, n.sons[1], x)
|
||||||
|
gen(p, n.sons[2], y)
|
||||||
|
if x.com != nil: appf(r.com, "$1;$n", [x.com])
|
||||||
|
if y.com != nil: appf(r.com, "$1;$n", [y.com])
|
||||||
|
var t = skipTypes(n.sons[1].typ, abstractVar).sons[0]
|
||||||
|
appf(r.com, "$1 = new Array($2); for (var i=0;i<$2;++i) {$1[i]=$3;}", [
|
||||||
|
x.res, y.res, createVar(p, t, false)])
|
||||||
|
|
||||||
proc genOrd(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genOrd(p: var TProc, 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)
|
||||||
|
|
@ -1168,7 +1189,7 @@ proc genRepr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
|
|
||||||
proc genOf(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genOf(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
var x: TCompRes
|
var x: TCompRes
|
||||||
let t = n.sons[2].typ
|
let t = skipTypes(n.sons[2].typ, abstractVarRange+{tyRef, tyPtr})
|
||||||
gen(p, n.sons[1], x)
|
gen(p, n.sons[1], x)
|
||||||
if tfFinal in t.flags:
|
if tfFinal in t.flags:
|
||||||
r.res = ropef("($1.m_type == $2)", [x.res, genTypeInfo(p, t)])
|
r.res = ropef("($1.m_type == $2)", [x.res, genTypeInfo(p, t)])
|
||||||
|
|
@ -1254,7 +1275,7 @@ proc genMagic(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
of mInSet: binaryExpr(p, n, r, "", "($1[$2] != undefined)")
|
of mInSet: binaryExpr(p, n, r, "", "($1[$2] != undefined)")
|
||||||
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: genNewSeq(p, n, r)
|
||||||
of mOf: genOf(p, n, r)
|
of mOf: genOf(p, n, r)
|
||||||
of mReset: genReset(p, n, r)
|
of mReset: genReset(p, n, r)
|
||||||
of mEcho: genEcho(p, n, r)
|
of mEcho: genEcho(p, n, r)
|
||||||
|
|
@ -1576,11 +1597,13 @@ proc myClose(b: PPassContext, n: PNode): PNode =
|
||||||
|
|
||||||
var disp = generateMethodDispatchers()
|
var disp = generateMethodDispatchers()
|
||||||
for i in 0..sonsLen(disp)-1:
|
for i in 0..sonsLen(disp)-1:
|
||||||
|
let prc = disp.sons[i].sym
|
||||||
|
if not globals.generatedSyms.containsOrIncl(prc.id):
|
||||||
var
|
var
|
||||||
p: TProc
|
p: TProc
|
||||||
r: TCompRes
|
r: TCompRes
|
||||||
initProc(p, globals, m, nil, m.module.options)
|
initProc(p, globals, m, nil, m.module.options)
|
||||||
genProc(p, disp.sons[i].sym, r)
|
genProc(p, prc, r)
|
||||||
app(p.g.code, mergeStmt(r))
|
app(p.g.code, mergeStmt(r))
|
||||||
|
|
||||||
# write the file:
|
# write the file:
|
||||||
|
|
|
||||||
23
tests/js/test1.nim
Normal file
23
tests/js/test1.nim
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
discard """
|
||||||
|
cmd: "nimrod js --hints:on $# $#"
|
||||||
|
output: "1261129"
|
||||||
|
"""
|
||||||
|
|
||||||
|
# This file tests the ECMAScript generator
|
||||||
|
|
||||||
|
import
|
||||||
|
dom, strutils
|
||||||
|
|
||||||
|
var
|
||||||
|
inputElement = "1123"
|
||||||
|
|
||||||
|
proc OnButtonClick(inputElement: string) {.exportc.} =
|
||||||
|
let v = $inputElement
|
||||||
|
if v.allCharsInSet(whiteSpace):
|
||||||
|
echo "only whitespace, hu?"
|
||||||
|
else:
|
||||||
|
var x = parseInt(v)
|
||||||
|
echo x*x
|
||||||
|
|
||||||
|
onButtonClick(inputElement)
|
||||||
|
|
||||||
|
|
@ -176,7 +176,7 @@ proc runJsTests(r: var TResults, options: string) =
|
||||||
runSingleTest(r, filename, options & " -d:nodejs", targetJS)
|
runSingleTest(r, filename, options & " -d:nodejs", targetJS)
|
||||||
runSingleTest(r, filename, options & " -d:nodejs -d:release", targetJS)
|
runSingleTest(r, filename, options & " -d:nodejs -d:release", targetJS)
|
||||||
|
|
||||||
# tactiontable, texceptions, texcpt1, texcsub, tfinally, tfinally2,
|
# texceptions, texcpt1, texcsub, tfinally, tfinally2,
|
||||||
# tfinally3
|
# tfinally3
|
||||||
for t in os.walkFiles("tests/js/t*.nim"):
|
for t in os.walkFiles("tests/js/t*.nim"):
|
||||||
test(t)
|
test(t)
|
||||||
|
|
|
||||||
2
todo.txt
2
todo.txt
|
|
@ -44,7 +44,7 @@ version 0.9.XX
|
||||||
|
|
||||||
- JS gen:
|
- JS gen:
|
||||||
- document it
|
- document it
|
||||||
- test & fix bugs
|
- fix exception handling
|
||||||
|
|
||||||
- document nimdoc properly finally
|
- document nimdoc properly finally
|
||||||
- implement a warning message for shadowed 'result' variable
|
- implement a warning message for shadowed 'result' variable
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue