compilation cache: multi methods now work

This commit is contained in:
Araq 2011-10-24 00:56:47 +02:00
commit 9fb97e24bf
5 changed files with 41 additions and 26 deletions

View file

@ -13,9 +13,9 @@ import
msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists, msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists,
intsets, idgen intsets, idgen
const const
ImportTablePos* = 0 ImportTablePos* = 0 # imported symbols are at level 0
ModuleTablePos* = 1 ModuleTablePos* = 1 # module's top level symbols are at level 1
type type
TCallingConvention* = enum TCallingConvention* = enum
@ -173,20 +173,20 @@ type
nkStmtListType, # a statement list ending in a type; for macros nkStmtListType, # a statement list ending in a type; for macros
nkBlockType, # a statement block ending in a type; for macros nkBlockType, # a statement block ending in a type; for macros
# types as syntactic trees: # types as syntactic trees:
nkTypeOfExpr, nkTypeOfExpr, # type(1+2)
nkObjectTy, nkObjectTy, # object body
nkTupleTy, nkTupleTy, # tuple body
nkRecList, # list of object parts nkRecList, # list of object parts
nkRecCase, # case section of object nkRecCase, # case section of object
nkRecWhen, # when section of object nkRecWhen, # when section of object
nkRefTy, nkRefTy, # ``ref T``
nkPtrTy, nkPtrTy, # ``ptr T``
nkVarTy, nkVarTy, # ``var T``
nkConstTy, # ``const T`` nkConstTy, # ``const T``
nkMutableTy, # ``mutable T`` nkMutableTy, # ``mutable T``
nkDistinctTy, # distinct type nkDistinctTy, # distinct type
nkProcTy, nkProcTy, # proc type
nkEnumTy, nkEnumTy, # enum body
nkEnumFieldDef, # `ident = expr` in an enumeration nkEnumFieldDef, # `ident = expr` in an enumeration
nkReturnToken # token used for interpretation nkReturnToken # token used for interpretation
TNodeKinds* = set[TNodeKind] TNodeKinds* = set[TNodeKind]
@ -235,7 +235,8 @@ type
TSymFlags* = set[TSymFlag] TSymFlags* = set[TSymFlag]
const 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 type
TTypeKind* = enum # order is important! TTypeKind* = enum # order is important!
@ -246,7 +247,7 @@ type
tyGenericInvokation, # ``T[a, b]`` for types to invoke tyGenericInvokation, # ``T[a, b]`` for types to invoke
tyGenericBody, # ``T[a, b, body]`` last parameter is the body tyGenericBody, # ``T[a, b, body]`` last parameter is the body
tyGenericInst, # ``T[a, b, realInstance]`` instantiated generic type tyGenericInst, # ``T[a, b, realInstance]`` instantiated generic type
tyGenericParam, # ``a`` in the example tyGenericParam, # ``a`` in the above patterns
tyDistinct, tyDistinct,
tyEnum, tyEnum,
tyOrdinal, # misnamed: should become 'tyConstraint' tyOrdinal, # misnamed: should become 'tyConstraint'
@ -575,7 +576,7 @@ const
pragmasPos* = 3 pragmasPos* = 3
codePos* = 4 codePos* = 4
resultPos* = 5 resultPos* = 5
dispatcherPos* = 6 dispatcherPos* = 6 # caution: if method has no 'result' it can be position 5!
# creator procs: # creator procs:
proc NewSym*(symKind: TSymKind, Name: PIdent, owner: PSym): PSym proc NewSym*(symKind: TSymKind, Name: PIdent, owner: PSym): PSym

View file

@ -34,9 +34,11 @@ proc genConv(n: PNode, d: PType, downcast: bool): PNode =
proc methodCall*(n: PNode): PNode = proc methodCall*(n: PNode): PNode =
result = n result = n
# replace ordinary method by dispatcher method:
var disp = lastSon(result.sons[0].sym.ast).sym var disp = lastSon(result.sons[0].sym.ast).sym
result.sons[0].sym = disp 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) result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true)
# save for incremental compilation: # save for incremental compilation:
@ -67,24 +69,36 @@ proc sameMethodBucket(a, b: PSym): bool =
return return
result = true 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) = proc methodDef*(s: PSym, fromCache: bool) =
var L = len(gMethods) var L = len(gMethods)
for i in countup(0, L - 1): for i in countup(0, L - 1):
if sameMethodBucket(gMethods[i][0], s): if sameMethodBucket(gMethods[i][0], s):
add(gMethods[i], s) # store a symbol to the dispatcher: add(gMethods[i], s)
addSon(s.ast, lastSon(gMethods[i][0].ast)) attachDispatcher(s, lastSon(gMethods[i][0].ast))
return return
add(gMethods, @[s]) add(gMethods, @[s])
# create a new dispatcher: # create a new dispatcher:
if not fromCache: if not fromCache:
var disp = copySym(s) var disp = copySym(s)
incl(disp.flags, sfDispatcher)
excl(disp.flags, sfExported)
disp.typ = copyType(disp.typ, disp.typ.owner, false) 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 if disp.typ.callConv == ccInline: disp.typ.callConv = ccDefault
disp.ast = copyTree(s.ast) disp.ast = copyTree(s.ast)
disp.ast.sons[codePos] = ast.emptyNode disp.ast.sons[codePos] = ast.emptyNode
if s.typ.sons[0] != nil: if s.typ.sons[0] != nil:
disp.ast.sons[resultPos].sym = copySym(s.ast.sons[resultPos].sym) 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 = proc relevantCol(methods: TSymSeq, col: int): bool =
# returns true iff the position is relevant # returns true iff the position is relevant

View file

@ -103,6 +103,7 @@ proc CommandGenDepend(filename: string) =
proc CommandCheck(filename: string) = proc CommandCheck(filename: string) =
msgs.gErrorMax = high(int) # do not stop after first error msgs.gErrorMax = high(int) # do not stop after first error
semanticPasses() # use an empty backend for semantic checking only semanticPasses() # use an empty backend for semantic checking only
registerPass(rodwrite.rodwritePass())
compileProject(filename) compileProject(filename)
proc CommandCompileToC(filename: string) = proc CommandCompileToC(filename: string) =

View file

@ -322,7 +322,7 @@ proc addToIndex(w: var TIndex, key, val: int) =
w.lastIdxVal = val w.lastIdxVal = val
IiTablePut(w.tab, key, val) IiTablePut(w.tab, key, val)
var debugWritten: TIntSet #var debugWritten = initIntSet()
proc symStack(w: PRodWriter) = proc symStack(w: PRodWriter) =
var i = 0 var i = 0
@ -351,7 +351,7 @@ proc symStack(w: PRodWriter) =
if s.kind == skConverter: if s.kind == skConverter:
if w.converters.len != 0: add(w.converters, ' ') if w.converters.len != 0: add(w.converters, ' ')
encodeVInt(s.id, 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, ' ') if w.methods.len != 0: add(w.methods, ' ')
encodeVInt(s.id, w.methods) encodeVInt(s.id, w.methods)
elif IiTableGet(w.imports.tab, s.id) == invalidKey: elif IiTableGet(w.imports.tab, s.id) == invalidKey:
@ -569,4 +569,3 @@ proc rodwritePass(): TPass =
result.close = myClose result.close = myClose
result.process = process result.process = process
debugWritten = initIntSet()

View file

@ -1,16 +1,16 @@
Version 0.8.14 Version 0.8.14
============== ==============
- optimize unused constants away (affected by HLO) - optimize unused constants away (affected by HLO); get rid of nfAllConst
- 'let x = y' - 'let x = y'
- fix actors.nim - fix actors.nim
- make threadvar efficient again on linux after testing - make threadvar efficient again on linux after testing
- test the sort implementation again
- document & test splicing; don't forget to test negative indexes - document & test splicing; don't forget to test negative indexes
- implement lib/pure/memfiles properly - implement lib/pure/memfiles properly
- eval context is per module; this way modularity is kept; global id generation - eval context is per module; this way modularity is kept; global id generation
macro can still be done once macros support basic IO (store current id in macro can still be done once macros support basic IO (store current id in
some file) some file)
- methods for JS backend (very easy to do!)
incremental compilation incremental compilation
@ -18,7 +18,6 @@ incremental compilation
- adapt thread var implementation to care about the new merge operation - adapt thread var implementation to care about the new merge operation
- write test cases: needs test script support - write test cases: needs test script support
- fix method generation
- test thread var - test thread var
- test DLL interfacing! - test DLL interfacing!
- stress test with whole compiler - stress test with whole compiler
@ -26,13 +25,14 @@ incremental compilation
- automate tests: - automate tests:
- test basic recompilation scheme - test basic recompilation scheme
- test type converters - test type converters
- test G, A, B example from the documentation - test G, A, B example from the documentation; test init sections
- test init sections - test method generation
version 0.9.0 version 0.9.0
============= =============
- test the sort implementation again
- const ptr/ref - const ptr/ref
- unsigned ints and bignums - unsigned ints and bignums
- implement the high level optimizer - implement the high level optimizer