diff options
author | Araq <rumpf_a@web.de> | 2011-04-12 01:13:42 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-04-12 01:13:42 +0200 |
commit | cd292568d775d55d9abb51e962882ecda12c03a9 (patch) | |
tree | 85451f0e1f17dc0463350915f12bdd0a82a73455 /nim/rodwrite.pas | |
parent | 46c41e43690cba9bc1caff6a994bb6915df8a1b7 (diff) | |
download | Nim-cd292568d775d55d9abb51e962882ecda12c03a9.tar.gz |
big repo cleanup
Diffstat (limited to 'nim/rodwrite.pas')
-rwxr-xr-x | nim/rodwrite.pas | 612 |
1 files changed, 0 insertions, 612 deletions
diff --git a/nim/rodwrite.pas b/nim/rodwrite.pas deleted file mode 100755 index c71eda7e3..000000000 --- a/nim/rodwrite.pas +++ /dev/null @@ -1,612 +0,0 @@ -// -// -// The Nimrod Compiler -// (c) Copyright 2008 Andreas Rumpf -// -// See the file "copying.txt", included in this -// distribution, for details about the copyright. -// -unit rodwrite; - -// This module is responsible for writing of rod files. Note that writing of -// rod files is a pass, reading of rod files is not! This is why reading and -// writing of rod files is split into two different modules. - -interface - -{$include 'config.inc'} - -uses - sysutils, nsystem, nos, options, strutils, nversion, ast, astalgo, msgs, - platform, condsyms, ropes, idents, crc, rodread, passes, importer; - -function rodwritePass(): TPass; - -implementation - -type - TRodWriter = object(TPassContext) - module: PSym; - crc: TCrc32; - options: TOptions; - defines: PRope; - inclDeps: PRope; - modDeps: PRope; - interf: PRope; - compilerProcs: PRope; - index, imports: TIndex; - converters: PRope; - init: PRope; - data: PRope; - filename: string; - sstack: TSymSeq; // a stack of symbols to process - tstack: TTypeSeq; // a stack of types to process - files: TStringSeq; - end; - PRodWriter = ^TRodWriter; - -function newRodWriter(const modfilename: string; crc: TCrc32; - module: PSym): PRodWriter; forward; -procedure addModDep(w: PRodWriter; const dep: string); forward; -procedure addInclDep(w: PRodWriter; const dep: string); forward; -procedure addInterfaceSym(w: PRodWriter; s: PSym); forward; -procedure addStmt(w: PRodWriter; n: PNode); forward; -procedure writeRod(w: PRodWriter); forward; - -function encodeStr(w: PRodWriter; const s: string): PRope; -begin - result := encode(s) -end; - -procedure processStacks(w: PRodWriter); forward; - -function getDefines: PRope; -var - it: TTabIter; - s: PSym; -begin - s := InitTabIter(it, gSymbols); - result := nil; - while s <> nil do begin - if s.position = 1 then begin - if result <> nil then app(result, ' '+''); - app(result, s.name.s); - end; - s := nextIter(it, gSymbols); - end -end; - -function fileIdx(w: PRodWriter; const filename: string): int; -var - i: int; -begin - for i := 0 to high(w.files) do begin - if w.files[i] = filename then begin result := i; exit end; - end; - result := length(w.files); - setLength(w.files, result+1); - w.files[result] := filename; -end; - -function newRodWriter(const modfilename: string; crc: TCrc32; - module: PSym): PRodWriter; -begin - new(result); -{@ignore} - fillChar(result^, sizeof(result^), 0); -{@emit - result.sstack := @[];} -{@emit - result.tstack := @[];} - InitIITable(result.index.tab); - InitIITable(result.imports.tab); - result.filename := modfilename; - result.crc := crc; - result.module := module; - result.defines := getDefines(); - result.options := options.gOptions; - {@emit result.files := @[];} -end; - -procedure addModDep(w: PRodWriter; const dep: string); -begin - if w.modDeps <> nil then app(w.modDeps, ' '+''); - app(w.modDeps, encodeInt(fileIdx(w, dep))); -end; - -const - rodNL = #10+''; - -procedure addInclDep(w: PRodWriter; const dep: string); -begin - app(w.inclDeps, encodeInt(fileIdx(w, dep))); - app(w.inclDeps, ' '+''); - app(w.inclDeps, encodeInt(crcFromFile(dep))); - app(w.inclDeps, rodNL); -end; - -procedure pushType(w: PRodWriter; t: PType); -var - L: int; -begin - // check so that the stack does not grow too large: - if IiTableGet(w.index.tab, t.id) = invalidKey then begin - L := length(w.tstack); - setLength(w.tstack, L+1); - w.tstack[L] := t; - end -end; - -procedure pushSym(w: PRodWriter; s: PSym); -var - L: int; -begin - // check so that the stack does not grow too large: - if IiTableGet(w.index.tab, s.id) = invalidKey then begin - L := length(w.sstack); - setLength(w.sstack, L+1); - w.sstack[L] := s; - end -end; - -function encodeNode(w: PRodWriter; const fInfo: TLineInfo; n: PNode): PRope; -var - i: int; - f: TNodeFlags; -begin - if n = nil then begin - // nil nodes have to be stored too: - result := toRope('()'); exit - end; - result := toRope('('+''); - app(result, encodeInt(ord(n.kind))); - // we do not write comments for now - // Line information takes easily 20% or more of the filesize! Therefore we - // omit line information if it is the same as the father's line information: - if (finfo.fileIndex <> n.info.fileIndex) then - appf(result, '?$1,$2,$3', [encodeInt(n.info.col), encodeInt(n.info.line), - encodeInt(fileIdx(w, toFilename(n.info)))]) - else if (finfo.line <> n.info.line) then - appf(result, '?$1,$2', [encodeInt(n.info.col), encodeInt(n.info.line)]) - else if (finfo.col <> n.info.col) then - appf(result, '?$1', [encodeInt(n.info.col)]); - // No need to output the file index, as this is the serialization of one - // file. - f := n.flags * PersistentNodeFlags; - if f <> {@set}[] then - appf(result, '$$$1', [encodeInt({@cast}int32(f))]); - if n.typ <> nil then begin - appf(result, '^$1', [encodeInt(n.typ.id)]); - pushType(w, n.typ); - end; - case n.kind of - nkCharLit..nkInt64Lit: begin - if n.intVal <> 0 then - appf(result, '!$1', [encodeInt(n.intVal)]); - end; - nkFloatLit..nkFloat64Lit: begin - if n.floatVal <> 0.0 then - appf(result, '!$1', [encodeStr(w, toStringF(n.floatVal))]); - end; - nkStrLit..nkTripleStrLit: begin - if n.strVal <> '' then - appf(result, '!$1', [encodeStr(w, n.strVal)]); - end; - nkIdent: - appf(result, '!$1', [encodeStr(w, n.ident.s)]); - nkSym: begin - appf(result, '!$1', [encodeInt(n.sym.id)]); - pushSym(w, n.sym); - end; - else begin - for i := 0 to sonsLen(n)-1 do - app(result, encodeNode(w, n.info, n.sons[i])); - end - end; - app(result, ')'+''); -end; - -function encodeLoc(w: PRodWriter; const loc: TLoc): PRope; -begin - result := nil; - if loc.k <> low(loc.k) then - app(result, encodeInt(ord(loc.k))); - if loc.s <> low(loc.s) then - appf(result, '*$1', [encodeInt(ord(loc.s))]); - if loc.flags <> {@set}[] then - appf(result, '$$$1', [encodeInt({@cast}int32(loc.flags))]); - if loc.t <> nil then begin - appf(result, '^$1', [encodeInt(loc.t.id)]); - pushType(w, loc.t); - end; - if loc.r <> nil then - appf(result, '!$1', [encodeStr(w, ropeToStr(loc.r))]); - if loc.a <> 0 then - appf(result, '?$1', [encodeInt(loc.a)]); - if result <> nil then - result := ropef('<$1>', [result]); -end; - -function encodeType(w: PRodWriter; t: PType): PRope; -var - i: int; -begin - if t = nil then begin - // nil nodes have to be stored too: - result := toRope('[]'); exit - end; - result := nil; - if t.kind = tyForward then InternalError('encodeType: tyForward'); - app(result, encodeInt(ord(t.kind))); - appf(result, '+$1', [encodeInt(t.id)]); - if t.n <> nil then - app(result, encodeNode(w, UnknownLineInfo(), t.n)); - if t.flags <> {@set}[] then - appf(result, '$$$1', [encodeInt({@cast}int32(t.flags))]); - if t.callConv <> low(t.callConv) then - appf(result, '?$1', [encodeInt(ord(t.callConv))]); - if t.owner <> nil then begin - appf(result, '*$1', [encodeInt(t.owner.id)]); - pushSym(w, t.owner); - end; - if t.sym <> nil then begin - appf(result, '&$1', [encodeInt(t.sym.id)]); - pushSym(w, t.sym); - end; - if t.size <> -1 then appf(result, '/$1', [encodeInt(t.size)]); - if t.align <> 2 then appf(result, '=$1', [encodeInt(t.align)]); - if t.containerID <> 0 then - appf(result, '@$1', [encodeInt(t.containerID)]); - app(result, encodeLoc(w, t.loc)); - for i := 0 to sonsLen(t)-1 do begin - if t.sons[i] = nil then - app(result, '^()') - else begin - appf(result, '^$1', [encodeInt(t.sons[i].id)]); - pushType(w, t.sons[i]); - end - end; -end; - -function encodeLib(w: PRodWriter; lib: PLib): PRope; -begin - result := nil; - appf(result, '|$1', [encodeInt(ord(lib.kind))]); - appf(result, '|$1', [encodeStr(w, ropeToStr(lib.name))]); - appf(result, '|$1', [encodeStr(w, lib.path)]); -end; - -function encodeSym(w: PRodWriter; s: PSym): PRope; -var - codeAst: PNode; - col, line: PRope; -begin - codeAst := nil; - if s = nil then begin - // nil nodes have to be stored too: - result := toRope('{}'); exit - end; - result := nil; - app(result, encodeInt(ord(s.kind))); - appf(result, '+$1', [encodeInt(s.id)]); - appf(result, '&$1', [encodeStr(w, s.name.s)]); - if s.typ <> nil then begin - appf(result, '^$1', [encodeInt(s.typ.id)]); - pushType(w, s.typ); - end; - if s.info.col = int16(-1) then col := nil - else col := encodeInt(s.info.col); - if s.info.line = int16(-1) then line := nil - else line := encodeInt(s.info.line); - appf(result, '?$1,$2,$3', [col, line, - encodeInt(fileIdx(w, toFilename(s.info)))]); - if s.owner <> nil then begin - appf(result, '*$1', [encodeInt(s.owner.id)]); - pushSym(w, s.owner); - end; - if s.flags <> {@set}[] then - appf(result, '$$$1', [encodeInt({@cast}int32(s.flags))]); - if s.magic <> mNone then - appf(result, '@$1', [encodeInt(ord(s.magic))]); - if (s.ast <> nil) then begin - if not astNeeded(s) then begin - codeAst := s.ast.sons[codePos]; - s.ast.sons[codePos] := nil; - end; - app(result, encodeNode(w, s.info, s.ast)); - if codeAst <> nil then // restore code ast - s.ast.sons[codePos] := codeAst; - end; - if s.options <> w.options then - appf(result, '!$1', [encodeInt({@cast}int32(s.options))]); - if s.position <> 0 then - appf(result, '%$1', [encodeInt(s.position)]); - if s.offset <> -1 then - appf(result, '`$1', [encodeInt(s.offset)]); - app(result, encodeLoc(w, s.loc)); - if s.annex <> nil then - app(result, encodeLib(w, s.annex)); -end; - -procedure addToIndex(var w: TIndex; key, val: int); -begin - if key - w.lastIdxKey = 1 then begin - // we do not store a key-diff of 1 to safe space - app(w.r, encodeInt(val - w.lastIdxVal)); - app(w.r, rodNL); - end - else - appf(w.r, '$1 $2'+rodNL, [encodeInt(key - w.lastIdxKey), - encodeInt(val - w.lastIdxVal)]); - w.lastIdxKey := key; - w.lastIdxVal := val; - IiTablePut(w.tab, key, val); -end; - -var - debugWritten: TIntSet; - -procedure symStack(w: PRodWriter); -var - i, L: int; - s, m: PSym; -begin - i := 0; - while i < length(w.sstack) do begin - s := w.sstack[i]; - if IiTableGet(w.index.tab, s.id) = invalidKey then begin - m := getModule(s); - if m = nil then InternalError('symStack: module nil: ' + s.name.s); - if (m.id = w.module.id) or (sfFromGeneric in s.flags) then begin - // put definition in here - L := ropeLen(w.data); - addToIndex(w.index, s.id, L); - //intSetIncl(debugWritten, s.id); - app(w.data, encodeSym(w, s)); - app(w.data, rodNL); - if sfInInterface in s.flags then - appf(w.interf, '$1 $2'+rodNL, [encode(s.name.s), encodeInt(s.id)]); - if sfCompilerProc in s.flags then - appf(w.compilerProcs, '$1 $2'+rodNL, [encode(s.name.s), encodeInt(s.id)]); - if s.kind = skConverter then begin - if w.converters <> nil then app(w.converters, ' '+''); - app(w.converters, encodeInt(s.id)) - end - end - else if IiTableGet(w.imports.tab, s.id) = invalidKey then begin - addToIndex(w.imports, s.id, m.id); - //if not IntSetContains(debugWritten, s.id) then begin - // MessageOut(w.filename); - // debug(s.owner); - // debug(s); - // InternalError('BUG!!!!'); - //end - end - end; - inc(i); - end; - setLength(w.sstack, 0); -end; - -procedure typeStack(w: PRodWriter); -var - i, L: int; -begin - i := 0; - while i < length(w.tstack) do begin - if IiTableGet(w.index.tab, w.tstack[i].id) = invalidKey then begin - L := ropeLen(w.data); - addToIndex(w.index, w.tstack[i].id, L); - app(w.data, encodeType(w, w.tstack[i])); - app(w.data, rodNL); - end; - inc(i); - end; - setLength(w.tstack, 0); -end; - -procedure processStacks(w: PRodWriter); -begin - while (length(w.tstack) > 0) or (length(w.sstack) > 0) do begin - symStack(w); - typeStack(w); - end -end; - -procedure rawAddInterfaceSym(w: PRodWriter; s: PSym); -begin - pushSym(w, s); - processStacks(w); -end; - -procedure addInterfaceSym(w: PRodWriter; s: PSym); -begin - if w = nil then exit; - if [sfInInterface, sfCompilerProc] * s.flags <> [] then begin - rawAddInterfaceSym(w, s); - end -end; - -procedure addStmt(w: PRodWriter; n: PNode); -begin - app(w.init, encodeInt(ropeLen(w.data))); - app(w.init, rodNL); - app(w.data, encodeNode(w, UnknownLineInfo(), n)); - app(w.data, rodNL); - processStacks(w); -end; - -procedure writeRod(w: PRodWriter); -var - content: PRope; - i: int; -begin - processStacks(w); - // write header: - content := toRope('NIM:'); - app(content, toRope(FileVersion)); - app(content, rodNL); - app(content, toRope('ID:')); - app(content, encodeInt(w.module.id)); - app(content, rodNL); - app(content, toRope('CRC:')); - app(content, encodeInt(w.crc)); - app(content, rodNL); - app(content, toRope('OPTIONS:')); - app(content, encodeInt({@cast}int32(w.options))); - app(content, rodNL); - app(content, toRope('DEFINES:')); - app(content, w.defines); - app(content, rodNL); - app(content, toRope('FILES('+rodNL)); - for i := 0 to high(w.files) do begin - app(content, encode(w.files[i])); - app(content, rodNL); - end; - app(content, toRope(')'+rodNL)); - app(content, toRope('INCLUDES('+rodNL)); - app(content, w.inclDeps); - app(content, toRope(')'+rodNL)); - app(content, toRope('DEPS:')); - app(content, w.modDeps); - app(content, rodNL); - app(content, toRope('INTERF('+rodNL)); - app(content, w.interf); - app(content, toRope(')'+rodNL)); - app(content, toRope('COMPILERPROCS('+rodNL)); - app(content, w.compilerProcs); - app(content, toRope(')'+rodNL)); - app(content, toRope('INDEX('+rodNL)); - app(content, w.index.r); - app(content, toRope(')'+rodNL)); - app(content, toRope('IMPORTS('+rodNL)); - app(content, w.imports.r); - app(content, toRope(')'+rodNL)); - app(content, toRope('CONVERTERS:')); - app(content, w.converters); - app(content, toRope(rodNL)); - app(content, toRope('INIT('+rodNL)); - app(content, w.init); - app(content, toRope(')'+rodNL)); - app(content, toRope('DATA('+rodNL)); - app(content, w.data); - app(content, toRope(')'+rodNL)); - - //MessageOut('interf ' + ToString(ropeLen(w.interf))); - //MessageOut('index ' + ToString(ropeLen(w.indexRope))); - //MessageOut('init ' + ToString(ropeLen(w.init))); - //MessageOut('data ' + ToString(ropeLen(w.data))); - - writeRope(content, - completeGeneratedFilePath(changeFileExt(w.filename, 'rod'))); -end; - -function process(c: PPassContext; n: PNode): PNode; -var - i: int; - w: PRodWriter; - a: PNode; - s: PSym; -begin - result := n; - if c = nil then exit; - w := PRodWriter(c); - case n.kind of - nkStmtList: begin - for i := 0 to sonsLen(n)-1 do {@discard} process(c, n.sons[i]); - end; - nkTemplateDef, nkMacroDef: begin - s := n.sons[namePos].sym; - addInterfaceSym(w, s); - end; - nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef: begin - s := n.sons[namePos].sym; - if s = nil then InternalError(n.info, 'rodwrite.process'); - if (n.sons[codePos] <> nil) or (s.magic <> mNone) - or not (sfForward in s.flags) then begin - addInterfaceSym(w, s); - end - end; - nkVarSection: begin - for i := 0 to sonsLen(n)-1 do begin - a := n.sons[i]; - if a.kind = nkCommentStmt then continue; - if a.kind <> nkIdentDefs then InternalError(a.info, 'rodwrite.process'); - addInterfaceSym(w, a.sons[0].sym); - end - end; - nkConstSection: begin - for i := 0 to sonsLen(n)-1 do begin - a := n.sons[i]; - if a.kind = nkCommentStmt then continue; - if a.kind <> nkConstDef then InternalError(a.info, 'rodwrite.process'); - addInterfaceSym(w, a.sons[0].sym); - end - end; - nkTypeSection: begin - for i := 0 to sonsLen(n)-1 do begin - a := n.sons[i]; - if a.kind = nkCommentStmt then continue; - if a.sons[0].kind <> nkSym then - InternalError(a.info, 'rodwrite.process'); - s := a.sons[0].sym; - addInterfaceSym(w, s); // this takes care of enum fields too - // Note: The check for ``s.typ.kind = tyEnum`` is wrong for enum - // type aliasing! Otherwise the same enum symbol would be included - // several times! - (* - if (a.sons[2] <> nil) and (a.sons[2].kind = nkEnumTy) then begin - a := s.typ.n; - for j := 0 to sonsLen(a)-1 do - addInterfaceSym(w, a.sons[j].sym); - end *) - end - end; - nkImportStmt: begin - for i := 0 to sonsLen(n)-1 do addModDep(w, getModuleFile(n.sons[i])); - addStmt(w, n); - end; - nkFromStmt: begin - addModDep(w, getModuleFile(n.sons[0])); - addStmt(w, n); - end; - nkIncludeStmt: begin - for i := 0 to sonsLen(n)-1 do addInclDep(w, getModuleFile(n.sons[i])); - end; - nkPragma: addStmt(w, n); - else begin end - end; -end; - -function myOpen(module: PSym; const filename: string): PPassContext; -var - w: PRodWriter; -begin - if module.id < 0 then InternalError('rodwrite: module ID not set'); - w := newRodWriter(filename, rodread.GetCRC(filename), module); - rawAddInterfaceSym(w, module); - result := w; -end; - -function myClose(c: PPassContext; n: PNode): PNode; -var - w: PRodWriter; -begin - w := PRodWriter(c); - writeRod(w); - result := n; -end; - -function rodwritePass(): TPass; -begin - initPass(result); - if optSymbolFiles in gGlobalOptions then begin - result.open := myOpen; - result.close := myClose; - result.process := process; - end -end; - -initialization - IntSetInit(debugWritten); -end. |