implemented 'emit' pragma

This commit is contained in:
Araq 2011-01-07 00:17:18 +01:00
commit e008630838
10 changed files with 108 additions and 74 deletions

View file

@ -1,7 +1,7 @@
# #
# #
# Maintenance program for Nimrod # Maintenance program for Nimrod
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -18,7 +18,7 @@ const
+-----------------------------------------------------------------+ +-----------------------------------------------------------------+
| Maintenance program for Nimrod | | Maintenance program for Nimrod |
| Version $1| | Version $1|
| (c) 2010 Andreas Rumpf | | (c) 2011 Andreas Rumpf |
+-----------------------------------------------------------------+ +-----------------------------------------------------------------+
Build time: $2, $3 Build time: $2, $3

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -213,34 +213,6 @@ proc genBreakStmt(p: BProc, t: PNode) =
genLineDir(p, t) genLineDir(p, t)
appf(p.s[cpsStmts], "goto LA$1;$n", [toRope(p.blocks[idx].id)]) 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 = proc getRaiseFrmt(p: BProc): string =
if gCmd == cmdCompileToCpp: if gCmd == cmdCompileToCpp:
result = "throw #nimException($1, $2);$n" result = "throw #nimException($1, $2);$n"
@ -605,6 +577,42 @@ proc genTryStmt(p: BProc, t: PNode) =
genStmts(p, t.sons[i].sons[0]) genStmts(p, t.sons[i].sons[0])
appcg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint]) 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 var
breakPointId: int = 0 breakPointId: int = 0
gBreakpoints: PRope # later the breakpoints are inserted into the main proc 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 var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
if key.kind == nkIdent: if key.kind == nkIdent:
case whichKeyword(key.ident) case whichKeyword(key.ident)
of wEmit:
genEmit(p, it)
of wBreakpoint: of wBreakpoint:
genBreakPoint(p, it) genBreakPoint(p, it)
of wDeadCodeElim: of wDeadCodeElim:

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -715,15 +715,15 @@ proc genConstPrototype(m: BModule, sym: PSym) =
proc getFileHeader(cfilenoext: string): PRope = proc getFileHeader(cfilenoext: string): PRope =
if optCompileOnly in gGlobalOptions: if optCompileOnly in gGlobalOptions:
result = ropeff("/* Generated by Nimrod Compiler v$1 */$n" & 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" & "; Generated by Nimrod Compiler v$1$n" &
"; (c) 2010 Andreas Rumpf$n", [toRope(versionAsString)]) "; (c) 2011 Andreas Rumpf$n", [toRope(versionAsString)])
else: else:
result = ropeff("/* Generated by Nimrod Compiler v$1 */$n" & 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", "/* Command for C compiler:$n $5 */$n",
"; Generated by Nimrod Compiler v$1$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), "; Command for LLVM compiler:$n $5$n", [toRope(versionAsString),
toRope(platform.OS[targetOS].name), toRope(platform.OS[targetOS].name),
toRope(platform.CPU[targetCPU].name), toRope(platform.CPU[targetCPU].name),

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -27,7 +27,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdlinePass, info: TLineInfo)
const const
HelpMessage = "Nimrod Compiler Version $1 (" & compileDate & ") [$2: $3]" & 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 const
Usage = """ Usage = """
@ -182,10 +182,10 @@ proc ProcessOnOffSwitchG(op: TGlobalOptions, arg: string, pass: TCmdlinePass,
else: liMessage(info, errOnOrOffExpectedButXFound, arg) else: liMessage(info, errOnOrOffExpectedButXFound, arg)
proc ExpectArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = 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) = 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, proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
info: TLineInfo) = info: TLineInfo) =

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -11,7 +11,8 @@
import import
os, platform, condsyms, ast, astalgo, idents, semdata, msgs, rnimsyn, 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 const
FirstCallConv* = wNimcall FirstCallConv* = wNimcall
@ -33,7 +34,7 @@ const
wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal,
wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop, wBreakpoint, wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop, wBreakpoint,
wCheckpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wFloatChecks, wCheckpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wFloatChecks,
wInfChecks, wNanChecks, wPragma} wInfChecks, wNanChecks, wPragma, wEmit}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wPure, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wPure,
wDeprecated, wExtern} wDeprecated, wExtern}
@ -323,6 +324,37 @@ proc PragmaCheckpoint(c: PContext, n: PNode) =
inc(info.line) # next line is affected! inc(info.line) # next line is affected!
msgs.addCheckpoint(info) 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) = proc noVal(n: PNode) =
if n.kind == nkExprColonExpr: invalidPragma(n) if n.kind == nkExprColonExpr: invalidPragma(n)
@ -477,6 +509,7 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
assert(sym != nil) assert(sym != nil)
if sym.typ == nil: invalidPragma(it) if sym.typ == nil: invalidPragma(it)
sym.typ.callConv = wordToCallConv(k) sym.typ.callConv = wordToCallConv(k)
of wEmit: PragmaEmit(c, it)
else: invalidPragma(it) else: invalidPragma(it)
else: invalidPragma(it) else: invalidPragma(it)
else: processNote(c, it) else: processNote(c, it)

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -96,35 +96,10 @@ proc semBlock(c: PContext, n: PNode): PNode =
Dec(c.p.nestedBlockCounter) Dec(c.p.nestedBlockCounter)
proc semAsm(con: PContext, n: PNode): PNode = proc semAsm(con: PContext, n: PNode): PNode =
result = n
checkSonsLen(n, 2) checkSonsLen(n, 2)
var marker = pragmaAsm(con, n.sons[0]) var marker = pragmaAsm(con, n.sons[0])
if marker == '\0': marker = '`' # default marker if marker == '\0': marker = '`' # default marker
case n.sons[1].kind result = semAsmOrEmit(con, n, marker)
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 semWhile(c: PContext, n: PNode): PNode = proc semWhile(c: PContext, n: PNode): PNode =
result = n result = n

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -57,7 +57,7 @@ type
wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty, wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty,
wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wJs, wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wJs,
wRst2html, wRst2tex, wI, wRst2html, wRst2tex, wI,
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit
TSpecialWords* = set[TSpecialWord] TSpecialWords* = set[TSpecialWord]
@ -104,7 +104,7 @@ const
"compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm", "compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm",
"pretty", "doc", "gendepend", "listdef", "check", "parse", "scan", "pretty", "doc", "gendepend", "listdef", "check", "parse", "scan",
"js", "rst2html", "rst2tex", "i", "js", "rst2html", "rst2tex", "i",
"write", "putenv", "prependenv", "appendenv", "threadvar"] "write", "putenv", "prependenv", "appendenv", "threadvar", "emit"]
proc whichKeyword*(id: PIdent): TSpecialWord proc whichKeyword*(id: PIdent): TSpecialWord
proc whichKeyword*(id: String): TSpecialWord proc whichKeyword*(id: String): TSpecialWord

View file

@ -19,6 +19,7 @@ tconstr2.nim;69
tcontinuexc.nim;ECcaught tcontinuexc.nim;ECcaught
tcopy.nim;TEMP=C:\Programs\xyz\bin tcopy.nim;TEMP=C:\Programs\xyz\bin
tcurrncy.nim;25 tcurrncy.nim;25
temit.nim;509
texcsub.nim;caught! texcsub.nim;caught!
texplicitgeneric1.nim;Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13 texplicitgeneric1.nim;Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13
tfinally.nim;came here 3 tfinally.nim;came here 3

1 tack.nim 125
19 tcontinuexc.nim ECcaught
20 tcopy.nim TEMP=C:\Programs\xyz\bin
21 tcurrncy.nim 25
22 temit.nim 509
23 texcsub.nim caught!
24 texplicitgeneric1.nim Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13
25 tfinally.nim came here 3

View file

@ -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()

View file

@ -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>`_. Version 0.8.12 has been released! Get it `here <download.html>`_.
@ -32,6 +32,7 @@ Additions
``\title``, ``\white``. ``\title``, ``\white``.
- Pegs support the new built-in ``\skip`` operation. - Pegs support the new built-in ``\skip`` operation.
- Source code filters are now properly documented. - Source code filters are now properly documented.
- Added ``emit`` pragma for direct code generator control.
2010-10-20 Version 0.8.10 released 2010-10-20 Version 0.8.10 released