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