diff options
author | Araq <rumpf_a@web.de> | 2015-01-14 13:57:59 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2015-01-14 13:57:59 +0100 |
commit | 33c587d06b0c24e571ac7f9b8ae3e565df1ab9f5 (patch) | |
tree | 058948ad6a52559eda9080a617530c95349a9a3a /compiler | |
parent | 8889fa9117cdb2b4b169396e53b0fd78988494cd (diff) | |
download | Nim-33c587d06b0c24e571ac7f9b8ae3e565df1ab9f5.tar.gz |
patterns for 'importcpp' (still undocumented)
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ccgcalls.nim | 118 | ||||
-rw-r--r-- | compiler/types.nim | 2 |
2 files changed, 92 insertions, 28 deletions
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 65244b3eb..64cdc789d 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -110,8 +110,7 @@ proc openArrayLoc(p: BProc, n: PNode): PRope = result = ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]) else: internalError("openArrayLoc: " & typeToString(a.t)) -proc genArgStringToCString(p: BProc, - n: PNode): PRope {.inline.} = +proc genArgStringToCString(p: BProc, n: PNode): PRope {.inline.} = var a: TLoc initLocExpr(p, n.sons[0], a) result = ropef("$1->data", [a.rdLoc]) @@ -218,40 +217,105 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = else: genCallPattern() +proc genCppArg(p: BProc; ri: PNode; i: int; typ: PType): PRope = + if i < sonsLen(typ): + # 'var T' is 'T&' in C++. This means we ignore the request of + # any nkHiddenAddr when it's a 'var T'. + assert(typ.n.sons[i].kind == nkSym) + if typ.sons[i].kind == tyVar and ri.sons[i].kind == nkHiddenAddr: + result = genArgNoParam(p, ri.sons[i][0]) + else: + result = genArg(p, ri.sons[i], typ.n.sons[i].sym) + else: + result = genArgNoParam(p, ri.sons[i]) + +proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): PRope = + var i = 0 + var j = 1 + while i < pat.len: + case pat[i] + of '@': + result.app genCppArg(p, ri, j, typ) + for k in j+1 .. < ri.len: + result.app(~", ") + result.app genCppArg(p, ri, k, typ) + inc i + of '#': + if pat[i+1] in {'+', '@'}: + let ri = ri[j] + if ri.kind in nkCallKinds: + let typ = skipTypes(ri.sons[0].typ, abstractInst) + if pat[i+1] == '+': result.app genArgNoParam(p, ri.sons[0]) + result.app(~"(") + result.app genCppArg(p, ri, 1, typ) + for k in j+1 .. < ri.len: + result.app(~", ") + result.app genCppArg(p, ri, k, typ) + result.app(~")") + else: + localError(ri.info, "call expression expected for C++ pattern") + inc i + else: + result.app genCppArg(p, ri, j, typ) + if pat[i+1] == '.': + let param = typ.n.sons[j].sym + if skipTypes(param.typ, {tyGenericInst}).kind == tyPtr: result.app(~"->") + else: result.app(~".") + inc i + inc j + of '\'': + inc i + let stars = i + while pat[i] == '*': inc i + if pat[i] in Digits: + let j = pat[i].ord - '0'.ord + var t = typ.sons[j] + for k in 1..i-stars: + if t != nil and t.len > 0: t = t.elemType + if t == nil: result.app(~"void") + else: result.app(getTypeDesc(p.module, t)) + else: + result.app(toRope($pat[i])) + inc i + proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) = var op, a: TLoc initLocExpr(p, ri.sons[0], op) - var pl: PRope = nil # getUniqueType() is too expensive here: var typ = skipTypes(ri.sons[0].typ, abstractInst) assert(typ.kind == tyProc) var length = sonsLen(ri) assert(sonsLen(typ) == sonsLen(typ.n)) - - var param = typ.n.sons[1].sym - if typ.sons[1].kind == tyVar and ri.sons[1].kind == nkHiddenAddr: - app(pl, genArgNoParam(p, ri.sons[1][0])) - else: - app(pl, genArg(p, ri.sons[1], param)) - - if skipTypes(param.typ, {tyGenericInst}).kind == tyPtr: app(pl, ~"->") - else: app(pl, ~".") - app(pl, op.r) - var params: PRope - for i in countup(2, length - 1): - if params != nil: params.app(~", ") - assert(sonsLen(typ) == sonsLen(typ.n)) - if i < sonsLen(typ): - # 'var T' is 'T&' in C++. This means we ignore the request of - # any nkHiddenAddr when it's a 'var T'. - assert(typ.n.sons[i].kind == nkSym) - if typ.sons[i].kind == tyVar and ri.sons[i].kind == nkHiddenAddr: - app(params, genArgNoParam(p, ri.sons[i][0])) - else: - app(params, genArg(p, ri.sons[i], typ.n.sons[i].sym)) + # don't call 'ropeToStr' here for efficiency: + let pat = ri.sons[0].sym.loc.r.data + internalAssert pat != nil + if pat.contains({'#', '(', '@', '\''}): + var pl = genPatternCall(p, ri, pat, typ) + # simpler version of 'fixupCall' that works with the pl+params combination: + var typ = skipTypes(ri.sons[0].typ, abstractInst) + if typ.sons[0] != nil: + if d.k == locNone: getTemp(p, typ.sons[0], d) + assert(d.t != nil) # generate an assignment to d: + var list: TLoc + initLoc(list, locCall, d.t, OnUnknown) + list.r = pl + genAssignment(p, d, list, {}) # no need for deep copying else: - app(params, genArgNoParam(p, ri.sons[i])) - fixupCall(p, le, ri, d, pl, params) + app(pl, ~";$n") + line(p, cpsStmts, pl) + else: + var pl: PRope = nil + var param = typ.n.sons[1].sym + app(pl, genCppArg(p, ri, 1, typ)) + if skipTypes(param.typ, {tyGenericInst}).kind == tyPtr: app(pl, ~"->") + else: app(pl, ~".") + app(pl, op.r) + var params: PRope + for i in countup(2, length - 1): + if params != nil: params.app(~", ") + assert(sonsLen(typ) == sonsLen(typ.n)) + app(params, genCppArg(p, ri, i, typ)) + fixupCall(p, le, ri, d, pl, params) proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) = # generates a crappy ObjC call diff --git a/compiler/types.nim b/compiler/types.nim index 4a77773e6..a07698012 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -141,7 +141,7 @@ proc elemType*(t: PType): PType = case t.kind of tyGenericInst, tyDistinct: result = elemType(lastSon(t)) of tyArray, tyArrayConstr: result = t.sons[1] - else: result = t.sons[0] + else: result = t.lastSon assert(result != nil) proc skipGeneric(t: PType): PType = |