summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2015-01-14 13:57:59 +0100
committerAraq <rumpf_a@web.de>2015-01-14 13:57:59 +0100
commit33c587d06b0c24e571ac7f9b8ae3e565df1ab9f5 (patch)
tree058948ad6a52559eda9080a617530c95349a9a3a /compiler
parent8889fa9117cdb2b4b169396e53b0fd78988494cd (diff)
downloadNim-33c587d06b0c24e571ac7f9b8ae3e565df1ab9f5.tar.gz
patterns for 'importcpp' (still undocumented)
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ccgcalls.nim118
-rw-r--r--compiler/types.nim2
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 =