bugfixes: macros; splitFile; strutils.split; iterator.method

This commit is contained in:
rumpf_a@web.de 2009-10-27 22:28:02 +01:00
commit d5acb88ccc
31 changed files with 177 additions and 95 deletions

View file

@ -247,6 +247,7 @@
'StrToIdent', 'StrToIdent',
'IdentToStr', 'IdentToStr',
'EqIdent', 'EqIdent',
'EqNimrodNode',
'NHint', 'NHint',
'NWarning', 'NWarning',
'NError' 'NError'

View file

@ -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'},

View file

@ -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

View file

@ -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*.

View file

@ -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

View file

@ -6,7 +6,7 @@
:Version: |nimrodversion| :Version: |nimrodversion|
.. contents:: .. contents::
Introduction Introduction
============ ============

View file

@ -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
View file

@ -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 ----------------------------------------

View file

@ -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`.

View file

@ -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]

View file

@ -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.

View file

@ -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]]]
); );

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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',

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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'}

View file

@ -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;

View file

@ -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
View 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

View file

@ -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)

View file

@ -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