compilation cache: multi methods now work
This commit is contained in:
parent
a702524ae4
commit
9fb97e24bf
5 changed files with 41 additions and 26 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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) =
|
||||||
|
|
|
||||||
|
|
@ -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()
|
|
||||||
|
|
|
||||||
10
todo.txt
10
todo.txt
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue