mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-18 23:11:36 +00:00
support for multiple modules of the same name; niminst supports 'platforms'; minor bugfixes
This commit is contained in:
@@ -1210,7 +1210,7 @@ proc writeHeader(m: BModule) =
|
||||
writeRope(result, m.filename)
|
||||
|
||||
proc getCFile(m: BModule): string =
|
||||
result = changeFileExt(completeCFilePath(m.cfilename), cExt)
|
||||
result = changeFileExt(completeCFilePath(m.cfilename.withPackageName), cExt)
|
||||
|
||||
proc myOpenCached(module: PSym, rd: PRodReader): PPassContext =
|
||||
assert optSymbolFiles in gGlobalOptions
|
||||
|
||||
@@ -162,10 +162,11 @@ var
|
||||
gNestedEvals: int # count the recursive calls to ``evalAux`` to prevent
|
||||
# endless recursion
|
||||
|
||||
proc evalWhile(c: PEvalContext, n: PNode): PNode =
|
||||
while true:
|
||||
proc evalWhile(c: PEvalContext, n: PNode): PNode =
|
||||
while true:
|
||||
evalX(n.sons[0], {})
|
||||
if getOrdValue(result) == 0: break
|
||||
if getOrdValue(result) == 0:
|
||||
result = emptyNode; break
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
case result.kind
|
||||
of nkBreakStmt:
|
||||
@@ -304,7 +305,7 @@ proc allocSlot(c: PStackFrame; sym: PSym): int =
|
||||
setLen(c.slots, max(result+1, c.slots.len))
|
||||
|
||||
proc setSlot(c: PStackFrame, sym: PSym, val: PNode) =
|
||||
assert sym.owner == c.prc
|
||||
assert sym.owner == c.prc or sfFromGeneric in sym.flags
|
||||
let idx = allocSlot(c, sym)
|
||||
c.slots[idx] = val
|
||||
|
||||
@@ -377,7 +378,7 @@ proc evalVariable(c: PStackFrame, sym: PSym, flags: TEvalFlags): PNode =
|
||||
#result = emptyNode
|
||||
|
||||
proc evalGlobalVar(c: PEvalContext, s: PSym, flags: TEvalFlags): PNode =
|
||||
if sfCompileTime in s.flags or c.mode == emRepl:
|
||||
if sfCompileTime in s.flags or c.mode == emRepl or s.kind == skForVar:
|
||||
result = IdNodeTableGet(c.globals, s)
|
||||
if result != nil:
|
||||
if not aliasNeeded(result, flags):
|
||||
@@ -549,7 +550,9 @@ proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
of skProc, skConverter, skMacro, skType:
|
||||
result = n
|
||||
#result = s.getBody
|
||||
of skVar, skLet, skForVar, skTemp, skResult:
|
||||
of skForVar:
|
||||
result = evalGlobalVar(c, s, flags)
|
||||
of skVar, skLet, skTemp, skResult:
|
||||
if sfGlobal notin s.flags:
|
||||
result = evalVariable(c.tos, s, flags)
|
||||
else:
|
||||
@@ -1396,7 +1399,7 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
of nkChckRangeF, nkChckRange64, nkChckRange: result = evalRangeChck(c, n)
|
||||
of nkStringToCString: result = evalConvStrToCStr(c, n)
|
||||
of nkCStringToString: result = evalConvCStrToStr(c, n)
|
||||
of nkStmtListExpr, nkStmtList, nkModule:
|
||||
of nkStmtListExpr, nkStmtList:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
result = evalAux(c, n.sons[i], flags)
|
||||
case result.kind
|
||||
@@ -1455,7 +1458,7 @@ proc evalConstExprAux*(p: PEvalContext, module, prc: PSym, e: PNode): PNode =
|
||||
|
||||
proc setupMacroParam(x: PNode): PNode =
|
||||
result = x
|
||||
if result.kind == nkHiddenStdConv: result = result.sons[1]
|
||||
if result.kind in {nkHiddenSubConv, nkHiddenStdConv}: result = result.sons[1]
|
||||
|
||||
proc evalMacroCall(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode =
|
||||
# XXX GlobalError() is ugly here, but I don't know a better solution for now
|
||||
|
||||
@@ -298,13 +298,13 @@ const
|
||||
gpp()]
|
||||
|
||||
const
|
||||
hExt* = "h"
|
||||
hExt* = ".h"
|
||||
|
||||
var
|
||||
cCompiler* = ccGcc # the used compiler
|
||||
|
||||
cExt* = "c" # extension of generated C/C++ files
|
||||
# (can be changed to .cpp later)
|
||||
cExt* = ".c" # extension of generated C/C++ files
|
||||
# (can be changed to .cpp later)
|
||||
|
||||
cIncludes*: seq[string] = @[] # directories to search for included files
|
||||
cLibs*: seq[string] = @[] # directories to search for lib files
|
||||
@@ -518,7 +518,7 @@ proc footprint(filename: string): TCrc32 =
|
||||
getCompileCFileCmd(filename, true)
|
||||
|
||||
proc externalFileChanged(filename: string): bool =
|
||||
var crcFile = toGeneratedFile(filename, "crc")
|
||||
var crcFile = toGeneratedFile(filename.withPackageName, "crc")
|
||||
var currentCrc = int(footprint(filename))
|
||||
var f: TFile
|
||||
if open(f, crcFile, fmRead):
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
[Project]
|
||||
Name: "Nimrod"
|
||||
Version: "$version"
|
||||
OS: "windows;linux;macosx;solaris;freebsd;netbsd;openbsd"
|
||||
CPU: "i386;amd64;powerpc64;arm" # ;sparc
|
||||
Platforms: """
|
||||
windows: i386;amd64
|
||||
linux: i386;amd64;powerpc64;arm;sparc;mips
|
||||
macosx: i386;amd64;powerpc64
|
||||
solaris: i386;amd64;sparc
|
||||
freebsd: i386;amd64
|
||||
netbsd: i386;amd64
|
||||
openbsd: i386;amd64
|
||||
haiku: i386;amd64
|
||||
"""
|
||||
|
||||
Authors: "Andreas Rumpf"
|
||||
Description: """This is the Nimrod Compiler. Nimrod is a new statically typed,
|
||||
|
||||
@@ -208,7 +208,19 @@ proc removeTrailingDirSep*(path: string): string =
|
||||
proc getGeneratedPath: string =
|
||||
result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir /
|
||||
genSubDir
|
||||
|
||||
|
||||
proc withPackageName*(path: string): string =
|
||||
var x = path
|
||||
while true:
|
||||
x = parentDir(x)
|
||||
if x.len == 0: break
|
||||
case x.normalize
|
||||
of "lib", "src", "source", "package", "pckg", "library": discard
|
||||
else:
|
||||
let (path, file, ext) = path.splitFile
|
||||
return (path / (x & '_' & file)) & ext
|
||||
result = path
|
||||
|
||||
proc toGeneratedFile*(path, ext: string): string =
|
||||
## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
|
||||
var (head, tail) = splitPath(path)
|
||||
|
||||
@@ -1440,7 +1440,7 @@ proc parseSection(p: var TParser, kind: TNodeKind,
|
||||
skipComment(p, result)
|
||||
while sameInd(p):
|
||||
case p.tok.tokType
|
||||
of tkSymbol, tkAccent:
|
||||
of tkSymbol, tkAccent, tkParLe:
|
||||
var a = defparser(p)
|
||||
skipComment(p, a)
|
||||
addSon(result, a)
|
||||
|
||||
@@ -818,7 +818,7 @@ proc checkDep(fileIdx: int32): TReasonForRecompile =
|
||||
gMods[fileIdx].reason = rrNone # we need to set it here to avoid cycles
|
||||
result = rrNone
|
||||
var r: PRodReader = nil
|
||||
var rodfile = toGeneratedFile(filename, RodExt)
|
||||
var rodfile = toGeneratedFile(filename.withPackageName, RodExt)
|
||||
r = newRodReader(rodfile, crc, fileIdx)
|
||||
if r == nil:
|
||||
result = (if ExistsFile(rodfile): rrRodInvalid else: rrRodDoesNotExist)
|
||||
|
||||
@@ -421,7 +421,8 @@ proc addStmt(w: PRodWriter, n: PNode) =
|
||||
proc writeRod(w: PRodWriter) =
|
||||
processStacks(w, true)
|
||||
var f: TFile
|
||||
if not open(f, completeGeneratedFilePath(changeFileExt(w.filename, "rod")),
|
||||
if not open(f, completeGeneratedFilePath(changeFileExt(
|
||||
w.filename.withPackageName, RodExt)),
|
||||
fmWrite):
|
||||
#echo "couldn't write rod file for: ", w.filename
|
||||
return
|
||||
|
||||
@@ -890,7 +890,7 @@ proc evalStaticExpr*(module: PSym, e: PNode, prc: PSym): PNode =
|
||||
|
||||
proc setupMacroParam(x: PNode): PNode =
|
||||
result = x
|
||||
if result.kind == nkHiddenStdConv: result = result.sons[1]
|
||||
if result.kind in {nkHiddenSubConv, nkHiddenStdConv}: result = result.sons[1]
|
||||
|
||||
proc evalMacroCall(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode =
|
||||
# XXX GlobalError() is ugly here, but I don't know a better solution for now
|
||||
|
||||
@@ -104,11 +104,12 @@ exprStmt = simpleExpr
|
||||
| IND{=} 'except' exprList ':' stmt
|
||||
| IND{=} 'else' ':' stmt )*
|
||||
))?
|
||||
importStmt = 'import' optInd expr
|
||||
((comma expr)*
|
||||
moduleName = expr ('as' expr)?
|
||||
importStmt = 'import' optInd moduleName
|
||||
((comma moduleName)*
|
||||
/ 'except' optInd (expr ^+ comma))
|
||||
includeStmt = 'include' optInd expr ^+ comma
|
||||
fromStmt = 'from' expr 'import' optInd expr (comma expr)*
|
||||
fromStmt = 'from' moduleName 'import' optInd expr (comma expr)*
|
||||
returnStmt = 'return' optInd expr?
|
||||
raiseStmt = 'raise' optInd expr?
|
||||
yieldStmt = 'yield' optInd expr?
|
||||
|
||||
@@ -2018,11 +2018,11 @@ Example:
|
||||
The `when`:idx: statement is almost identical to the ``if`` statement with some
|
||||
exceptions:
|
||||
|
||||
* Each ``expr`` has to be a constant expression (of type ``bool``).
|
||||
* Each condition (``expr``) has to be a constant expression (of type ``bool``).
|
||||
* The statements do not open a new scope.
|
||||
* The statements that belong to the expression that evaluated to true are
|
||||
translated by the compiler, the other statements are not checked for
|
||||
semantics! However, each ``expr`` is checked for semantics.
|
||||
semantics! However, each condition is checked for semantics.
|
||||
|
||||
The ``when`` statement enables conditional compilation techniques. As
|
||||
a special syntactic extension, the ``when`` construct is also available
|
||||
@@ -2268,7 +2268,7 @@ A `table constructor`:idx: is syntactic sugar for an array constructor:
|
||||
{"key1": "value1", "key2", "key3": "value2"}
|
||||
|
||||
# is the same as:
|
||||
[("key1", "value1"), ("key2", "value2"), ("key3", "value")]
|
||||
[("key1", "value1"), ("key2", "value2"), ("key3", "value2")]
|
||||
|
||||
|
||||
The empty table can be written ``{:}`` (in contrast to the empty set
|
||||
@@ -2565,9 +2565,6 @@ Overloading of the subscript operator
|
||||
-------------------------------------
|
||||
|
||||
The ``[]`` subscript operator for arrays/openarrays/sequences can be overloaded.
|
||||
Overloading support is only possible if the first parameter has no type that
|
||||
already supports the built-in ``[]`` notation. Currently the compiler
|
||||
does not check this restriction.
|
||||
|
||||
|
||||
Multi-methods
|
||||
@@ -3301,13 +3298,11 @@ Specifically, the type class will be matched if:
|
||||
a) all of the expressions within the body can be compiled for the tested type
|
||||
b) all statically evaluatable boolean expressions in the body must be true
|
||||
|
||||
Please note that the `is` operator allows you to easily verify the precise type
|
||||
Please note that the ``is`` operator allows you to easily verify the precise type
|
||||
signatures of the required operations, but since type inference and default
|
||||
parameters are still applied in the provided block, it's also possible to encode
|
||||
usage protocols that doesn't reveal implementation details.
|
||||
|
||||
.. code-block:: nimrod
|
||||
|
||||
Much like generics, the user defined type classes will be instantiated exactly
|
||||
once for each tested type and any static code included within them will also be
|
||||
executed once.
|
||||
@@ -3327,7 +3322,7 @@ from the proc body. This is usually used with the ``auto`` type class:
|
||||
The return type will be treated as additional generic param and can be
|
||||
explicitly specified at call sites as any other generic param.
|
||||
|
||||
Future versions of nimrod may also support overloading based on the return type
|
||||
Future versions of Nimrod may also support overloading based on the return type
|
||||
of the overloads. In such settings, the expected result type at call sites may
|
||||
also influence the inferred return type.
|
||||
|
||||
@@ -3398,8 +3393,9 @@ templates:
|
||||
|
||||
The "types" of templates can be the symbols ``expr`` (stands for *expression*),
|
||||
``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type
|
||||
description*). These are no real types, they just help the compiler parsing.
|
||||
Real types can be used too; this implies that expressions are expected.
|
||||
description*). These are "meta types", they can only be used in certain
|
||||
contexts. Real types can be used too; this implies that expressions are
|
||||
expected.
|
||||
|
||||
|
||||
Ordinary vs immediate templates
|
||||
@@ -3868,7 +3864,7 @@ values inside containers and so on. For example, here is how one can create
|
||||
a type-safe wrapper for the unsafe `printf` function from C:
|
||||
|
||||
.. code-block:: nimrod
|
||||
macro safePrintF(formatString: string{lit}, args: vararg[expr]): expr =
|
||||
macro safePrintF(formatString: string{lit}, args: varargs[expr]): expr =
|
||||
var i = 0
|
||||
for c in formatChars(formatString):
|
||||
var expectedType = case c
|
||||
@@ -4196,10 +4192,10 @@ implemented with term rewriting:
|
||||
template optP2{p(x, y, false)}(x, y: expr): expr = x - y
|
||||
|
||||
|
||||
Example: hoisting
|
||||
Example: Hoisting
|
||||
-----------------
|
||||
|
||||
The following example how some form of hoisting can be implemented:
|
||||
The following example shows how some form of hoisting can be implemented:
|
||||
|
||||
.. code-block:: nimrod
|
||||
import pegs
|
||||
@@ -4267,7 +4263,7 @@ optimization for types that have copying semantics:
|
||||
|
||||
var t: TTable
|
||||
# overloading resolution ensures that the optimized []= is called here:
|
||||
t["abc"] = "xyz"
|
||||
t[f()] = g()
|
||||
|
||||
|
||||
|
||||
@@ -4326,6 +4322,36 @@ module name followed by an ``except`` to prevent some symbols to be imported:
|
||||
echo "$1" % "abc"
|
||||
|
||||
|
||||
Module names in imports
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A module alias can be introduced via the ``as`` keyword:
|
||||
|
||||
.. code-block:: nimrod
|
||||
import strutils as su, sequtils as qu
|
||||
|
||||
echo su.format("$1", "lalelu")
|
||||
|
||||
The original module name is then not accessible. The
|
||||
notations ``path/to/module`` or ``path.to.module`` or ``"path/to/module"``
|
||||
can be used to refer to a module in subdirectories:
|
||||
|
||||
.. code-block:: nimrod
|
||||
import lib.pure.strutils, lib/pure/os, "lib/pure/times"
|
||||
|
||||
Note that the module name is still ``strutils`` and not ``lib.pure.strutils``
|
||||
and so one **cannot** do:
|
||||
|
||||
.. code-block:: nimrod
|
||||
import lib.pure.strutils
|
||||
echo lib.pure.strutils
|
||||
|
||||
Likewise the following does not make sense as the name is ``strutils`` already:
|
||||
|
||||
.. code-block:: nimrod
|
||||
import lib.pure.strutils as strutils
|
||||
|
||||
|
||||
From import statement
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -5085,9 +5111,9 @@ string expressions in general:
|
||||
|
||||
proc getDllName: string =
|
||||
result = "mylib.dll"
|
||||
if ExistsFile(result): return
|
||||
if existsFile(result): return
|
||||
result = "mylib2.dll"
|
||||
if ExistsFile(result): return
|
||||
if existsFile(result): return
|
||||
quit("could not load dynamic library")
|
||||
|
||||
proc myImport(s: cstring) {.cdecl, importc, dynlib: getDllName().}
|
||||
|
||||
@@ -38,7 +38,7 @@ type
|
||||
nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange,
|
||||
nnkStringToCString, nnkCStringToString, nnkAsgn,
|
||||
nnkFastAsgn, nnkGenericParams, nnkFormalParams, nnkOfInherit,
|
||||
nnkModule, nnkProcDef, nnkMethodDef, nnkConverterDef,
|
||||
nnkImportAs, nnkProcDef, nnkMethodDef, nnkConverterDef,
|
||||
nnkMacroDef, nnkTemplateDef, nnkIteratorDef, nnkOfBranch,
|
||||
nnkElifBranch, nnkExceptBranch, nnkElse,
|
||||
nnkAsmStmt, nnkPragma, nnkPragmaBlock, nnkIfStmt, nnkWhenStmt,
|
||||
|
||||
6
todo.txt
6
todo.txt
@@ -1,6 +1,8 @@
|
||||
version 0.9.4
|
||||
=============
|
||||
|
||||
- change search path algorithm to care about packages
|
||||
- XXX how can 'lib_system' ever be generated?
|
||||
- new VM:
|
||||
- implement the glue to replace evals.nim
|
||||
- implement missing magics
|
||||
@@ -20,7 +22,6 @@ version 0.9.4
|
||||
Bugs
|
||||
====
|
||||
|
||||
- 'quote' without 'do' doesn't work
|
||||
- compilation of niminst takes way too long. looks like a regression
|
||||
- simple closure iterator doesn't work
|
||||
- docgen: sometimes effects are listed twice
|
||||
@@ -46,6 +47,7 @@ version 0.9.x
|
||||
* test libffi on windows
|
||||
* test: times.format with the FFI
|
||||
- document NimMain and check whether it works for threading
|
||||
- 'quote' without 'do' doesn't work: parser/grammar issue; could be supported
|
||||
|
||||
|
||||
version 0.9.X
|
||||
@@ -125,7 +127,7 @@ GC
|
||||
CGEN
|
||||
====
|
||||
- codegen should use "NIM_CAST" macro and respect aliasing rules for GCC
|
||||
- ``restrict`` pragma + backend support; computed goto support
|
||||
- ``restrict`` pragma + backend support
|
||||
- 'const' objects including case objects
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Installation Generator
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -52,10 +52,12 @@ type
|
||||
cat: array[TFileCategory, seq[string]]
|
||||
binPaths, authors, oses, cpus: seq[string]
|
||||
cfiles: array[1..maxOS, array[1..maxCPU, seq[string]]]
|
||||
platforms: array[1..maxOS, array[1..maxCPU, bool]]
|
||||
ccompiler, linker, innosetup: tuple[path, flags: string]
|
||||
name, displayName, version, description, license, infile, outdir: string
|
||||
libpath: string
|
||||
innoSetupFlag, installScript, uninstallScript: bool
|
||||
explicitPlatforms: bool
|
||||
vars: PStringTable
|
||||
app: TAppType
|
||||
nimrodArgs: string
|
||||
@@ -126,7 +128,7 @@ const
|
||||
Version = "0.9"
|
||||
Usage = "niminst - Nimrod Installation Generator Version " & version & """
|
||||
|
||||
(c) 2012 Andreas Rumpf
|
||||
(c) 2013 Andreas Rumpf
|
||||
Usage:
|
||||
niminst [options] command[;command2...] ini-file[.ini] [compile_options]
|
||||
Command:
|
||||
@@ -221,6 +223,23 @@ proc yesno(p: var TCfgParser, v: string): bool =
|
||||
result = false
|
||||
else: quit(errorStr(p, "unknown value; use: yes|no"))
|
||||
|
||||
proc incl(s: var seq[string], x: string): int =
|
||||
for i in 0.. <s.len:
|
||||
if cmpIgnoreStyle(s[i], x) == 0: return i
|
||||
s.add(x)
|
||||
result = s.len-1
|
||||
|
||||
proc platforms(c: var TConfigData, v: string) =
|
||||
for line in splitLines(v):
|
||||
let p = line.find(": ")
|
||||
if p <= 1: continue
|
||||
let os = line.substr(0, p-1).strip
|
||||
let cpus = line.substr(p+1).strip
|
||||
c.oses.add(os)
|
||||
for cpu in cpus.split(';'):
|
||||
let cpuIdx = c.cpus.incl(cpu)
|
||||
c.platforms[c.oses.len][cpuIdx+1] = true
|
||||
|
||||
proc parseIniFile(c: var TConfigData) =
|
||||
var
|
||||
p: TCfgParser
|
||||
@@ -244,8 +263,19 @@ proc parseIniFile(c: var TConfigData) =
|
||||
of "name": c.name = v
|
||||
of "displayname": c.displayName = v
|
||||
of "version": c.version = v
|
||||
of "os": c.oses = split(v, {';'})
|
||||
of "cpu": c.cpus = split(v, {';'})
|
||||
of "os":
|
||||
c.oses = split(v, {';'})
|
||||
if c.explicitPlatforms:
|
||||
quit(errorStr(p, "you cannot have both 'platforms' and 'os'"))
|
||||
of "cpu":
|
||||
c.cpus = split(v, {';'})
|
||||
if c.explicitPlatforms:
|
||||
quit(errorStr(p, "you cannot have both 'platforms' and 'cpu'"))
|
||||
of "platforms":
|
||||
platforms(c, v)
|
||||
c.explicitPlatforms = true
|
||||
if c.cpus.len > 0 or c.oses.len > 0:
|
||||
quit(errorStr(p, "you cannot have both 'platforms' and 'os'"))
|
||||
of "authors": c.authors = split(v, {';'})
|
||||
of "description": c.description = v
|
||||
of "app":
|
||||
@@ -409,6 +439,7 @@ proc srcdist(c: var TConfigData) =
|
||||
let osname = c.oses[osA-1]
|
||||
if osname.cmpIgnoreStyle("windows") == 0: winIndex = osA-1
|
||||
for cpuA in 1..c.cpus.len:
|
||||
if c.explicitPlatforms and not c.platforms[osA][cpuA]: continue
|
||||
let cpuname = c.cpus[cpuA-1]
|
||||
if cpuname.cmpIgnoreStyle("i386") == 0: intel32Index = cpuA-1
|
||||
elif cpuname.cmpIgnoreStyle("amd64") == 0: intel64Index = cpuA-1
|
||||
|
||||
Reference in New Issue
Block a user