# # # The Nim Compiler # (c) Copyright 2015 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # import ast, types, msgs, osproc, streams, options, idents, securehash proc readOutput(p: Process): string = result = "" var output = p.outputStream while not output.atEnd: result.add(output.readLine) result.add("\n") if result.len > 0: result.setLen(result.len - "\n".len) discard p.waitForExit proc opGorge*(cmd, input, cache: string): string = if cache.len > 0:# and optForceFullMake notin gGlobalOptions: let h = secureHash(cmd & "\t" & input & "\t" & cache) let filename = options.toGeneratedFile("gorge_" & $h, "txt") var f: File if open(f, filename): result = f.readAll f.close return var readSuccessful = false try: var p = startProcess(cmd, options={poEvalCommand, poStderrToStdout}) if input.len != 0: p.inputStream.write(input) p.inputStream.close() result = p.readOutput readSuccessful = true writeFile(filename, result) except IOError, OSError: if not readSuccessful: result = "" else: try: var p = startProcess(cmd, options={poEvalCommand, poStderrToStdout}) if input.len != 0: p.inputStream.write(input) p.inputStream.close() result = p.readOutput except IOError, OSError: result = "" proc opSlurp*(file: string, info: TLineInfo, module: PSym): string = try: let filename = file.findFile result = readFile(filename) # we produce a fake include statement for every slurped filename, so that # the module dependencies are accurate: appendToModule(module, newNode(nkIncludeStmt, info, @[ newStrNode(nkStrLit, filename)])) except IOError: localError(info, errCannotOpenFile, file) result = "" proc atomicTypeX(name: string; t: PType; info: TLineInfo): PNode = let sym = newSym(skType, getIdent(name), t.owner, info) sym.typ = t result = newSymNode(sym) result.typ = t proc mapTypeToAstX(t: PType; info: TLineInfo; inst=false; allowRecursionX=false): PNode proc mapTypeToBracketX(name: string; t: PType; info: TLineInfo; inst=false): PNode = result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t) result.add atomicTypeX(name, t, info) for i in 0 .. < t.len: if t.sons[i] == nil: let void = atomicTypeX("void", t, info) void.typ = newType(tyEmpty, t.owner) result.add void else: result.add mapTypeToAstX(t.sons[i], info, inst) proc mapTypeToAstX(t: PType; info: TLineInfo; inst=false; allowRecursionX=false): PNode = var allowRecursion = allowRecursionX template atomicType(name): expr = atomicTypeX(name, t, info) template mapTypeToAst(t,info): expr = mapTypeToAstX(t, info, inst) template mapTypeToAstR(t,info): expr = mapTypeToAstX(t, info, inst, true) template mapTypeToAst(t,i,info): expr = if i0: var rl = copyNode(t.n) # handle nkRecList for s in t.n.sons: rl.add newIdentDefs(s) result.add rl else: result.add ast.emptyNode else: if allowRecursion or t.sym == nil: result = newNodeIT(nkObjectTy, if t.n.isNil: info else: t.n.info, t) result.add ast.emptyNode if t.sons[0] == nil: result.add ast.emptyNode else: result.add mapTypeToAst(t.sons[0], info) result.add copyTree(t.n) else: result = atomicType(t.sym.name.s) of tyEnum: result = newNodeIT(nkEnumTy, if t.n.isNil: info else: t.n.info, t) result.add copyTree(t.n) of tyTuple: if inst: result = newNodeX(nkTupleTy) for s in t.n.sons: result.add newIdentDefs(s) else: result = mapTypeToBracket("tuple", t, info) of tySet: result = mapTypeToBracket("set", t, info) of tyPtr: if inst: result = newNodeX(nkPtrTy) result.add mapTypeToAst(t.sons[0], info) else: result = mapTypeToBracket("ptr", t, info) of tyRef: if inst: result = newNodeX(nkRefTy) result.add mapTypeToAst(t.sons[0], info) else: result = mapTypeToBracket("ref", t, info) of tyVar: result = mapTypeToBracket("var", t, info) of tySequence: result = mapTypeToBracket("seq", t, info) of tyProc: if inst: result = newNodeX(nkProcTy) var fp = newNodeX(nkFormalParams) if t.sons[0] == nil: fp.add ast.emptyNode else: fp.add mapTypeToAst(t.sons[0], t.n[0].info) for i in 1..