bugfixes: macros; splitFile; strutils.split; iterator.method
This commit is contained in:
parent
053309e60a
commit
d5acb88ccc
31 changed files with 177 additions and 95 deletions
|
|
@ -247,6 +247,7 @@
|
||||||
'StrToIdent',
|
'StrToIdent',
|
||||||
'IdentToStr',
|
'IdentToStr',
|
||||||
'EqIdent',
|
'EqIdent',
|
||||||
|
'EqNimrodNode',
|
||||||
'NHint',
|
'NHint',
|
||||||
'NWarning',
|
'NWarning',
|
||||||
'NError'
|
'NError'
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@
|
||||||
{'errXNeedsReturnType': '$1 needs a return type'},
|
{'errXNeedsReturnType': '$1 needs a return type'},
|
||||||
{'errInvalidCommandX': "invalid command: '$1'"},
|
{'errInvalidCommandX': "invalid command: '$1'"},
|
||||||
{'errXOnlyAtModuleScope': "'$1' is only allowed at top level"},
|
{'errXOnlyAtModuleScope': "'$1' is only allowed at top level"},
|
||||||
{'errTemplateInstantiationTooNested': 'template instantiation too nested'},
|
{'errTemplateInstantiationTooNested': 'template/macro instantiation too nested'},
|
||||||
{'errInstantiationFrom': 'instantiation from here'},
|
{'errInstantiationFrom': 'instantiation from here'},
|
||||||
{'errInvalidIndexValueForTuple': 'invalid index value for tuple subscript'},
|
{'errInvalidIndexValueForTuple': 'invalid index value for tuple subscript'},
|
||||||
{'errCommandExpectsFilename': 'command expects a filename argument'},
|
{'errCommandExpectsFilename': 'command expects a filename argument'},
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
|
|
||||||
Abstraction is layering ignorance on top of reality. -- unknown
|
"Abstraction is layering ignorance on top of reality." -- unknown
|
||||||
|
|
||||||
|
|
||||||
Directory structure
|
Directory structure
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ Nimrod Standard Library
|
||||||
|
|
||||||
..
|
..
|
||||||
|
|
||||||
The good thing about reinventing the wheel is that you can get a round one.
|
"The good thing about reinventing the wheel is that you can get a round one."
|
||||||
|
|
||||||
Though the Nimrod Standard Library is still evolving, it is already quite
|
Though the Nimrod Standard Library is still evolving, it is already quite
|
||||||
usable. It is divided into *pure libraries*, *impure libraries* and *wrappers*.
|
usable. It is divided into *pure libraries*, *impure libraries* and *wrappers*.
|
||||||
|
|
|
||||||
|
|
@ -760,7 +760,7 @@ An example:
|
||||||
nkIf # an if statement
|
nkIf # an if statement
|
||||||
PNode = ref TNode
|
PNode = ref TNode
|
||||||
TNode = object
|
TNode = object
|
||||||
case kind: TNodeKind # the ``kind`` field is the discriminator
|
case kind: TNodeKind # the ``kind`` field is the discriminant
|
||||||
of nkInt: intVal: int
|
of nkInt: intVal: int
|
||||||
of nkFloat: floavVal: float
|
of nkFloat: floavVal: float
|
||||||
of nkString: strVal: string
|
of nkString: strVal: string
|
||||||
|
|
@ -1648,7 +1648,7 @@ required. ``Elif`` parts are also allowed (but unlikely to be good
|
||||||
style).
|
style).
|
||||||
|
|
||||||
|
|
||||||
Type convertions
|
Type conversions
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
Syntactically a `type conversion` is like a procedure call, but a
|
Syntactically a `type conversion` is like a procedure call, but a
|
||||||
type name replaces the procedure name. A type conversion is always
|
type name replaces the procedure name. A type conversion is always
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
:Version: |nimrodversion|
|
:Version: |nimrodversion|
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
============
|
============
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -871,7 +871,7 @@ type:
|
||||||
var
|
var
|
||||||
x = 0.0 # x is of type ``float``
|
x = 0.0 # x is of type ``float``
|
||||||
y = 0.0'f32 # y is of type ``float32``
|
y = 0.0'f32 # y is of type ``float32``
|
||||||
z = 0.0'f64 # z is of type ``int64``
|
z = 0.0'f64 # z is of type ``float64``
|
||||||
|
|
||||||
The common operators ``+ - * / < <= == != > >=`` are defined for
|
The common operators ``+ - * / < <= == != > >=`` are defined for
|
||||||
floats and follow the IEEE standard.
|
floats and follow the IEEE standard.
|
||||||
|
|
@ -1318,7 +1318,7 @@ This is best illustrated by an example:
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
# Module B
|
# Module B
|
||||||
import A # A is not parsed here! Only the already known symbols
|
import A # A is not parsed here! Only the already known symbols
|
||||||
# of A are imported.
|
# of A are imported.
|
||||||
|
|
@ -1338,9 +1338,11 @@ imported by a third one:
|
||||||
# Module A
|
# Module A
|
||||||
var x*: string
|
var x*: string
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
# Module B
|
# Module B
|
||||||
var x*: int
|
var x*: int
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
# Module C
|
# Module C
|
||||||
import A, B
|
import A, B
|
||||||
write(stdout, x) # error: x is ambiguous
|
write(stdout, x) # error: x is ambiguous
|
||||||
|
|
@ -1357,9 +1359,11 @@ rules apply:
|
||||||
# Module A
|
# Module A
|
||||||
proc x*(a: int): string = return $a
|
proc x*(a: int): string = return $a
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
# Module B
|
# Module B
|
||||||
proc x*(a: string): string = return $a
|
proc x*(a: string): string = return $a
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
# Module C
|
# Module C
|
||||||
import A, B
|
import A, B
|
||||||
write(stdout, x(3)) # no error: A.x is called
|
write(stdout, x(3)) # no error: A.x is called
|
||||||
|
|
|
||||||
13
koch.py
13
koch.py
|
|
@ -12,7 +12,7 @@ from pycompab import *
|
||||||
|
|
||||||
# --------------------- constants ----------------------------------------
|
# --------------------- constants ----------------------------------------
|
||||||
|
|
||||||
NIMROD_VERSION = '0.8.2'
|
NIMROD_VERSION = '0.8.3'
|
||||||
# This string contains Nimrod's version. It is the only place
|
# This string contains Nimrod's version. It is the only place
|
||||||
# where the version needs to be updated. The rest is done by
|
# where the version needs to be updated. The rest is done by
|
||||||
# the build process automatically. It is replaced **everywhere**!
|
# the build process automatically. It is replaced **everywhere**!
|
||||||
|
|
@ -362,7 +362,7 @@ def cmd_rod(options):
|
||||||
if Exists(ExeExt("bin/nimrod")):
|
if Exists(ExeExt("bin/nimrod")):
|
||||||
c.success()
|
c.success()
|
||||||
|
|
||||||
# ------------------- constants -----------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
HELP = Subs("""\
|
HELP = Subs("""\
|
||||||
+-----------------------------------------------------------------+
|
+-----------------------------------------------------------------+
|
||||||
|
|
@ -426,6 +426,7 @@ def main(args):
|
||||||
elif cmd == "inno": cmd_inno()
|
elif cmd == "inno": cmd_inno()
|
||||||
elif cmd == "csource": cmd_csource(join(args[i+1:]))
|
elif cmd == "csource": cmd_csource(join(args[i+1:]))
|
||||||
elif cmd == "install": cmd_install() # for backwards compability
|
elif cmd == "install": cmd_install() # for backwards compability
|
||||||
|
#elif cmd == "llvmdebug": cmd_llvm(debug=true)
|
||||||
else: Error("illegal command: " + cmd)
|
else: Error("illegal command: " + cmd)
|
||||||
|
|
||||||
def cmd_csource(args):
|
def cmd_csource(args):
|
||||||
|
|
@ -443,6 +444,14 @@ def cmd_inno():
|
||||||
|
|
||||||
def cmd_install():
|
def cmd_install():
|
||||||
Exec("sh ./build.sh")
|
Exec("sh ./build.sh")
|
||||||
|
|
||||||
|
def cmd_llvm(debug=true):
|
||||||
|
if not debug: release = "--enable-optimized"
|
||||||
|
else: release = ""
|
||||||
|
Exec(Subs("./configure --enable-bindings $1 --enable-shared" +
|
||||||
|
" --enable-targets=host", release))
|
||||||
|
Exec("make")
|
||||||
|
Echo("Type [sudo] make install!")
|
||||||
|
|
||||||
# -------------------------- bootstrap ----------------------------------------
|
# -------------------------- bootstrap ----------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -122,8 +122,11 @@ proc `!` *(s: string): TNimrodIdent {.magic: "StrToIdent".}
|
||||||
proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".}
|
proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".}
|
||||||
## converts a Nimrod identifier to a string
|
## converts a Nimrod identifier to a string
|
||||||
|
|
||||||
proc `==`* (a, b: TNimrodIdent): bool {.magic: "EqIdent".}
|
proc `==`* (a, b: TNimrodIdent): bool {.magic: "EqIdent", noSideEffect.}
|
||||||
## compares two Nimrod identifiers
|
## compares two Nimrod identifiers
|
||||||
|
|
||||||
|
proc `==`* (a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.}
|
||||||
|
## compares two Nimrod nodes
|
||||||
|
|
||||||
proc len*(n: PNimrodNode): int {.magic: "NLen".}
|
proc len*(n: PNimrodNode): int {.magic: "NLen".}
|
||||||
## returns the number of children of `n`.
|
## returns the number of children of `n`.
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
## This module contains basic operating system facilities like
|
## This module contains basic operating system facilities like
|
||||||
## retrieving environment variables, reading command line arguments,
|
## retrieving environment variables, reading command line arguments,
|
||||||
## working with directories, running shell commands, etc.
|
## working with directories, running shell commands, etc.
|
||||||
## This module is -- like any other basic library -- platform independant.
|
|
||||||
{.deadCodeElim: on.}
|
{.deadCodeElim: on.}
|
||||||
|
|
||||||
{.push debugger: off.}
|
{.push debugger: off.}
|
||||||
|
|
@ -384,10 +383,13 @@ proc SplitPath*(path: string): tuple[head, tail: string] {.noSideEffect.} =
|
||||||
## Splits a directory into (head, tail), so that
|
## Splits a directory into (head, tail), so that
|
||||||
## ``JoinPath(head, tail) == path``.
|
## ``JoinPath(head, tail) == path``.
|
||||||
##
|
##
|
||||||
## Example: After ``SplitPath("usr/local/bin", head, tail)``,
|
## Examples:
|
||||||
## `head` is "usr/local" and `tail` is "bin".
|
## .. code-block:: nimrod
|
||||||
## Example: After ``SplitPath("usr/local/bin/", head, tail)``,
|
## SplitPath("usr/local/bin") -> ("usr/local", "bin")
|
||||||
## `head` is "usr/local/bin" and `tail` is "".
|
## SplitPath("usr/local/bin/") -> ("usr/local/bin", "")
|
||||||
|
## SplitPath("bin") -> ("", "bin")
|
||||||
|
## SplitPath("/bin") -> ("", "bin")
|
||||||
|
## SplitPath("") -> ("", "")
|
||||||
var
|
var
|
||||||
sepPos = -1
|
sepPos = -1
|
||||||
for i in countdown(len(path)-1, 0):
|
for i in countdown(len(path)-1, 0):
|
||||||
|
|
@ -431,8 +433,9 @@ proc normExt(ext: string): string =
|
||||||
else: result = extSep & ext
|
else: result = extSep & ext
|
||||||
|
|
||||||
proc searchExtPos(s: string): int =
|
proc searchExtPos(s: string): int =
|
||||||
|
# BUGFIX: do not search until 0! .DS_Store is no file extension!
|
||||||
result = -1
|
result = -1
|
||||||
for i in countdown(len(s)-1, 0):
|
for i in countdown(len(s)-1, 1):
|
||||||
if s[i] == extsep:
|
if s[i] == extsep:
|
||||||
result = i
|
result = i
|
||||||
break
|
break
|
||||||
|
|
@ -447,10 +450,11 @@ proc splitFile*(path: string): tuple[dir, name, ext: string] {.noSideEffect.} =
|
||||||
## Example:
|
## Example:
|
||||||
##
|
##
|
||||||
## .. code-block:: nimrod
|
## .. code-block:: nimrod
|
||||||
## var (dir, name, ext) = splitFile("usr/local/nimrodc.html")
|
## var (dir, name, ext) = splitFile("usr/local/nimrodc.html")
|
||||||
## assert dir == "usr/local"
|
## assert dir == "usr/local"
|
||||||
## assert name == "nimrodc"
|
## assert name == "nimrodc"
|
||||||
## assert ext == ".html"
|
## assert ext == ".html"
|
||||||
|
##
|
||||||
## If `path` has no extension, `ext` is the empty string.
|
## If `path` has no extension, `ext` is the empty string.
|
||||||
## If `path` has no directory component, `dir` is the empty string.
|
## If `path` has no directory component, `dir` is the empty string.
|
||||||
## If `path` has no filename component, `name` and `ext` are empty strings.
|
## If `path` has no filename component, `name` and `ext` are empty strings.
|
||||||
|
|
@ -461,7 +465,7 @@ proc splitFile*(path: string): tuple[dir, name, ext: string] {.noSideEffect.} =
|
||||||
var dotPos = path.len
|
var dotPos = path.len
|
||||||
for i in countdown(len(path)-1, 0):
|
for i in countdown(len(path)-1, 0):
|
||||||
if path[i] == ExtSep:
|
if path[i] == ExtSep:
|
||||||
if dotPos == path.len: dotPos = i
|
if dotPos == path.len and i > 0: dotPos = i
|
||||||
elif path[i] in {dirsep, altsep}:
|
elif path[i] in {dirsep, altsep}:
|
||||||
sepPos = i
|
sepPos = i
|
||||||
break
|
break
|
||||||
|
|
@ -877,9 +881,9 @@ iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string =
|
||||||
## filter meaning
|
## filter meaning
|
||||||
## --------------------- ---------------------------------------------
|
## --------------------- ---------------------------------------------
|
||||||
## ``pcFile`` yield real files
|
## ``pcFile`` yield real files
|
||||||
## ``pcLinkToFile`` yield symbol links to files
|
## ``pcLinkToFile`` yield symbolic links to files
|
||||||
## ``pcDir`` follow real directories
|
## ``pcDir`` follow real directories
|
||||||
## ``pcLinkToDir`` follow symbol links to directories
|
## ``pcLinkToDir`` follow symbolic links to directories
|
||||||
## --------------------- ---------------------------------------------
|
## --------------------- ---------------------------------------------
|
||||||
##
|
##
|
||||||
var stack = @[dir]
|
var stack = @[dir]
|
||||||
|
|
|
||||||
|
|
@ -169,15 +169,14 @@ iterator split*(s: string, seps: set[char] = Whitespace): string =
|
||||||
## writeln(stdout, word)
|
## writeln(stdout, word)
|
||||||
##
|
##
|
||||||
## produces the same output.
|
## produces the same output.
|
||||||
var
|
var last = 0
|
||||||
first: int = 0
|
|
||||||
last: int = 0
|
|
||||||
assert(not ('\0' in seps))
|
assert(not ('\0' in seps))
|
||||||
while last < len(s):
|
while last < len(s):
|
||||||
while s[last] in seps: inc(last)
|
while s[last] in seps: inc(last)
|
||||||
first = last
|
var first = last
|
||||||
while last < len(s) and s[last] not_in seps: inc(last) # BUGFIX!
|
while last < len(s) and s[last] not_in seps: inc(last) # BUGFIX!
|
||||||
yield copy(s, first, last-1)
|
if first <= last-1:
|
||||||
|
yield copy(s, first, last-1)
|
||||||
|
|
||||||
iterator split*(s: string, sep: char): string =
|
iterator split*(s: string, sep: char): string =
|
||||||
## Splits the string `s` into substrings.
|
## Splits the string `s` into substrings.
|
||||||
|
|
|
||||||
|
|
@ -262,7 +262,8 @@ type
|
||||||
mNAddMultiple, mNDel, mNKind, mNIntVal, mNFloatVal, mNSymbol,
|
mNAddMultiple, mNDel, mNKind, mNIntVal, mNFloatVal, mNSymbol,
|
||||||
mNIdent, mNGetType, mNStrVal, mNSetIntVal, mNSetFloatVal, mNSetSymbol,
|
mNIdent, mNGetType, mNStrVal, mNSetIntVal, mNSetFloatVal, mNSetSymbol,
|
||||||
mNSetIdent, mNSetType, mNSetStrVal, mNNewNimNode, mNCopyNimNode, mNCopyNimTree,
|
mNSetIdent, mNSetType, mNSetStrVal, mNNewNimNode, mNCopyNimNode, mNCopyNimTree,
|
||||||
mStrToIdent, mIdentToStr, mEqIdent, mNHint, mNWarning, mNError
|
mStrToIdent, mIdentToStr, mEqIdent, mEqNimrodNode, mNHint, mNWarning,
|
||||||
|
mNError
|
||||||
//[[[end]]]
|
//[[[end]]]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -521,7 +522,8 @@ const // "MagicToStr" array:
|
||||||
'NAddMultiple', 'NDel', 'NKind', 'NIntVal', 'NFloatVal', 'NSymbol',
|
'NAddMultiple', 'NDel', 'NKind', 'NIntVal', 'NFloatVal', 'NSymbol',
|
||||||
'NIdent', 'NGetType', 'NStrVal', 'NSetIntVal', 'NSetFloatVal', 'NSetSymbol',
|
'NIdent', 'NGetType', 'NStrVal', 'NSetIntVal', 'NSetFloatVal', 'NSetSymbol',
|
||||||
'NSetIdent', 'NSetType', 'NSetStrVal', 'NNewNimNode', 'NCopyNimNode', 'NCopyNimTree',
|
'NSetIdent', 'NSetType', 'NSetStrVal', 'NNewNimNode', 'NCopyNimNode', 'NCopyNimTree',
|
||||||
'StrToIdent', 'IdentToStr', 'EqIdent', 'NHint', 'NWarning', 'NError'
|
'StrToIdent', 'IdentToStr', 'EqIdent', 'EqNimrodNode', 'NHint', 'NWarning',
|
||||||
|
'NError'
|
||||||
//[[[end]]]
|
//[[[end]]]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ type
|
||||||
cfsProcs, // section for C procs that are not inline
|
cfsProcs, // section for C procs that are not inline
|
||||||
cfsTypeInit1, // section 1 for declarations of type information
|
cfsTypeInit1, // section 1 for declarations of type information
|
||||||
cfsTypeInit2, // section 2 for initialization of type information
|
cfsTypeInit2, // section 2 for initialization of type information
|
||||||
cfsTypeInit3, // section 3 for init of type information
|
cfsTypeInit3, // section 3 for initialization of type information
|
||||||
cfsDebugInit, // section for initialization of debug information
|
cfsDebugInit, // section for initialization of debug information
|
||||||
cfsDynLibInit, // section for initialization of dynamic library binding
|
cfsDynLibInit, // section for initialization of dynamic library binding
|
||||||
cfsDynLibDeinit // section for deinitialization of dynamic libraries
|
cfsDynLibDeinit // section for deinitialization of dynamic libraries
|
||||||
|
|
|
||||||
|
|
@ -309,11 +309,11 @@ end;
|
||||||
|
|
||||||
procedure processCompile(const filename: string);
|
procedure processCompile(const filename: string);
|
||||||
var
|
var
|
||||||
found, trunc, ext: string;
|
found, trunc: string;
|
||||||
begin
|
begin
|
||||||
found := findFile(filename);
|
found := findFile(filename);
|
||||||
if found = '' then found := filename;
|
if found = '' then found := filename;
|
||||||
splitFilename(found, trunc, ext);
|
trunc := changeFileExt(found, '');
|
||||||
extccomp.addExternalFileToCompile(trunc);
|
extccomp.addExternalFileToCompile(trunc);
|
||||||
extccomp.addFileToLink(completeCFilePath(trunc, false));
|
extccomp.addFileToLink(completeCFilePath(trunc, false));
|
||||||
end;
|
end;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// The Nimrod Compiler
|
// The Nimrod Compiler
|
||||||
// (c) Copyright 2008 Andreas Rumpf
|
// (c) Copyright 2009 Andreas Rumpf
|
||||||
//
|
//
|
||||||
// See the file "copying.txt", included in this
|
// See the file "copying.txt", included in this
|
||||||
// distribution, for details about the copyright.
|
// distribution, for details about the copyright.
|
||||||
|
|
@ -51,12 +51,12 @@ begin
|
||||||
case n.kind of
|
case n.kind of
|
||||||
nkImportStmt: begin
|
nkImportStmt: begin
|
||||||
for i := 0 to sonsLen(n)-1 do begin
|
for i := 0 to sonsLen(n)-1 do begin
|
||||||
imported := extractFileTrunk(getModuleFile(n.sons[i]));
|
imported := splitFile(getModuleFile(n.sons[i])).name;
|
||||||
addDependencyAux(g.module.name.s, imported);
|
addDependencyAux(g.module.name.s, imported);
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
nkFromStmt: begin
|
nkFromStmt: begin
|
||||||
imported := extractFileTrunk(getModuleFile(n.sons[0]));
|
imported := splitFile(getModuleFile(n.sons[0])).name;
|
||||||
addDependencyAux(g.module.name.s, imported);
|
addDependencyAux(g.module.name.s, imported);
|
||||||
end;
|
end;
|
||||||
nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr: begin
|
nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr: begin
|
||||||
|
|
|
||||||
|
|
@ -994,9 +994,11 @@ begin
|
||||||
result := evalAux(c, n.sons[2]);
|
result := evalAux(c, n.sons[2]);
|
||||||
if result.kind = nkExceptBranch then exit;
|
if result.kind = nkExceptBranch then exit;
|
||||||
k := getOrdValue(result);
|
k := getOrdValue(result);
|
||||||
if (k >= 0) and (k < sonsLen(a))
|
if not (a.kind in [nkEmpty..nkNilLit]) and (k >= 0)
|
||||||
and not (a.kind in [nkEmpty..nkNilLit]) then
|
and (k < sonsLen(a)) then begin
|
||||||
result := a.sons[int(k)]
|
result := a.sons[int(k)];
|
||||||
|
if result = nil then result := newNode(nkEmpty)
|
||||||
|
end
|
||||||
else begin
|
else begin
|
||||||
stackTrace(c, n, errIndexOutOfBounds);
|
stackTrace(c, n, errIndexOutOfBounds);
|
||||||
result := emptyNode
|
result := emptyNode
|
||||||
|
|
@ -1013,8 +1015,10 @@ begin
|
||||||
if result.kind = nkExceptBranch then exit;
|
if result.kind = nkExceptBranch then exit;
|
||||||
k := getOrdValue(b);
|
k := getOrdValue(b);
|
||||||
if (k >= 0) and (k < sonsLen(a))
|
if (k >= 0) and (k < sonsLen(a))
|
||||||
and not (a.kind in [nkEmpty..nkNilLit]) then
|
and not (a.kind in [nkEmpty..nkNilLit]) then begin
|
||||||
a.sons[int(k)] := result
|
if result.kind = nkEmpty then a.sons[int(k)] := nil
|
||||||
|
else a.sons[int(k)] := result
|
||||||
|
end
|
||||||
else
|
else
|
||||||
stackTrace(c, n, errIndexOutOfBounds);
|
stackTrace(c, n, errIndexOutOfBounds);
|
||||||
result := emptyNode;
|
result := emptyNode;
|
||||||
|
|
@ -1205,6 +1209,19 @@ begin
|
||||||
if (a.kind = nkIdent) and (b.kind = nkIdent) then
|
if (a.kind = nkIdent) and (b.kind = nkIdent) then
|
||||||
if a.ident.id = b.ident.id then result.intVal := 1
|
if a.ident.id = b.ident.id then result.intVal := 1
|
||||||
end;
|
end;
|
||||||
|
mEqNimrodNode: begin
|
||||||
|
result := evalAux(c, n.sons[1]);
|
||||||
|
if result.kind = nkExceptBranch then exit;
|
||||||
|
a := result;
|
||||||
|
result := evalAux(c, n.sons[2]);
|
||||||
|
if result.kind = nkExceptBranch then exit;
|
||||||
|
b := result;
|
||||||
|
result := newNodeIT(nkIntLit, n.info, n.typ);
|
||||||
|
if (a = b)
|
||||||
|
or (b.kind in [nkNilLit, nkEmpty])
|
||||||
|
and (a.kind in [nkNilLit, nkEmpty]) then
|
||||||
|
result.intVal := 1
|
||||||
|
end;
|
||||||
mNHint: begin
|
mNHint: begin
|
||||||
result := evalAux(c, n.sons[1]);
|
result := evalAux(c, n.sons[1]);
|
||||||
if result.kind = nkExceptBranch then exit;
|
if result.kind = nkExceptBranch then exit;
|
||||||
|
|
|
||||||
|
|
@ -438,7 +438,7 @@ var
|
||||||
begin
|
begin
|
||||||
c := ccompiler;
|
c := ccompiler;
|
||||||
options := compileOptions;
|
options := compileOptions;
|
||||||
trunk := extractFileTrunk(cfilename);
|
trunk := splitFile(cfilename).name;
|
||||||
if optCDebug in gGlobalOptions then begin
|
if optCDebug in gGlobalOptions then begin
|
||||||
key := trunk + '.debug';
|
key := trunk + '.debug';
|
||||||
if existsConfigVar(key) then
|
if existsConfigVar(key) then
|
||||||
|
|
@ -594,15 +594,15 @@ begin
|
||||||
|
|
||||||
if optGenDynLib in gGlobalOptions then begin
|
if optGenDynLib in gGlobalOptions then begin
|
||||||
exefile := format(platform.os[targetOS].dllFrmt,
|
exefile := format(platform.os[targetOS].dllFrmt,
|
||||||
[extractFileTrunk(projectFile)]);
|
[splitFile(projectFile).name]);
|
||||||
buildDll := cc[c].buildDll;
|
buildDll := cc[c].buildDll;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
exefile := extractFileTrunk(projectFile) +{&} platform.os[targetOS].exeExt;
|
exefile := splitFile(projectFile).name +{&} platform.os[targetOS].exeExt;
|
||||||
buildDll := '';
|
buildDll := '';
|
||||||
end;
|
end;
|
||||||
if targetOS = platform.hostOS then
|
if targetOS = platform.hostOS then
|
||||||
exefile := joinPath(extractDir(projectFile), exefile);
|
exefile := joinPath(splitFile(projectFile).dir, exefile);
|
||||||
exefile := quoteIfContainsWhite(exefile);
|
exefile := quoteIfContainsWhite(exefile);
|
||||||
|
|
||||||
it := PStrEntry(toLink.head);
|
it := PStrEntry(toLink.head);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// The Nimrod Compiler
|
// The Nimrod Compiler
|
||||||
// (c) Copyright 2008 Andreas Rumpf
|
// (c) Copyright 2009 Andreas Rumpf
|
||||||
//
|
//
|
||||||
// See the file "copying.txt", included in this
|
// See the file "copying.txt", included in this
|
||||||
// distribution, for details about the copyright.
|
// distribution, for details about the copyright.
|
||||||
|
|
@ -69,7 +69,7 @@ begin
|
||||||
{@emit}
|
{@emit}
|
||||||
result.id := -1; // for better error checking
|
result.id := -1; // for better error checking
|
||||||
result.kind := skModule;
|
result.kind := skModule;
|
||||||
result.name := getIdent(extractFileTrunk(filename));
|
result.name := getIdent(splitFile(filename).name);
|
||||||
result.owner := result; // a module belongs to itself
|
result.owner := result; // a module belongs to itself
|
||||||
result.info := newLineInfo(filename, 1, 1);
|
result.info := newLineInfo(filename, 1, 1);
|
||||||
include(result.flags, sfUsed);
|
include(result.flags, sfUsed);
|
||||||
|
|
@ -321,14 +321,11 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure MainCommand(const cmd, filename: string);
|
procedure MainCommand(const cmd, filename: string);
|
||||||
var
|
|
||||||
dir, f: string;
|
|
||||||
begin
|
begin
|
||||||
appendStr(searchPaths, options.libpath);
|
appendStr(searchPaths, options.libpath);
|
||||||
if filename <> '' then begin
|
if filename <> '' then begin
|
||||||
splitPath(filename, dir, f);
|
|
||||||
// current path is always looked first for modules
|
// current path is always looked first for modules
|
||||||
prependStr(searchPaths, dir);
|
prependStr(searchPaths, splitFile(filename).dir);
|
||||||
end;
|
end;
|
||||||
setID(100);
|
setID(100);
|
||||||
passes.gIncludeFile := syntaxes.parseFile;
|
passes.gIncludeFile := syntaxes.parseFile;
|
||||||
|
|
|
||||||
|
|
@ -467,7 +467,7 @@ const
|
||||||
'$1 needs a return type',
|
'$1 needs a return type',
|
||||||
'invalid command: ''$1''',
|
'invalid command: ''$1''',
|
||||||
'''$1'' is only allowed at top level',
|
'''$1'' is only allowed at top level',
|
||||||
'template instantiation too nested',
|
'template/macro instantiation too nested',
|
||||||
'instantiation from here',
|
'instantiation from here',
|
||||||
'invalid index value for tuple subscript',
|
'invalid index value for tuple subscript',
|
||||||
'command expects a filename argument',
|
'command expects a filename argument',
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ begin
|
||||||
command := '';
|
command := '';
|
||||||
filename := '';
|
filename := '';
|
||||||
ProcessCmdLine(passCmd1, command, filename);
|
ProcessCmdLine(passCmd1, command, filename);
|
||||||
if filename <> '' then options.projectPath := extractDir(filename);
|
if filename <> '' then options.projectPath := splitFile(filename).dir;
|
||||||
nimconf.LoadConfig(filename); // load the right config file
|
nimconf.LoadConfig(filename); // load the right config file
|
||||||
// now process command line arguments again, because some options in the
|
// now process command line arguments again, because some options in the
|
||||||
// command line can overwite the config file's settings
|
// command line can overwite the config file's settings
|
||||||
|
|
|
||||||
45
nim/nos.pas
45
nim/nos.pas
|
|
@ -29,6 +29,13 @@ uses
|
||||||
type
|
type
|
||||||
EOSError = class(exception)
|
EOSError = class(exception)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TSplitFileResult = record
|
||||||
|
dir, name, ext: string;
|
||||||
|
end;
|
||||||
|
TSplitPathResult = record
|
||||||
|
head, tail: string;
|
||||||
|
end;
|
||||||
|
|
||||||
const
|
const
|
||||||
curdir = '.';
|
curdir = '.';
|
||||||
|
|
@ -59,7 +66,7 @@ procedure putEnv(const name, val: string);
|
||||||
function JoinPath(const head, tail: string): string; overload;
|
function JoinPath(const head, tail: string): string; overload;
|
||||||
function JoinPath(const parts: array of string): string; overload;
|
function JoinPath(const parts: array of string): string; overload;
|
||||||
|
|
||||||
procedure SplitPath(const path: string; out head, tail: string);
|
procedure SplitPath(const path: string; out head, tail: string); overload;
|
||||||
|
|
||||||
function extractDir(const f: string): string;
|
function extractDir(const f: string): string;
|
||||||
function extractFilename(const f: string): string;
|
function extractFilename(const f: string): string;
|
||||||
|
|
@ -87,9 +94,38 @@ function sameFile(const path1, path2: string): boolean;
|
||||||
|
|
||||||
function extractFileTrunk(const filename: string): string;
|
function extractFileTrunk(const filename: string): string;
|
||||||
|
|
||||||
|
function splitFile(const path: string): TSplitFileResult;
|
||||||
|
function splitPath(const path: string): TSplitPathResult; overload;
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
function splitFile(const path: string): TSplitFileResult;
|
||||||
|
var
|
||||||
|
sepPos, dotPos, i: int;
|
||||||
|
begin
|
||||||
|
if (path = '') or (path[length(path)] in [dirSep, altSep]) then begin
|
||||||
|
result.dir := path;
|
||||||
|
result.name := '';
|
||||||
|
result.ext := '';
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
sepPos := 0;
|
||||||
|
dotPos := length(path)+1;
|
||||||
|
for i := length(path) downto 1 do begin
|
||||||
|
if path[i] = ExtSep then begin
|
||||||
|
if (dotPos = length(path)+1) and (i > 1) then dotPos := i
|
||||||
|
end
|
||||||
|
else if path[i] in [dirsep, altsep] then begin
|
||||||
|
sepPos := i; break
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
result.dir := ncopy(path, 1, sepPos-1);
|
||||||
|
result.name := ncopy(path, sepPos+1, dotPos-1);
|
||||||
|
result.ext := ncopy(path, dotPos)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
function extractFileTrunk(const filename: string): string;
|
function extractFileTrunk(const filename: string): string;
|
||||||
var
|
var
|
||||||
f, e, dir: string;
|
f, e, dir: string;
|
||||||
|
|
@ -146,7 +182,7 @@ var
|
||||||
i: int;
|
i: int;
|
||||||
begin
|
begin
|
||||||
result := -1;
|
result := -1;
|
||||||
for i := length(s) downto 1 do
|
for i := length(s) downto 2 do
|
||||||
if s[i] = extsep then begin
|
if s[i] = extsep then begin
|
||||||
result := i;
|
result := i;
|
||||||
break
|
break
|
||||||
|
|
@ -219,6 +255,11 @@ begin
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function SplitPath(const path: string): TSplitPathResult;
|
||||||
|
begin
|
||||||
|
SplitPath(path, result.head, result.tail);
|
||||||
|
end;
|
||||||
|
|
||||||
function getApplicationFilename(): string;
|
function getApplicationFilename(): string;
|
||||||
{$ifdef darwin}
|
{$ifdef darwin}
|
||||||
var
|
var
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,10 @@ const
|
||||||
//cog.outl('VersionMinor = %s;' % ver[1])
|
//cog.outl('VersionMinor = %s;' % ver[1])
|
||||||
//cog.outl('VersionPatch = %s;' % ver[2])
|
//cog.outl('VersionPatch = %s;' % ver[2])
|
||||||
//]]]
|
//]]]
|
||||||
VersionAsString = '0.8.2';
|
VersionAsString = '0.8.3';
|
||||||
VersionMajor = 0;
|
VersionMajor = 0;
|
||||||
VersionMinor = 8;
|
VersionMinor = 8;
|
||||||
VersionPatch = 2;
|
VersionPatch = 3;
|
||||||
//[[[[end]]]]
|
//[[[[end]]]]
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
|
||||||
|
|
@ -176,11 +176,8 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function getPrefixDir: string;
|
function getPrefixDir: string;
|
||||||
var
|
|
||||||
appdir, bin: string;
|
|
||||||
begin
|
begin
|
||||||
appdir := getApplicationDir();
|
result := SplitPath(getApplicationDir()).head;
|
||||||
SplitPath(appdir, result, bin);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function shortenDir(const dir: string): string;
|
function shortenDir(const dir: string): string;
|
||||||
|
|
|
||||||
|
|
@ -415,24 +415,23 @@ type
|
||||||
|
|
||||||
procedure processCompile(c: PContext; n: PNode);
|
procedure processCompile(c: PContext; n: PNode);
|
||||||
var
|
var
|
||||||
s, found, trunc, ext: string;
|
s, found, trunc: string;
|
||||||
begin
|
begin
|
||||||
s := expectStrLit(c, n);
|
s := expectStrLit(c, n);
|
||||||
found := findFile(s);
|
found := findFile(s);
|
||||||
if found = '' then found := s;
|
if found = '' then found := s;
|
||||||
splitFilename(found, trunc, ext);
|
trunc := ChangeFileExt(found, '');
|
||||||
extccomp.addExternalFileToCompile(trunc);
|
extccomp.addExternalFileToCompile(trunc);
|
||||||
extccomp.addFileToLink(completeCFilePath(trunc, false));
|
extccomp.addFileToLink(completeCFilePath(trunc, false));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure processCommonLink(c: PContext; n: PNode; feature: TLinkFeature);
|
procedure processCommonLink(c: PContext; n: PNode; feature: TLinkFeature);
|
||||||
var
|
var
|
||||||
f, tmp, ext, found: string;
|
f, found: string;
|
||||||
begin
|
begin
|
||||||
f := expectStrLit(c, n);
|
f := expectStrLit(c, n);
|
||||||
splitFilename(f, tmp, ext);
|
if splitFile(f).ext = '' then
|
||||||
if (ext = '') then
|
f := toObjFile(f);
|
||||||
f := toObjFile(tmp);
|
|
||||||
found := findFile(f);
|
found := findFile(f);
|
||||||
if found = '' then
|
if found = '' then
|
||||||
found := f; // use the default
|
found := f; // use the default
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// The Nimrod Compiler
|
// The Nimrod Compiler
|
||||||
// (c) Copyright 2008 Andreas Rumpf
|
// (c) Copyright 2009 Andreas Rumpf
|
||||||
//
|
//
|
||||||
// See the file "copying.txt", included in this
|
// See the file "copying.txt", included in this
|
||||||
// distribution, for details about the copyright.
|
// distribution, for details about the copyright.
|
||||||
//
|
//
|
||||||
unit rst;
|
unit rst;
|
||||||
|
|
||||||
// This module implements a *reStructuredText* parser. Currently, only a
|
// This module implements a *reStructuredText* parser. A larget
|
||||||
// subset is provided. Later, there will be additions.
|
// subset is provided.
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -130,12 +130,17 @@ begin
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{$include 'semtempl.pas'}
|
||||||
|
|
||||||
function semMacroExpr(c: PContext; n: PNode; sym: PSym;
|
function semMacroExpr(c: PContext; n: PNode; sym: PSym;
|
||||||
semCheck: bool = true): PNode;
|
semCheck: bool = true): PNode;
|
||||||
var
|
var
|
||||||
p: PEvalContext;
|
p: PEvalContext;
|
||||||
s: PStackFrame;
|
s: PStackFrame;
|
||||||
begin
|
begin
|
||||||
|
inc(evalTemplateCounter);
|
||||||
|
if evalTemplateCounter > 100 then
|
||||||
|
liMessage(n.info, errTemplateInstantiationTooNested);
|
||||||
markUsed(n, sym);
|
markUsed(n, sym);
|
||||||
p := newEvalContext(c.module, '', false);
|
p := newEvalContext(c.module, '', false);
|
||||||
s := newStackFrame();
|
s := newStackFrame();
|
||||||
|
|
@ -150,9 +155,9 @@ begin
|
||||||
if cyclicTree(result) then liMessage(n.info, errCyclicTree);
|
if cyclicTree(result) then liMessage(n.info, errCyclicTree);
|
||||||
if semCheck then
|
if semCheck then
|
||||||
result := semAfterMacroCall(c, result, sym);
|
result := semAfterMacroCall(c, result, sym);
|
||||||
|
dec(evalTemplateCounter);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{$include 'semtempl.pas'}
|
|
||||||
{$include 'seminst.pas'}
|
{$include 'seminst.pas'}
|
||||||
{$include 'sigmatch.pas'}
|
{$include 'sigmatch.pas'}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -517,20 +517,19 @@ begin
|
||||||
result := nil;
|
result := nil;
|
||||||
prc := n.sons[0];
|
prc := n.sons[0];
|
||||||
checkMinSonsLen(n, 1);
|
checkMinSonsLen(n, 1);
|
||||||
case n.sons[0].kind of
|
if n.sons[0].kind = nkDotExpr then begin
|
||||||
nkDotExpr: begin
|
checkSonsLen(n.sons[0], 2);
|
||||||
checkSonsLen(n.sons[0], 2);
|
n.sons[0] := semDotExpr(c, n.sons[0]);
|
||||||
n.sons[0] := semDotExpr(c, n.sons[0]);
|
if n.sons[0].kind = nkDotCall then begin // it is a static call!
|
||||||
if n.sons[0].kind = nkDotCall then begin // it is a static call!
|
result := n.sons[0];
|
||||||
result := n.sons[0];
|
result.kind := nkCall;
|
||||||
result.kind := nkCall;
|
for i := 1 to sonsLen(n)-1 do addSon(result, n.sons[i]);
|
||||||
for i := 1 to sonsLen(n)-1 do addSon(result, n.sons[i]);
|
result := semExpr(c, result, flags);
|
||||||
result := semExpr(c, result);
|
exit
|
||||||
exit
|
end
|
||||||
end
|
end
|
||||||
end;
|
else
|
||||||
else n.sons[0] := semExpr(c, n.sons[0]);
|
n.sons[0] := semExpr(c, n.sons[0]);
|
||||||
end;
|
|
||||||
semOpAux(c, n);
|
semOpAux(c, n);
|
||||||
if (n.sons[0].typ <> nil) then t := skipTypes(n.sons[0].typ, abstractInst)
|
if (n.sons[0].typ <> nil) then t := skipTypes(n.sons[0].typ, abstractInst)
|
||||||
else t := nil;
|
else t := nil;
|
||||||
|
|
|
||||||
|
|
@ -162,9 +162,11 @@ begin
|
||||||
while (last <= length(s)) and (s[last] in seps) do inc(last);
|
while (last <= length(s)) and (s[last] in seps) do inc(last);
|
||||||
first := last;
|
first := last;
|
||||||
while (last <= length(s)) and not (s[last] in seps) do inc(last);
|
while (last <= length(s)) and not (s[last] in seps) do inc(last);
|
||||||
len := length(result);
|
if first >= last-1 then begin
|
||||||
setLength(result, len+1);
|
len := length(result);
|
||||||
result[len] := ncopy(s, first, last-1);
|
setLength(result, len+1);
|
||||||
|
result[len] := ncopy(s, first, last-1);
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
|
||||||
8
tests/titer5.nim
Executable file
8
tests/titer5.nim
Executable file
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Test method call syntax for iterators:
|
||||||
|
const lines = """abc xyz"""
|
||||||
|
|
||||||
|
for x in lines.split():
|
||||||
|
stdout.write(x)
|
||||||
|
|
||||||
|
#OUT abcxyz
|
||||||
|
|
||||||
|
|
@ -220,7 +220,7 @@ proc main(c: var TConfigData) =
|
||||||
buildAddDoc(c, "web/upload")
|
buildAddDoc(c, "web/upload")
|
||||||
buildDoc(c, "web/upload")
|
buildDoc(c, "web/upload")
|
||||||
buildDoc(c, "doc")
|
buildDoc(c, "doc")
|
||||||
#buildPdfDoc(c, "doc")
|
buildPdfDoc(c, "doc")
|
||||||
|
|
||||||
var c: TConfigData
|
var c: TConfigData
|
||||||
initConfigData(c)
|
initConfigData(c)
|
||||||
|
|
|
||||||
|
|
@ -94,11 +94,6 @@ Nimrod plays nice with others
|
||||||
New bindings are easily generated in a semi-automatic way.
|
New bindings are easily generated in a semi-automatic way.
|
||||||
* A Pascal to Nimrod conversion utility: A large subset of Object Pascal
|
* A Pascal to Nimrod conversion utility: A large subset of Object Pascal
|
||||||
can be translated to Nimrod automatically!
|
can be translated to Nimrod automatically!
|
||||||
* Nimrod's documentation syntax is a subset of the wonderfully readable plaintext
|
|
||||||
markup syntax
|
|
||||||
`reStructuredText <http://docutils.sourceforge.net/docs/user/rst/quickref.html>`_.
|
|
||||||
The documentation generator is very flexible; this website has been generated
|
|
||||||
with it!
|
|
||||||
|
|
||||||
|
|
||||||
Roadmap to 1.0
|
Roadmap to 1.0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue