summary refs log tree commit diff stats
path: root/web/index.rst
blob: 4b712fa3b62f156bc46d4fd31154b4cb75fae41c (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
====
Home
====

Welcome to Nim
--------------

**Nim** is a statically typed, imperative
programming language that tries to give the programmer ultimate power without
compromises on runtime efficiency. This means it focuses on compile-time
mechanisms in all their various forms.

Beneath a nice infix/indentation based syntax with a
powerful (AST based, hygienic) macro system lies a semantic model that supports
a soft realtime GC on thread local heaps. Asynchronous message passing is used
between threads, so no "stop the world" mechanism is necessary. An unsafe
shared memory heap is also provided for the increased efficiency that results
from that model.


Nim is efficient
================

* Native code generation (currently via compilation to C), not dependent on a
  virtual machine: **Nim produces small executables without dependencies
  for easy redistribution.**
* A fast **non-tracing** garbage collector that supports soft
  real-time systems (like games).
* System programming features: Ability to manage your own memory and access the
  hardware directly. Pointers to garbage collected memory are distinguished
  from pointers to manually managed memory.
* Zero-overhead iterators.
* Cross-module inlining.
* Dynamic method binding with inlining and without virtual method table.
* Compile time evaluation of user-defined functions.
* Whole program dead code elimination: Only *used functions* are included in
  the executable.
* Value-based datatypes: For instance, objects and arrays can be allocated on
  the stack.


Nim is expressive
=================

* **The Nim compiler and all of the standard libraries are implemented in
  Nim.**
* Built-in high level datatypes: strings, sets, sequences, etc.
* Modern type system with local type inference, tuples, variants,
  generics, etc.
* User-defineable operators; code with new operators is often easier to read
  than code which overloads built-in operators. For example, a
  ``=~`` operator is defined in the ``re`` module.
* Macros can modify the abstract syntax tree at compile time.


Nim is elegant
==============

* Macros can use the imperative paradigm to construct parse trees. Nim
  does not require a different coding style for meta programming.
* Macros cannot change Nim's syntax because there is no need for it.
  Nim's syntax is flexible enough.
* Statements are grouped by indentation but can span multiple lines.
  Indentation must not contain tabulators so the compiler always sees
  the code the same way as you do.


Nim plays nice with others
==========================

* The Nim Compiler runs on Windows, Linux, BSD and Mac OS X.
  Porting to other platforms is easy.
* **The Nim Compiler can also generate C++ or Objective C for easier
  interfacing.**
* There are lots of bindings: for example, bindings to GTK2, the Windows API,
  the POSIX API, OpenGL, SDL, Cairo, Python, Lua, TCL, X11, libzip, PCRE,
  libcurl, mySQL and SQLite are included in the standard distribution or
  can easily be obtained via the
  `Nimble package manager <https://github.com/nim-lang/nimble>`_.
* A C to Nim conversion utility: New bindings to C libraries are easily
  generated by ``c2nim``.


Roadmap to 1.0
==============

Please have a look at
this `wiki page <https://github.com/nim-lang/Nim/wiki/Roadmap>`_ for
an up-to-date overview.
09' href='#n309'>309 310 311 312
313



































                                                                       
                                                                                    


















































































































































































































































































                                                                                     
            
#
#
#            Nim's Runtime Library
#        (c) Copyright 2022 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

## This module contains system facilities for reading command
## line parameters.

## **See also:**
## * `parseopt module <parseopt.html>`_ for command-line parser beyond
##   `parseCmdLine proc`_


include system/inclrtl

when defined(nimPreviewSlimSystem):
  import std/widestrs
  
when defined(nodejs):
  from std/private/oscommon import ReadDirEffect


const weirdTarget = defined(nimscript) or defined(js)


when weirdTarget:
  discard
elif defined(windows):
  import winlean
elif defined(posix):
  import posix
else:
  {.error: "The cmdline module has not been implemented for the target platform.".}


# Needed by windows in order to obtain the command line for targets
# other than command line targets
when defined(windows) and not weirdTarget:
  when useWinUnicode:
    template getCommandLine*(): untyped = getCommandLineW()
  else:
    template getCommandLine*(): untyped = getCommandLineA()


proc parseCmdLine*(c: string): seq[string] {.
  noSideEffect, rtl, extern: "nos$1".} =
  ## Splits a `command line`:idx: into several components.
  ##
  ## **Note**: This proc is only occasionally useful, better use the
  ## `parseopt module <parseopt.html>`_.
  ##
  ## On Windows, it uses the `following parsing rules
  ## <http://msdn.microsoft.com/en-us/library/17w5ykft.aspx>`_:
  ##
  ## * Arguments are delimited by white space, which is either a space or a tab.
  ## * The caret character (^) is not recognized as an escape character or
  ##   delimiter. The character is handled completely by the command-line parser
  ##   in the operating system before being passed to the argv array in the
  ##   program.
  ## * A string surrounded by double quotation marks ("string") is interpreted
  ##   as a single argument, regardless of white space contained within. A
  ##   quoted string can be embedded in an argument.
  ## * A double quotation mark preceded by a backslash (\") is interpreted as a
  ##   literal double quotation mark character (").
  ## * Backslashes are interpreted literally, unless they immediately precede
  ##   a double quotation mark.
  ## * If an even number of backslashes is followed by a double quotation mark,
  ##   one backslash is placed in the argv array for every pair of backslashes,
  ##   and the double quotation mark is interpreted as a string delimiter.
  ## * If an odd number of backslashes is followed by a double quotation mark,
  ##   one backslash is placed in the argv array for every pair of backslashes,
  ##   and the double quotation mark is "escaped" by the remaining backslash,
  ##   causing a literal double quotation mark (") to be placed in argv.
  ##
  ## On Posix systems, it uses the following parsing rules:
  ## Components are separated by whitespace unless the whitespace
  ## occurs within ``"`` or ``'`` quotes.
  ##
  ## See also:
  ## * `parseopt module <parseopt.html>`_
  ## * `paramCount proc`_
  ## * `paramStr proc`_
  ## * `commandLineParams proc`_

  result = @[]
  var i = 0
  var a = ""
  while true:
    setLen(a, 0)
    # eat all delimiting whitespace
    while i < c.len and c[i] in {' ', '\t', '\l', '\r'}: inc(i)
    if i >= c.len: break
    when defined(windows):
      # parse a single argument according to the above rules:
      var inQuote = false
      while i < c.len:
        case c[i]
        of '\\':
          var j = i
          while j < c.len and c[j] == '\\': inc(j)
          if j < c.len and c[j] == '"':
            for k in 1..(j-i) div 2: a.add('\\')
            if (j-i) mod 2 == 0:
              i = j
            else:
              a.add('"')
              i = j+1
          else:
            a.add(c[i])
            inc(i)
        of '"':
          inc(i)
          if not inQuote: inQuote = true
          elif i < c.len and c[i] == '"':
            a.add(c[i])
            inc(i)
          else:
            inQuote = false
            break
        of ' ', '\t':
          if not inQuote: break
          a.add(c[i])
          inc(i)
        else:
          a.add(c[i])
          inc(i)
    else:
      case c[i]
      of '\'', '\"':
        var delim = c[i]
        inc(i) # skip ' or "
        while i < c.len and c[i] != delim:
          add a, c[i]
          inc(i)
        if i < c.len: inc(i)
      else:
        while i < c.len and c[i] > ' ':
          add(a, c[i])
          inc(i)
    add(result, a)

when defined(nimdoc):
  # Common forward declaration docstring block for parameter retrieval procs.
  proc paramCount*(): int {.tags: [ReadIOEffect].} =
    ## Returns the number of `command line arguments`:idx: given to the
    ## application.
    ##
    ## Unlike `argc`:idx: in C, if your binary was called without parameters this
    ## will return zero.
    ## You can query each individual parameter with `paramStr proc`_
    ## or retrieve all of them in one go with `commandLineParams proc`_.
    ##
    ## **Availability**: When generating a dynamic library (see `--app:lib`) on
    ## Posix this proc is not defined.
    ## Test for availability using `declared() <system.html#declared,untyped>`_.
    ##
    ## See also:
    ## * `parseopt module <parseopt.html>`_
    ## * `parseCmdLine proc`_
    ## * `paramStr proc`_
    ## * `commandLineParams proc`_
    ##
    ## **Examples:**
    ##
    ## .. code-block:: nim
    ##   when declared(paramCount):
    ##     # Use paramCount() here
    ##   else:
    ##     # Do something else!

  proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
    ## Returns the `i`-th `command line argument`:idx: given to the application.
    ##
    ## `i` should be in the range `1..paramCount()`, the `IndexDefect`
    ## exception will be raised for invalid values. Instead of iterating
    ## over `paramCount()`_ with this proc you can
    ## call the convenience `commandLineParams()`_.
    ##
    ## Similarly to `argv`:idx: in C,
    ## it is possible to call `paramStr(0)` but this will return OS specific
    ## contents (usually the name of the invoked executable). You should avoid
    ## this and call `getAppFilename()`_ instead.
    ##
    ## **Availability**: When generating a dynamic library (see `--app:lib`) on
    ## Posix this proc is not defined.
    ## Test for availability using `declared() <system.html#declared,untyped>`_.
    ##
    ## See also:
    ## * `parseopt module <parseopt.html>`_
    ## * `parseCmdLine proc`_
    ## * `paramCount proc`_
    ## * `commandLineParams proc`_
    ## * `getAppFilename proc`_
    ##
    ## **Examples:**
    ##
    ## .. code-block:: nim
    ##   when declared(paramStr):
    ##     # Use paramStr() here
    ##   else:
    ##     # Do something else!

elif defined(nimscript): discard
elif defined(nodejs):
  type Argv = object of JsRoot
  let argv {.importjs: "process.argv".} : Argv
  proc len(argv: Argv): int {.importjs: "#.length".}
  proc `[]`(argv: Argv, i: int): cstring {.importjs: "#[#]".}

  proc paramCount*(): int {.tags: [ReadDirEffect].} =
    result = argv.len - 2

  proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
    let i = i + 1
    if i < argv.len and i >= 0:
      result = $argv[i]
    else:
      raise newException(IndexDefect, formatErrorIndexBound(i - 1, argv.len - 2))
elif defined(windows):
  # Since we support GUI applications with Nim, we sometimes generate
  # a WinMain entry proc. But a WinMain proc has no access to the parsed
  # command line arguments. The way to get them differs. Thus we parse them
  # ourselves. This has the additional benefit that the program's behaviour
  # is always the same -- independent of the used C compiler.
  var
    ownArgv {.threadvar.}: seq[string]
    ownParsedArgv {.threadvar.}: bool

  proc paramCount*(): int {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
    # Docstring in nimdoc block.
    if not ownParsedArgv:
      ownArgv = parseCmdLine($getCommandLine())
      ownParsedArgv = true
    result = ownArgv.len-1

  proc paramStr*(i: int): string {.rtl, extern: "nos$1",
    tags: [ReadIOEffect].} =
    # Docstring in nimdoc block.
    if not ownParsedArgv:
      ownArgv = parseCmdLine($getCommandLine())
      ownParsedArgv = true
    if i < ownArgv.len and i >= 0:
      result = ownArgv[i]
    else:
      raise newException(IndexDefect, formatErrorIndexBound(i, ownArgv.len-1))

elif defined(genode):
  proc paramStr*(i: int): string =
    raise newException(OSError, "paramStr is not implemented on Genode")

  proc paramCount*(): int =
    raise newException(OSError, "paramCount is not implemented on Genode")
elif weirdTarget or (defined(posix) and appType == "lib"):
  proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
    raise newException(OSError, "paramStr is not implemented on current platform")

  proc paramCount*(): int {.tags: [ReadIOEffect].} =
    raise newException(OSError, "paramCount is not implemented on current platform")
elif not defined(createNimRtl) and
  not(defined(posix) and appType == "lib"):
  # On Posix, there is no portable way to get the command line from a DLL.
  var
    cmdCount {.importc: "cmdCount".}: cint
    cmdLine {.importc: "cmdLine".}: cstringArray

  proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
    # Docstring in nimdoc block.
    if i < cmdCount and i >= 0:
      result = $cmdLine[i]
    else:
      raise newException(IndexDefect, formatErrorIndexBound(i, cmdCount-1))

  proc paramCount*(): int {.tags: [ReadIOEffect].} =
    # Docstring in nimdoc block.
    result = cmdCount-1

when declared(paramCount) or defined(nimdoc):
  proc commandLineParams*(): seq[string] =
    ## Convenience proc which returns the command line parameters.
    ##
    ## This returns **only** the parameters. If you want to get the application
    ## executable filename, call `getAppFilename()`_.
    ##
    ## **Availability**: On Posix there is no portable way to get the command
    ## line from a DLL and thus the proc isn't defined in this environment. You
    ## can test for its availability with `declared()
    ## <system.html#declared,untyped>`_.
    ##
    ## See also:
    ## * `parseopt module <parseopt.html>`_
    ## * `parseCmdLine proc`_
    ## * `paramCount proc`_
    ## * `paramStr proc`_
    ## * `getAppFilename proc`_
    ##
    ## **Examples:**
    ##
    ## .. code-block:: nim
    ##   when declared(commandLineParams):
    ##     # Use commandLineParams() here
    ##   else:
    ##     # Do something else!
    result = @[]
    for i in 1..paramCount():
      result.add(paramStr(i))
else:
  proc commandLineParams*(): seq[string] {.error:
  "commandLineParams() unsupported by dynamic libraries".} =
    discard