compilation cache: multi methods now work

This commit is contained in:
Araq
2011-10-24 00:56:47 +02:00
parent a702524ae4
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,
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

View File

@@ -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

View File

@@ -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) =

View File

@@ -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()

View File

@@ -1,16 +1,16 @@
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'
- fix actors.nim
- make threadvar efficient again on linux after testing
- test the sort implementation again
- document & test splicing; don't forget to test negative indexes
- implement lib/pure/memfiles properly
- 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
some file)
- methods for JS backend (very easy to do!)
incremental compilation
@@ -18,7 +18,6 @@ incremental compilation
- adapt thread var implementation to care about the new merge operation
- write test cases: needs test script support
- fix method generation
- test thread var
- test DLL interfacing!
- stress test with whole compiler
@@ -26,13 +25,14 @@ incremental compilation
- automate tests:
- test basic recompilation scheme
- test type converters
- test G, A, B example from the documentation
- test init sections
- test G, A, B example from the documentation; test init sections
- test method generation
version 0.9.0
=============
- test the sort implementation again
- const ptr/ref
- unsigned ints and bignums
- implement the high level optimizer