diff options
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/ast.nim | 29 | ||||
-rwxr-xr-x | compiler/cgmeth.nim | 22 | ||||
-rwxr-xr-x | compiler/main.nim | 1 | ||||
-rwxr-xr-x | compiler/rodwrite.nim | 5 |
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() |