summary refs log tree commit diff stats
path: root/compiler/nim.nim
blob: a58afd593d7c8550d1920b73e1efeea76672b6f8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#
#
#           The Nim Compiler
#        (c) Copyright 2015 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

when defined(gcc) and defined(windows):
  when defined(x86):
    {.link: "icons/nim.res".}
  else:
    {.link: "icons/nim_icon.o".}

import
  commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes,
  extccomp, strutils, os, osproc, platform, main, parseopt, service,
  nodejs, scriptconfig

when hasTinyCBackend:
  import tccgen

when defined(profiler) or defined(memProfiler):
  {.hint: "Profiling support is turned on!".}
  import nimprof

proc prependCurDir(f: string): string =
  when defined(unix):
    if os.isAbsolute(f): result = f
    else: result = "./" & f
  else:
    result = f

proc handleCmdLine() =
  if paramCount() == 0:
    writeCommandLineUsage()
  else:
    # Process command line arguments:
    processCmdLine(passCmd1, "")
    if gProjectName == "-":
      gProjectName = "stdinfile"
      gProjectFull = "stdinfile"
      gProjectPath = getCurrentDir()
      gProjectIsStdin = true
    elif gProjectName != "":
      try:
        gProjectFull = canonicalizePath(gProjectName)
      except OSError:
        gProjectFull = gProjectName
      let p = splitFile(gProjectFull)
      gProjectPath = p.dir
      gProjectName = p.name
    else:
      gProjectPath = getCurrentDir()
    loadConfigs(DefaultConfig) # load all config files
    let scriptFile = gProjectFull.changeFileExt("nims")
    if fileExists(scriptFile):
      runNimScript(scriptFile, freshDefines=false)
      # 'nim foo.nims' means to just run the NimScript file and do nothing more:
      if scriptFile == gProjectFull: return
    elif fileExists(gProjectPath / "config.nims"):
      # directory wide NimScript file
      runNimScript(gProjectPath / "config.nims", freshDefines=false)
    # now process command line arguments again, because some options in the
    # command line can overwite the config file's settings
    extccomp.initVars()
    processCmdLine(passCmd2, "")
    if options.command == "":
      rawMessage(errNoCommand, command)
    mainCommand()
    if optHints in gOptions and hintGCStats in gNotes: echo(GC_getStatistics())
    #echo(GC_getStatistics())
    if msgs.gErrorCounter == 0:
      when hasTinyCBackend:
        if gCmd == cmdRun:
          tccgen.run(commands.arguments)
      if optRun in gGlobalOptions:
        if gCmd == cmdCompileToJS:
          var ex: string
          if options.outFile.len > 0:
            ex = options.outFile.prependCurDir.quoteShell
          else:
            ex = quoteShell(
              completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir))
          execExternalProgram(findNodeJs() & " " & ex & ' ' & commands.arguments)
        elif gCmd == cmdCompileToPHP:
          var ex: string
          if options.outFile.len > 0:
            ex = options.outFile.prependCurDir.quoteShell
          else:
            ex = quoteShell(
              completeCFilePath(changeFileExt(gProjectFull, "php").prependCurDir))
          execExternalProgram("php " & ex & ' ' & commands.arguments)
        else:
          var binPath: string
          if options.outFile.len > 0:
            # If the user specified an outFile path, use that directly.
            binPath = options.outFile.prependCurDir
          else:
            # Figure out ourselves a valid binary name.
            binPath = changeFileExt(gProjectFull, ExeExt).prependCurDir
          var ex = quoteShell(binPath)
          execExternalProgram(ex & ' ' & commands.arguments)

when declared(GC_setMaxPause):
  GC_setMaxPause 2_000

when compileOption("gc", "v2") or compileOption("gc", "refc"):
  # the new correct mark&sweet collector is too slow :-/
  GC_disableMarkAndSweep()
condsyms.initDefines()

when not defined(selftest):
  handleCmdLine()
  msgQuit(int8(msgs.gErrorCounter > 0))
ass="n">dstseq = cast[PGenericSeq](dst) dstseq.len = seq.len dstseq.space = seq.len of tyObject, tyTuple, tyPureObject: # we don't need to copy m_type field for tyObject, as they are equal anyway genericAssignAux(dest, src, mt.node) of tyArray, tyArrayConstr: for i in 0..(mt.size div mt.base.size)-1: genericAssign(cast[pointer](d +% i*% mt.base.size), cast[pointer](s +% i*% mt.base.size), mt.base) of tyString: # a leaf var s2 = cast[ppointer](s)^ if s2 != nil: # nil strings are possible! unsureAsgnRef(cast[ppointer](dest), copyString(cast[NimString](s2))) else: var x = cast[ppointer](dest) x^ = nil return of tyRef: # BUGFIX: a long time this has been forgotten! unsureAsgnRef(cast[ppointer](dest), cast[ppointer](s)^) else: copyMem(dest, src, mt.size) # copy raw bits proc genericSeqAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} = var src = src # ugly, but I like to stress the parser sometimes :-) genericAssign(dest, addr(src), mt) proc genericAssignOpenArray(dest, src: pointer, len: int, mt: PNimType) {.compilerproc.} = var d = cast[TAddress](dest) s = cast[TAddress](src) for i in 0..len-1: genericAssign(cast[pointer](d +% i*% mt.base.size), cast[pointer](s +% i*% mt.base.size), mt.base) proc objectInit(dest: Pointer, typ: PNimType) {.compilerProc.} proc objectInitAux(dest: Pointer, n: ptr TNimNode) = var d = cast[TAddress](dest) case n.kind of nkNone: assert(false) of nkSLot: objectInit(cast[pointer](d +% n.offset), n.typ) of nkList: for i in 0..n.len-1: objectInitAux(dest, n.sons[i]) of nkCase: var m = selectBranch(dest, n) if m != nil: objectInitAux(dest, m) proc objectInit(dest: Pointer, typ: PNimType) = # the generic init proc that takes care of initialization of complex # objects on the stack or heap var d = cast[TAddress](dest) case typ.kind of tyObject: # iterate over any structural type # here we have to init the type field: var pint = cast[ptr PNimType](dest) pint^ = typ objectInitAux(dest, typ.node) of tyTuple, tyPureObject: objectInitAux(dest, typ.node) of tyArray, tyArrayConstr: for i in 0..(typ.size div typ.base.size)-1: objectInit(cast[pointer](d +% i * typ.base.size), typ.base) else: nil # nothing to do