c2nim: rewritten symbol exporting code

This commit is contained in:
Andreas Rumpf
2010-07-22 20:07:49 +02:00
parent e6bc065cc5
commit 704663738a
4 changed files with 44 additions and 90 deletions

View File

@@ -13,7 +13,7 @@
# XXX standalone structs and unions!
# XXX header pragma for struct and union fields!
# XXX rewrite symbol export handling!
# XXX "cast" bug!
import
os, llstream, rnimsyn, clex, idents, strutils, pegs, ast, astalgo, msgs,
@@ -74,8 +74,6 @@ proc ParseUnit*(p: var TParser): PNode
proc openParser*(p: var TParser, filename: string, inputStream: PLLStream,
options = newParserOptions())
proc closeParser*(p: var TParser)
proc exSymbol*(n: var PNode)
proc fixRecordDef*(n: var PNode)
# implementation
@@ -134,8 +132,8 @@ proc parseMacroArguments(p: var TParser): seq[seq[ref TToken]] =
result[L].add(p.tok)
of pxParRi:
# end of arguments?
if i[pxParLe] == 0: break
dec(i[pxParLe])
if i[pxParLe] == 0 and i[pxBracketLe] == 0 and i[pxCurlyLe] == 0: break
if i[pxParLe] > 0: dec(i[pxParLe])
result[L].add(p.tok)
of pxBracketRi, pxCurlyRi:
kind = pred(kind, 3)
@@ -144,7 +142,6 @@ proc parseMacroArguments(p: var TParser): seq[seq[ref TToken]] =
of pxComma:
if i[pxParLe] == 0 and i[pxBracketLe] == 0 and i[pxCurlyLe] == 0:
# next argument: comma is not part of the argument
rawGetTok(p)
result.add(@[])
inc(L)
else:
@@ -298,8 +295,16 @@ proc addImportToPragma(pragmas: PNode, ident: string, p: TParser) =
else:
addSon(pragmas, newIdentStrLitPair("header", p.options.header, p))
proc mangledIdentAndImport(ident: string, p: TParser): PNode =
result = mangledIdent(ident, p)
proc exportSym(p: TParser, i: PNode): PNode =
assert i.kind == nkIdent
if p.scopeCounter == 0:
result = newNodeI(nkPostfix, i.info)
addSon(result, newIdentNode(getIdent("*"), i.info), i)
else:
result = i
proc varIdent(ident: string, p: TParser): PNode =
result = exportSym(p, mangledIdent(ident, p))
if p.scopeCounter > 0: return
if p.options.dynlibSym.len > 0 or p.options.header.len > 0:
var a = result
@@ -318,45 +323,17 @@ proc newBinary(opr: string, a, b: PNode, p: TParser): PNode =
addSon(result, newIdentNodeP(getIdent(opr), p))
addSon(result, a)
addSon(result, b)
# --------------- symbol exporter --------------------------------------------
proc identVis(p: var TParser): PNode =
# identifier with visability
var a = mangledIdent(p.tok.s, p)
result = newNodeP(nkPostfix, p)
addSon(result, newIdentNodeP("*", p))
addSon(result, a)
getTok(p)
proc skipIdent(p: var TParser): PNode =
expectIdent(p)
result = mangledIdent(p.tok.s, p)
getTok(p, result)
proc skipIdentExport(p: var TParser): PNode =
expectIdent(p)
result = exportSym(p, mangledIdent(p.tok.s, p))
getTok(p, result)
proc exSymbol(n: var PNode) =
case n.kind
of nkPostfix:
nil
of nkPragmaExpr:
exSymbol(n.sons[0])
of nkIdent, nkAccQuoted:
var a = newNodeI(nkPostFix, n.info)
addSon(a, newIdentNode(getIdent("*"), n.info))
addSon(a, n)
n = a
else: internalError(n.info, "exSymbol(): " & $n.kind)
proc fixRecordDef(n: var PNode) =
if n == nil: return
case n.kind
of nkRecCase:
fixRecordDef(n.sons[0])
for i in countup(1, sonsLen(n) - 1):
var length = sonsLen(n.sons[i])
fixRecordDef(n.sons[i].sons[length - 1])
of nkRecList, nkRecWhen, nkElse, nkOfBranch, nkElifBranch, nkObjectTy:
for i in countup(0, sonsLen(n) - 1): fixRecordDef(n.sons[i])
of nkIdentDefs:
for i in countup(0, sonsLen(n) - 3): exSymbol(n.sons[i])
of nkNilLit: nil
else: internalError(n.info, "fixRecordDef(): " & $n.kind)
proc addPragmaToIdent(ident: var PNode, pragma: PNode) =
var pragmasNode: PNode
if ident.kind != nkPragmaExpr:
@@ -371,25 +348,6 @@ proc addPragmaToIdent(ident: var PNode, pragma: PNode) =
InternalError(ident.info, "addPragmaToIdent")
addSon(pragmasNode, pragma)
proc exSymbols(n: PNode) =
if n == nil: return
case n.kind
of nkEmpty..nkNilLit: nil
of nkProcDef..nkIteratorDef: exSymbol(n.sons[namePos])
of nkWhenStmt:
for i in countup(0, sonsLen(n) - 1): exSymbols(lastSon(n.sons[i]))
of nkStmtList:
for i in countup(0, sonsLen(n) - 1): exSymbols(n.sons[i])
of nkVarSection, nkConstSection:
for i in countup(0, sonsLen(n) - 1): exSymbol(n.sons[i].sons[0])
of nkTypeSection:
for i in countup(0, sonsLen(n) - 1):
exSymbol(n.sons[i].sons[0])
if (n.sons[i].sons[2] != nil) and
(n.sons[i].sons[2].kind == nkObjectTy):
fixRecordDef(n.sons[i].sons[2])
else: nil
# --------------- parser -----------------------------------------------------
# We use this parsing rule: If it looks like a declaration, it is one. This
# avoids to build a symbol table, which can't be done reliably anyway for our
@@ -418,11 +376,6 @@ proc stmtKeyword(s: string): bool =
# ------------------- type desc -----------------------------------------------
proc skipIdent(p: var TParser): PNode =
expectIdent(p)
result = mangledIdent(p.tok.s, p)
getTok(p, result)
proc isIntType(s: string): bool =
case s
of "short", "int", "long", "float", "double", "signed", "unsigned":
@@ -519,7 +472,7 @@ proc parseStructBody(p: var TParser): PNode =
while true:
var def = newNodeP(nkIdentDefs, p)
var t = pointer(p, baseTyp)
var i = skipIdent(p)
var i = skipIdentExport(p)
t = parseTypeSuffix(p, t)
addSon(def, i, t, nil)
addSon(result, def)
@@ -615,7 +568,7 @@ proc parseFunctionPointerDecl(p: var TParser, rettyp: PNode): PNode =
parseCallConv(p, pragmas)
if p.tok.xkind == pxStar: getTok(p, params)
else: parMessage(p, errTokenExpected, "*")
var name = skipIdent(p)
var name = skipIdentExport(p)
eat(p, pxParRi, name)
parseFormalParams(p, params, pragmas)
addSon(procType, params)
@@ -651,11 +604,11 @@ proc otherTypeDef(p: var TParser, section, typ: PNode) =
of pxStar:
# typedef typ *b;
t = pointer(p, typ)
name = skipIdent(p)
name = skipIdentExport(p)
else:
# typedef typ name;
t = typ
name = skipIdent(p)
name = skipIdentExport(p)
t = parseTypeSuffix(p, t)
addTypeDef(section, name, t)
@@ -663,7 +616,7 @@ proc parseTrailingDefinedTypes(p: var TParser, section, typ: PNode) =
while p.tok.xkind == pxComma:
getTok(p, nil)
var newTyp = pointer(p, typ)
var newName = skipIdent(p)
var newName = skipIdentExport(p)
newTyp = parseTypeSuffix(p, newTyp)
addTypeDef(section, newName, newTyp)
@@ -697,7 +650,7 @@ proc parseTypeDef(p: var TParser): PNode =
if p.tok.xkind == pxCurlyLe:
var t = parseStruct(p)
var name = skipIdent(p)
addTypeDef(result, structPragmas(p, name), t)
addTypeDef(result, structPragmas(p, exportSym(p, name)), t)
parseTrailingDefinedTypes(p, result, name)
elif p.tok.xkind == pxSymbol:
# name to be defined or type "struct a", we don't know yet:
@@ -709,10 +662,10 @@ proc parseTypeDef(p: var TParser): PNode =
# typedef struct tagABC {} abc, *pabc;
# --> abc is a better type name than tagABC!
var name = skipIdent(p)
addTypeDef(result, structPragmas(p, name), t)
addTypeDef(result, structPragmas(p, exportSym(p, name)), t)
parseTrailingDefinedTypes(p, result, name)
else:
addTypeDef(result, structPragmas(p, nameOrType), t)
addTypeDef(result, structPragmas(p, exportSym(p, nameOrType)), t)
of pxSymbol:
# typedef struct a a?
if mangleName(p.tok.s, p) == nameOrType.ident.s:
@@ -732,7 +685,7 @@ proc parseTypeDef(p: var TParser): PNode =
var t = enumFields(p)
eat(p, pxCurlyRi, t)
var name = skipIdent(p)
addTypeDef(result, enumPragmas(p, name), t)
addTypeDef(result, enumPragmas(p, exportSym(p, name)), t)
parseTrailingDefinedTypes(p, result, name)
elif p.tok.xkind == pxSymbol:
# name to be defined or type "enum a", we don't know yet:
@@ -746,10 +699,10 @@ proc parseTypeDef(p: var TParser): PNode =
# typedef enum tagABC {} abc, *pabc;
# --> abc is a better type name than tagABC!
var name = skipIdent(p)
addTypeDef(result, enumPragmas(p, name), t)
addTypeDef(result, enumPragmas(p, exportSym(p, name)), t)
parseTrailingDefinedTypes(p, result, name)
else:
addTypeDef(result, enumPragmas(p, nameOrType), t)
addTypeDef(result, enumPragmas(p, exportSym(p, nameOrType)), t)
of pxSymbol:
# typedef enum a a?
if mangleName(p.tok.s, p) == nameOrType.ident.s:
@@ -798,7 +751,7 @@ proc parseVarDecl(p: var TParser, baseTyp, typ: PNode,
origName: string): PNode =
result = newNodeP(nkVarSection, p)
var def = newNodeP(nkIdentDefs, p)
addSon(def, mangledIdentAndImport(origName, p))
addSon(def, varIdent(origName, p))
addSon(def, parseTypeSuffix(p, typ))
addInitializer(p, def)
addSon(result, def)
@@ -808,7 +761,7 @@ proc parseVarDecl(p: var TParser, baseTyp, typ: PNode,
var t = pointer(p, baseTyp)
expectIdent(p)
def = newNodeP(nkIdentDefs, p)
addSon(def, mangledIdentAndImport(p.tok.s, p))
addSon(def, varIdent(p.tok.s, p))
getTok(p, def)
addSon(def, parseTypeSuffix(p, t))
addInitializer(p, def)
@@ -851,7 +804,7 @@ proc declaration(p: var TParser): PNode =
addSon(pragmas, newIdentNodeP("cdecl", p))
elif pfStdcall in p.options.flags:
addSon(pragmas, newIdentNodeP("stdcall", p))
addSon(result, name)
addSon(result, exportSym(p, name))
addSon(result, nil) # no generics
addSon(result, params)
addSon(result, pragmas)
@@ -883,7 +836,7 @@ proc enumSpecifier(p: var TParser): PNode =
getTok(p, result)
var i = 0
while true:
var name = skipIdent(p)
var name = skipIdentExport(p)
var val: PNode
if p.tok.xkind == pxAsgn:
getTok(p, name)
@@ -908,7 +861,7 @@ proc enumSpecifier(p: var TParser): PNode =
var t = newNodeP(nkTypeDef, p)
getTok(p, t)
var e = enumFields(p)
addSon(t, name, nil, e) # nil for generic params
addSon(t, exportSym(p, name), nil, e) # nil for generic params
addSon(result, t)
else:
parMessage(p, errTokenExpected, "{")
@@ -1537,5 +1490,4 @@ proc parseUnit(p: var TParser): PNode =
while p.tok.xkind != pxEof:
var s = statement(p)
if s != nil: embedStmts(result, s)
exSymbols(result)

View File

@@ -40,7 +40,7 @@ proc parseDefine(p: var TParser): PNode =
# a macro with parameters:
result = newNodeP(nkTemplateDef, p)
getTok(p)
addSon(result, skipIdent(p))
addSon(result, skipIdentExport(p))
eat(p, pxParLe)
var params = newNodeP(nkFormalParams, p)
# return type; not known yet:
@@ -68,7 +68,7 @@ proc parseDefine(p: var TParser): PNode =
while p.tok.xkind == pxDirective and p.tok.s == "define":
getTok(p) # skip #define
var c = newNodeP(nkConstDef, p)
addSon(c, skipIdent(p))
addSon(c, skipIdentExport(p))
addSon(c, nil)
skipStarCom(p, c)
if p.tok.xkind in {pxLineComment, pxNewLine, pxEof}:

View File

@@ -234,8 +234,6 @@ Limitations
* C's ``,`` operator (comma operator) is not supported.
* C's ``union`` has no equivalent in Nimrod.
* Standalone ``struct x {}`` declarations are not implemented. Put them into
a ``typedef``.
* The condition in a ``do while(condition)`` statement must be ``0``.
* Lots of other small issues...

View File

@@ -130,6 +130,7 @@ int IupConvertXYToPos(PIhandle ih, int x, int y);
#ifdef C2NIM
# def EXTERN(x) static x
# def TWO_ARGS(x, y) x* y
#endif
// parses now!
EXTERN(int) f(void);
@@ -141,6 +142,9 @@ int IupConvertXYToPos(PIhandle ih, int x, int y);
EXPORT int f(void);
EXPORT int g(void);
static TWO_ARGS(int, x) = TWO_ARGS(56, 45);
# define abc 34
# define xyz 42