JS backend: supports methods (untested)

This commit is contained in:
Araq 2011-10-28 00:14:19 +02:00
commit fe9bb1869d
2 changed files with 23 additions and 16 deletions

View file

@ -8,14 +8,14 @@
# #
# This is the EMCAScript (also known as JavaScript) code generator. # This is the EMCAScript (also known as JavaScript) code generator.
# **Invariant: each expression only occurs once in the generated # **Invariant: each expression occurs only once in the generated
# code!** # code!**
import import
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os, options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os,
times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils, times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils,
intsets intsets, cgmeth
proc ecmasgenPass*(): TPass proc ecmasgenPass*(): TPass
# implementation # implementation
@ -1290,31 +1290,30 @@ proc genProcBody(p: var TProc, prc: PSym, r: TCompRes): PRope =
" 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:
app(result, "framePtr = framePtr.prev;" & tnl) app(result, "framePtr = framePtr.prev;" & tnl)
proc genProc(oldProc: var TProc, n: PNode, r: var TCompRes) = proc genProc(oldProc: var TProc, prc: PSym, r: var TCompRes) =
var var
p: TProc p: TProc
resultSym: PSym resultSym: PSym
name, returnStmt, resultAsgn, header: PRope name, returnStmt, resultAsgn, header: PRope
a: TCompRes a: TCompRes
var prc = n.sons[namePos].sym initProc(p, oldProc.globals, oldProc.module, prc.ast, prc.options)
initProc(p, oldProc.globals, oldProc.module, n, prc.options)
returnStmt = nil returnStmt = nil
resultAsgn = nil resultAsgn = nil
name = mangleName(prc) name = mangleName(prc)
header = generateHeader(p, prc.typ) header = generateHeader(p, prc.typ)
if (prc.typ.sons[0] != nil) and not (sfPure in prc.flags): if (prc.typ.sons[0] != nil) and not (sfPure in prc.flags):
resultSym = n.sons[resultPos].sym resultSym = prc.ast.sons[resultPos].sym
resultAsgn = ropef("var $1 = $2;$n", [mangleName(resultSym), resultAsgn = ropef("var $1 = $2;$n", [mangleName(resultSym),
createVar(p, resultSym.typ, isIndirect(resultSym))]) createVar(p, resultSym.typ, isIndirect(resultSym))])
gen(p, n.sons[resultPos], a) gen(p, prc.ast.sons[resultPos], a)
if a.com != nil: appf(returnStmt, "$1;$n", [a.com]) if a.com != nil: appf(returnStmt, "$1;$n", [a.com])
returnStmt = ropef("return $1;$n", [a.res]) returnStmt = ropef("return $1;$n", [a.res])
genStmt(p, n.sons[codePos], r) genStmt(p, prc.ast.sons[codePos], r)
r.com = ropef("function $1($2) {$n$3$4$5}$n", r.com = ropef("function $1($2) {$n$3$4$5}$n",
[name, header, resultAsgn, genProcBody(p, prc, r), returnStmt]) [name, header, resultAsgn, genProcBody(p, prc, r), returnStmt])
r.res = nil r.res = nil
proc genStmtListExpr(p: var TProc, n: PNode, r: var TCompRes) = proc genStmtListExpr(p: var TProc, n: PNode, r: var TCompRes) =
var a: TCompRes var a: TCompRes
# watch out this trick: ``function () { stmtList; return expr; }()`` # watch out this trick: ``function () { stmtList; return expr; }()``
@ -1361,9 +1360,9 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
of nkProcDef, nkMethodDef, nkConverterDef: of nkProcDef, nkMethodDef, nkConverterDef:
if (n.sons[genericParamsPos].kind == nkEmpty): if (n.sons[genericParamsPos].kind == nkEmpty):
var prc = n.sons[namePos].sym var prc = n.sons[namePos].sym
if (n.sons[codePos].kind != nkEmpty) and not (lfNoDecl in prc.loc.flags): if (prc.ast.sons[codePos].kind != nkEmpty) and not (lfNoDecl in prc.loc.flags):
genProc(p, n, r) genProc(p, prc, r)
else: else:
discard mangleName(prc) discard mangleName(prc)
else: else:
genLineDir(p, n, r) genLineDir(p, n, r)
@ -1469,6 +1468,15 @@ proc myClose(b: PPassContext, n: PNode): PNode =
result = myProcess(b, n) result = myProcess(b, n)
var m = BModule(b) var m = BModule(b)
if sfMainModule in m.module.flags: if sfMainModule in m.module.flags:
var disp = generateMethodDispatchers()
for i in 0..sonsLen(disp)-1:
var
p: TProc
r: TCompRes
initProc(p, globals, m, nil, m.module.options)
genProc(p, disp.sons[i].sym, r)
app(p.globals.code, mergeStmt(r))
# write the file: # write the file:
var code = con(globals.typeInfo, globals.code) var code = con(globals.typeInfo, globals.code)
var outfile = changeFileExt(completeCFilePath(m.filename), "js") var outfile = changeFileExt(completeCFilePath(m.filename), "js")

View file

@ -10,8 +10,7 @@ Version 0.8.14
- eval context is per module; this way modularity is kept; global id generation - eval context is per module; this way modularity is kept; global id generation
macro can still be done once macros support basic IO (store current id in macro can still be done once macros support basic IO (store current id in
some file) some file)
- methods for JS backend (very easy to do!)
incremental compilation incremental compilation
----------------------- -----------------------