# # # The Nim Compiler # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # ## This module implements the merge operation of 2 different C files. This ## is needed for incremental compilation. import ast, astalgo, ropes, options, strutils, nimlexbase, msgs, cgendata, rodutils, intsets, platform, llstream, tables, sighashes, pathutils # Careful! Section marks need to contain a tabulator so that they cannot # be part of C string literals. const CFileSectionNames: array[TCFileSection, string] = [ cfsMergeInfo: "", cfsHeaders: "NIM_merge_HEADERS", cfsForwardTypes: "NIM_merge_FORWARD_TYPES", cfsTypes: "NIM_merge_TYPES", cfsSeqTypes: "NIM_merge_SEQ_TYPES", cfsFieldInfo: "NIM_merge_FIELD_INFO", cfsTypeInfo: "NIM_merge_TYPE_INFO", cfsProcHeaders: "NIM_merge_PROC_HEADERS", cfsVars: "NIM_merge_VARS", cfsData: "NIM_merge_DATA", cfsProcs: "NIM_merge_PROCS", cfsInitProc: "NIM_merge_INIT_PROC", cfsTypeInit1: "NIM_merge_TYPE_INIT1", cfsTypeInit2: "NIM_merge_TYPE_INIT2", cfsTypeInit3: "NIM_merge_TYPE_INIT3", cfsDebugInit: "NIM_merge_DEBUG_INIT", cfsDynLibInit: "NIM_merge_DYNLIB_INIT", cfsDynLibDeinit: "NIM_merge_DYNLIB_DEINIT", ] CProcSectionNames: array[TCProcSection, string] = [ cpsLocals: "NIM_merge_PROC_LOCALS", cpsInit: "NIM_merge_PROC_INIT", cpsStmts: "NIM_merge_PROC_BODY" ] NimMergeEndMark = "/*\tNIM_merge_END:*/" proc genSectionStart*(fs: TCFileSection; conf: ConfigRef): Rope = if compilationCachePresent(conf): result = nil add(result, "\n/*\t") add(result, CFileSectionNames[fs]) add(result, ":*/\n") proc genSectionEnd*(fs: TCFileSection; conf: ConfigRef): Rope = if compilationCachePresent(conf): result = rope(NimMergeEndMark & "\n") proc genSectionStart*(ps: TCProcSection; conf: ConfigRef): Rope = if compilationCachePresent(conf): result = rope("") add(result, "\n/*\t") add(result, CProcSectionNames[ps]) add(result, ":*/\n") proc genSectionEnd*(ps: TCProcSection; conf: ConfigRef): Rope = if compilationCachePresent(conf): result = rope(NimMergeEndMark & "\n") proc writeTypeCache(a: TypeCache, s: var string) = var i = 0 for id, value in pairs(a): if i == 10: i = 0 s.add('\L') else: s.add(' ') encodeStr($id, s) s.add(':') encodeStr($value, s) inc i s.add('}') proc writeIntSet(a: IntSet, s: var string) = var i = 0 for x in items(a): if i == 10: i = 0 s.add('\L') else: s.add(' ') encodeVInt(x, s) inc i s.add('}') proc genMergeInfo*(m: BModule): Rope = if not compilationCachePresent(m.config): return nil var s = "/*\tNIM_merge_INFO:\n" s.add("typeCache:{") writeTypeCache(m.typeCache, s) s.add("declared:{") writeIntSet(m.declaredThings, s) when false: s.add("typeInfo:{") writeIntSet(m.typeInfoMarker, s) s.add("labels:") encodeVInt(m.labels, s) s.add(" flags:") encodeVInt(cast[int](m.flags), s) s.add("\n*/") result = s.rope template `^`(pos: int): untyped = L.buf[pos] proc skipWhite(L: var TBaseLexer) = var pos = L.bufpos while true: case ^pos of CR: pos = nimlexbase.handleCR(L, pos) of LF: pos = nimlexbase.handleLF(L, pos) of ' ': inc pos else: break L.bufpos = pos proc skipUnti