diff options
author | Araq <rumpf_a@web.de> | 2011-01-07 00:17:18 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-01-07 00:17:18 +0100 |
commit | e008630838f545a04334ee71a5d6c52469fed056 (patch) | |
tree | 32fd06e7c0a4eb519d313c9535f0c61be0239378 | |
parent | 1e25aa365b3eef6b8a52ca115a4f27e37432577a (diff) | |
download | Nim-e008630838f545a04334ee71a5d6c52469fed056.tar.gz |
implemented 'emit' pragma
-rw-r--r-- | koch.nim | 4 | ||||
-rwxr-xr-x | rod/ccgstmts.nim | 68 | ||||
-rwxr-xr-x | rod/cgen.nim | 10 | ||||
-rwxr-xr-x | rod/commands.nim | 8 | ||||
-rwxr-xr-x | rod/pragmas.nim | 39 | ||||
-rwxr-xr-x | rod/semstmts.nim | 29 | ||||
-rwxr-xr-x | rod/wordrecg.nim | 6 | ||||
-rwxr-xr-x | tests/accept/run/spec.csv | 1 | ||||
-rw-r--r-- | tests/accept/run/temit.nim | 14 | ||||
-rwxr-xr-x | web/news.txt | 3 |
10 files changed, 108 insertions, 74 deletions
diff --git a/koch.nim b/koch.nim index 4df8edbed..9e0ea1a54 100644 --- a/koch.nim +++ b/koch.nim @@ -1,7 +1,7 @@ # # # Maintenance program for Nimrod -# (c) Copyright 2010 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -18,7 +18,7 @@ const +-----------------------------------------------------------------+ | Maintenance program for Nimrod | | Version $1| -| (c) 2010 Andreas Rumpf | +| (c) 2011 Andreas Rumpf | +-----------------------------------------------------------------+ Build time: $2, $3 diff --git a/rod/ccgstmts.nim b/rod/ccgstmts.nim index b888b44c6..f98a59580 100755 --- a/rod/ccgstmts.nim +++ b/rod/ccgstmts.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2010 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -213,34 +213,6 @@ proc genBreakStmt(p: BProc, t: PNode) = genLineDir(p, t) appf(p.s[cpsStmts], "goto LA$1;$n", [toRope(p.blocks[idx].id)]) -proc genAsmStmt(p: BProc, t: PNode) = - var - sym: PSym - r, s: PRope - a: TLoc - genLineDir(p, t) - assert(t.kind == nkAsmStmt) - s = nil - for i in countup(0, sonsLen(t) - 1): - case t.sons[i].Kind - of nkStrLit..nkTripleStrLit: - app(s, t.sons[i].strVal) - of nkSym: - sym = t.sons[i].sym - if sym.kind in {skProc, skMethod}: - initLocExpr(p, t.sons[i], a) - app(s, rdLoc(a)) - else: - r = sym.loc.r - if r == nil: - # if no name has already been given, - # it doesn't matter much: - r = mangleName(sym) - sym.loc.r = r # but be consequent! - app(s, r) - else: InternalError(t.sons[i].info, "genAsmStmt()") - appf(p.s[cpsStmts], CC[ccompiler].asmStmtFrmt, [s]) - proc getRaiseFrmt(p: BProc): string = if gCmd == cmdCompileToCpp: result = "throw #nimException($1, $2);$n" @@ -605,6 +577,42 @@ proc genTryStmt(p: BProc, t: PNode) = genStmts(p, t.sons[i].sons[0]) appcg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint]) +proc genAsmOrEmitStmt(p: BProc, t: PNode): PRope = + for i in countup(0, sonsLen(t) - 1): + case t.sons[i].Kind + of nkStrLit..nkTripleStrLit: + app(result, t.sons[i].strVal) + of nkSym: + var sym = t.sons[i].sym + if sym.kind in {skProc, skMethod}: + var a: TLoc + initLocExpr(p, t.sons[i], a) + app(result, rdLoc(a)) + else: + var r = sym.loc.r + if r == nil: + # if no name has already been given, + # it doesn't matter much: + r = mangleName(sym) + sym.loc.r = r # but be consequent! + app(result, r) + else: InternalError(t.sons[i].info, "genAsmOrEmitStmt()") + +proc genAsmStmt(p: BProc, t: PNode) = + assert(t.kind == nkAsmStmt) + genLineDir(p, t) + var s = genAsmOrEmitStmt(p, t) + appf(p.s[cpsStmts], CC[ccompiler].asmStmtFrmt, [s]) + +proc genEmit(p: BProc, t: PNode) = + genLineDir(p, t) + var s = genAsmOrEmitStmt(p, t.sons[1]) + if p.prc == nil: + # top level emit pragma? + app(p.module.s[cfsProcs], s) + else: + app(p.s[cpsStmts], s) + var breakPointId: int = 0 gBreakpoints: PRope # later the breakpoints are inserted into the main proc @@ -630,6 +638,8 @@ proc genPragma(p: BProc, n: PNode) = var key = if it.kind == nkExprColonExpr: it.sons[0] else: it if key.kind == nkIdent: case whichKeyword(key.ident) + of wEmit: + genEmit(p, it) of wBreakpoint: genBreakPoint(p, it) of wDeadCodeElim: diff --git a/rod/cgen.nim b/rod/cgen.nim index d4592c185..d57d5250a 100755 --- a/rod/cgen.nim +++ b/rod/cgen.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2010 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -715,15 +715,15 @@ proc genConstPrototype(m: BModule, sym: PSym) = proc getFileHeader(cfilenoext: string): PRope = if optCompileOnly in gGlobalOptions: result = ropeff("/* Generated by Nimrod Compiler v$1 */$n" & - "/* (c) 2010 Andreas Rumpf */$n", + "/* (c) 2011 Andreas Rumpf */$n", "; Generated by Nimrod Compiler v$1$n" & - "; (c) 2010 Andreas Rumpf$n", [toRope(versionAsString)]) + "; (c) 2011 Andreas Rumpf$n", [toRope(versionAsString)]) else: result = ropeff("/* Generated by Nimrod Compiler v$1 */$n" & - "/* (c) 2010 Andreas Rumpf */$n" & "/* Compiled for: $2, $3, $4 */$n" & + "/* (c) 2011 Andreas Rumpf */$n" & "/* Compiled for: $2, $3, $4 */$n" & "/* Command for C compiler:$n $5 */$n", "; Generated by Nimrod Compiler v$1$n" & - "; (c) 2010 Andreas Rumpf$n" & "; Compiled for: $2, $3, $4$n" & + "; (c) 2011 Andreas Rumpf$n" & "; Compiled for: $2, $3, $4$n" & "; Command for LLVM compiler:$n $5$n", [toRope(versionAsString), toRope(platform.OS[targetOS].name), toRope(platform.CPU[targetCPU].name), diff --git a/rod/commands.nim b/rod/commands.nim index b47bbf1bb..c5648afe5 100755 --- a/rod/commands.nim +++ b/rod/commands.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2010 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -27,7 +27,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) const HelpMessage = "Nimrod Compiler Version $1 (" & compileDate & ") [$2: $3]" & - "\n" & "Copyright (c) 2004-2010 by Andreas Rumpf" & "\n" + "\n" & "Copyright (c) 2004-2011 by Andreas Rumpf" & "\n" const Usage = """ @@ -182,10 +182,10 @@ proc ProcessOnOffSwitchG(op: TGlobalOptions, arg: string, pass: TCmdlinePass, else: liMessage(info, errOnOrOffExpectedButXFound, arg) proc ExpectArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = - if (arg == ""): liMessage(info, errCmdLineArgExpected, switch) + if arg == "": liMessage(info, errCmdLineArgExpected, switch) proc ExpectNoArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = - if (arg != ""): liMessage(info, errCmdLineNoArgExpected, switch) + if arg != "": liMessage(info, errCmdLineNoArgExpected, switch) proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass, info: TLineInfo) = diff --git a/rod/pragmas.nim b/rod/pragmas.nim index afbdbb5f4..d19c8d58e 100755 --- a/rod/pragmas.nim +++ b/rod/pragmas.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2010 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -11,7 +11,8 @@ import os, platform, condsyms, ast, astalgo, idents, semdata, msgs, rnimsyn, - wordrecg, ropes, options, strutils, lists, extccomp, math, magicsys, trees + wordrecg, ropes, options, strutils, lists, extccomp, math, magicsys, trees, + rodread const FirstCallConv* = wNimcall @@ -33,7 +34,7 @@ const wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal, wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop, wBreakpoint, wCheckpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wFloatChecks, - wInfChecks, wNanChecks, wPragma} + wInfChecks, wNanChecks, wPragma, wEmit} lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wPure, wDeprecated, wExtern} @@ -323,6 +324,37 @@ proc PragmaCheckpoint(c: PContext, n: PNode) = inc(info.line) # next line is affected! msgs.addCheckpoint(info) +proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode = + case n.sons[1].kind + of nkStrLit, nkRStrLit, nkTripleStrLit: + result = copyNode(n) + var str = n.sons[1].strVal + if str == "": liMessage(n.info, errEmptyAsm) + # now parse the string literal and substitute symbols: + var a = 0 + while true: + var b = strutils.find(str, marker, a) + var sub = if b < 0: copy(str, a) else: copy(str, a, b - 1) + if sub != "": addSon(result, newStrNode(nkStrLit, sub)) + if b < 0: break + var c = strutils.find(str, marker, b + 1) + if c < 0: sub = copy(str, b + 1) + else: sub = copy(str, b + 1, c - 1) + if sub != "": + var e = SymtabGet(con.tab, getIdent(sub)) + if e != nil: + if e.kind == skStub: loadStub(e) + addSon(result, newSymNode(e)) + else: + addSon(result, newStrNode(nkStrLit, sub)) + if c < 0: break + a = c + 1 + else: illFormedAst(n) + +proc PragmaEmit(c: PContext, n: PNode) = + discard getStrLitNode(c, n) + n.sons[1] = semAsmOrEmit(c, n, '`') + proc noVal(n: PNode) = if n.kind == nkExprColonExpr: invalidPragma(n) @@ -477,6 +509,7 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) = assert(sym != nil) if sym.typ == nil: invalidPragma(it) sym.typ.callConv = wordToCallConv(k) + of wEmit: PragmaEmit(c, it) else: invalidPragma(it) else: invalidPragma(it) else: processNote(c, it) diff --git a/rod/semstmts.nim b/rod/semstmts.nim index 95974e7be..0546c24dd 100755 --- a/rod/semstmts.nim +++ b/rod/semstmts.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2010 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -96,35 +96,10 @@ proc semBlock(c: PContext, n: PNode): PNode = Dec(c.p.nestedBlockCounter) proc semAsm(con: PContext, n: PNode): PNode = - result = n checkSonsLen(n, 2) var marker = pragmaAsm(con, n.sons[0]) if marker == '\0': marker = '`' # default marker - case n.sons[1].kind - of nkStrLit, nkRStrLit, nkTripleStrLit: - result = copyNode(n) - var str = n.sons[1].strVal - if str == "": liMessage(n.info, errEmptyAsm) - # now parse the string literal and substitute symbols: - var a = 0 - while true: - var b = strutils.find(str, marker, a) - var sub = if b < 0: copy(str, a) else: copy(str, a, b - 1) - if sub != "": addSon(result, newStrNode(nkStrLit, sub)) - if b < 0: break - var c = strutils.find(str, marker, b + 1) - if c < 0: sub = copy(str, b + 1) - else: sub = copy(str, b + 1, c - 1) - if sub != "": - var e = SymtabGet(con.tab, getIdent(sub)) - if e != nil: - if e.kind == skStub: loadStub(e) - addSon(result, newSymNode(e)) - else: - addSon(result, newStrNode(nkStrLit, sub)) - if c < 0: break - a = c + 1 - else: illFormedAst(n) + result = semAsmOrEmit(con, n, marker) proc semWhile(c: PContext, n: PNode): PNode = result = n diff --git a/rod/wordrecg.nim b/rod/wordrecg.nim index c64985846..42be7994b 100755 --- a/rod/wordrecg.nim +++ b/rod/wordrecg.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2010 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -57,7 +57,7 @@ type wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty, wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wJs, wRst2html, wRst2tex, wI, - wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar + wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit TSpecialWords* = set[TSpecialWord] @@ -104,7 +104,7 @@ const "compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm", "pretty", "doc", "gendepend", "listdef", "check", "parse", "scan", "js", "rst2html", "rst2tex", "i", - "write", "putenv", "prependenv", "appendenv", "threadvar"] + "write", "putenv", "prependenv", "appendenv", "threadvar", "emit"] proc whichKeyword*(id: PIdent): TSpecialWord proc whichKeyword*(id: String): TSpecialWord diff --git a/tests/accept/run/spec.csv b/tests/accept/run/spec.csv index 377c78a58..4bb94ed74 100755 --- a/tests/accept/run/spec.csv +++ b/tests/accept/run/spec.csv @@ -19,6 +19,7 @@ tconstr2.nim;69 tcontinuexc.nim;ECcaught tcopy.nim;TEMP=C:\Programs\xyz\bin tcurrncy.nim;25 +temit.nim;509 texcsub.nim;caught! texplicitgeneric1.nim;Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13 tfinally.nim;came here 3 diff --git a/tests/accept/run/temit.nim b/tests/accept/run/temit.nim new file mode 100644 index 000000000..81f9b53ae --- /dev/null +++ b/tests/accept/run/temit.nim @@ -0,0 +1,14 @@ +# Test the new ``emit`` pragma: + +{.emit: """ +static int cvariable = 420; + +""".} + +proc embedsC() {.pure.} = + var nimrodVar = 89 + {.emit: """fprintf(stdout, "%d\n", cvariable + (int)`nimrodVar`);""".} + +embedsC() + + diff --git a/web/news.txt b/web/news.txt index 77b557558..80405e62e 100755 --- a/web/news.txt +++ b/web/news.txt @@ -3,7 +3,7 @@ News ==== -2010-XX-XX Version 0.8.12 released +2011-XX-XX Version 0.8.12 released ================================== Version 0.8.12 has been released! Get it `here <download.html>`_. @@ -32,6 +32,7 @@ Additions ``\title``, ``\white``. - Pegs support the new built-in ``\skip`` operation. - Source code filters are now properly documented. +- Added ``emit`` pragma for direct code generator control. 2010-10-20 Version 0.8.10 released |