summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ast.nim29
-rwxr-xr-xcompiler/cgmeth.nim22
-rwxr-xr-xcompiler/main.nim1
-rwxr-xr-xcompiler/rodwrite.nim5
4 files changed, 36 insertions, 21 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 01b70980d..9b2f210a3 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -13,9 +13,9 @@ import
   msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists, 
   intsets, idgen
 
-const 
-  ImportTablePos* = 0
-  ModuleTablePos* = 1
+const
+  ImportTablePos* = 0         # imported symbols are at level 0
+  ModuleTablePos* = 1         # module's top level symbols are at level 1
 
 type 
   TCallingConvention* = enum 
@@ -173,20 +173,20 @@ type
     nkStmtListType,       # a statement list ending in a type; for macros
     nkBlockType,          # a statement block ending in a type; for macros
                           # types as syntactic trees:
-    nkTypeOfExpr,
-    nkObjectTy,
-    nkTupleTy,
+    nkTypeOfExpr,         # type(1+2)
+    nkObjectTy,           # object body
+    nkTupleTy,            # tuple body
     nkRecList,            # list of object parts
     nkRecCase,            # case section of object
     nkRecWhen,            # when section of object
-    nkRefTy,
-    nkPtrTy,
-    nkVarTy,
+    nkRefTy,              # ``ref T``
+    nkPtrTy,              # ``ptr T``
+    nkVarTy,              # ``var T``
     nkConstTy,            # ``const T``
     nkMutableTy,          # ``mutable T``
     nkDistinctTy,         # distinct type
-    nkProcTy,
-    nkEnumTy,
+    nkProcTy,             # proc type
+    nkEnumTy,             # enum body
     nkEnumFieldDef,       # `ident = expr` in an enumeration
     nkReturnToken         # token used for interpretation
   TNodeKinds* = set[TNodeKind]
@@ -235,7 +235,8 @@ type
   TSymFlags* = set[TSymFlag]
 
 const
-  sfFakeConst* = sfDeadCodeElim # const cannot be put into a data section
+  sfFakeConst* = sfDeadCodeElim  # const cannot be put into a data section
+  sfDispatcher* = sfDeadCodeElim # copied method symbol is the dispatcher 
 
 type
   TTypeKind* = enum  # order is important!
@@ -246,7 +247,7 @@ type
     tyGenericInvokation, # ``T[a, b]`` for types to invoke
     tyGenericBody,       # ``T[a, b, body]`` last parameter is the body
     tyGenericInst,       # ``T[a, b, realInstance]`` instantiated generic type
-    tyGenericParam,      # ``a`` in the example
+    tyGenericParam,      # ``a`` in the above patterns
     tyDistinct,
     tyEnum,
     tyOrdinal,           # misnamed: should become 'tyConstraint'
@@ -575,7 +576,7 @@ const
   pragmasPos* = 3
   codePos* = 4
   resultPos* = 5
-  dispatcherPos* = 6
+  dispatcherPos* = 6 # caution: if method has no 'result' it can be position 5!
 
 # creator procs:
 proc NewSym*(symKind: TSymKind, Name: PIdent, owner: PSym): PSym
diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim
index 3c90f3343..e2c3c009c 100755
--- a/compiler/cgmeth.nim
+++ b/compiler/cgmeth.nim
@@ -34,9 +34,11 @@ proc genConv(n: PNode, d: PType, downcast: bool): PNode =
   
 proc methodCall*(n: PNode): PNode = 
   result = n
+  # replace ordinary method by dispatcher method: 
   var disp = lastSon(result.sons[0].sym.ast).sym
   result.sons[0].sym = disp
-  for i in countup(1, sonsLen(result) - 1): 
+  # change the arguments to up/downcasts to fit the dispatcher's parameters:
+  for i in countup(1, sonsLen(result)-1):
     result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true)
 
 # save for incremental compilation:
@@ -67,24 +69,36 @@ proc sameMethodBucket(a, b: PSym): bool =
       return 
   result = true
 
+proc attachDispatcher(s: PSym, dispatcher: PNode) =
+  var L = s.ast.len-1
+  var x = s.ast.sons[L]
+  if x.kind == nkSym and sfDispatcher in x.sym.flags:
+    # we've added a dispatcher already, so overwrite it
+    s.ast.sons[L] = dispatcher
+  else:
+    s.ast.add(dispatcher)
+
 proc methodDef*(s: PSym, fromCache: bool) =
   var L = len(gMethods)
   for i in countup(0, L - 1): 
     if sameMethodBucket(gMethods[i][0], s): 
-      add(gMethods[i], s)     # store a symbol to the dispatcher:
-      addSon(s.ast, lastSon(gMethods[i][0].ast))
+      add(gMethods[i], s)
+      attachDispatcher(s, lastSon(gMethods[i][0].ast))
       return 
   add(gMethods, @[s])
   # create a new dispatcher:
   if not fromCache:
     var disp = copySym(s)
+    incl(disp.flags, sfDispatcher)
+    excl(disp.flags, sfExported)
     disp.typ = copyType(disp.typ, disp.typ.owner, false)
+    # we can't inline the dispatcher itself (for now):
     if disp.typ.callConv == ccInline: disp.typ.callConv = ccDefault
     disp.ast = copyTree(s.ast)
     disp.ast.sons[codePos] = ast.emptyNode
     if s.typ.sons[0] != nil: 
       disp.ast.sons[resultPos].sym = copySym(s.ast.sons[resultPos].sym)
-    addSon(s.ast, newSymNode(disp))
+    attachDispatcher(s, newSymNode(disp))
 
 proc relevantCol(methods: TSymSeq, col: int): bool = 
   # returns true iff the position is relevant
diff --git a/compiler/main.nim b/compiler/main.nim
index f8c6860fd..7a0d016ce 100755
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -103,6 +103,7 @@ proc CommandGenDepend(filename: string) =
 proc CommandCheck(filename: string) = 
   msgs.gErrorMax = high(int)  # do not stop after first error
   semanticPasses()            # use an empty backend for semantic checking only
+  registerPass(rodwrite.rodwritePass())
   compileProject(filename)
 
 proc CommandCompileToC(filename: string) = 
diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim
index 0aa7b3b57..626d0382c 100755
--- a/compiler/rodwrite.nim
+++ b/compiler/rodwrite.nim
@@ -322,7 +322,7 @@ proc addToIndex(w: var TIndex, key, val: int) =
   w.lastIdxVal = val
   IiTablePut(w.tab, key, val)
 
-var debugWritten: TIntSet
+#var debugWritten = initIntSet()
 
 proc symStack(w: PRodWriter) =
   var i = 0
@@ -351,7 +351,7 @@ proc symStack(w: PRodWriter) =
         if s.kind == skConverter: 
           if w.converters.len != 0: add(w.converters, ' ')
           encodeVInt(s.id, w.converters)
-        elif s.kind == skMethod:
+        elif s.kind == skMethod and sfDispatcher notin s.flags:
           if w.methods.len != 0: add(w.methods, ' ')
           encodeVInt(s.id, w.methods)
       elif IiTableGet(w.imports.tab, s.id) == invalidKey: 
@@ -569,4 +569,3 @@ proc rodwritePass(): TPass =
     result.close = myClose
     result.process = process
 
-debugWritten = initIntSet()