.experimental can now be used to enable specific features
This commit is contained in:
parent
8ce9e43434
commit
ee366f1746
18 changed files with 122 additions and 116 deletions
|
|
@ -102,4 +102,10 @@
|
||||||
- Added ``macros.getProjectPath`` and ``ospaths.putEnv`` procs to Nim's virtual
|
- Added ``macros.getProjectPath`` and ``ospaths.putEnv`` procs to Nim's virtual
|
||||||
machine.
|
machine.
|
||||||
|
|
||||||
|
- The ``deadCodeElim`` option is now always turned on and the switch has no
|
||||||
|
effect anymore, but is recognized for backwards compatibility.
|
||||||
|
|
||||||
|
- ``experimental`` is now a pragma / command line switch that can enable specific
|
||||||
|
language extensions, it is not an all-or-nothing switch anymore.
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
|
||||||
|
|
@ -46,9 +46,9 @@ type
|
||||||
passCmd2, # second pass over the command line
|
passCmd2, # second pass over the command line
|
||||||
passPP # preprocessor called processCommand()
|
passPP # preprocessor called processCommand()
|
||||||
|
|
||||||
proc processCommand*(switch: string, pass: TCmdLinePass)
|
proc processCommand*(switch: string, pass: TCmdLinePass; config: ConfigRef)
|
||||||
proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
config: ConfigRef = nil)
|
config: ConfigRef)
|
||||||
|
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
|
|
@ -58,7 +58,13 @@ const
|
||||||
|
|
||||||
const
|
const
|
||||||
Usage = slurp"../doc/basicopt.txt".replace("//", "")
|
Usage = slurp"../doc/basicopt.txt".replace("//", "")
|
||||||
AdvancedUsage = slurp"../doc/advopt.txt".replace("//", "")
|
FeatureDesc = block:
|
||||||
|
var x = ""
|
||||||
|
for f in low(Feature)..high(Feature):
|
||||||
|
if x.len > 0: x.add "|"
|
||||||
|
x.add $f
|
||||||
|
x
|
||||||
|
AdvancedUsage = slurp"../doc/advopt.txt".replace("//", "") % FeatureDesc
|
||||||
|
|
||||||
proc getCommandLineDesc(): string =
|
proc getCommandLineDesc(): string =
|
||||||
result = (HelpMessage % [VersionAsString, platform.OS[platform.hostOS].name,
|
result = (HelpMessage % [VersionAsString, platform.OS[platform.hostOS].name,
|
||||||
|
|
@ -276,7 +282,6 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
|
||||||
of "tlsemulation": result = contains(gGlobalOptions, optTlsEmulation)
|
of "tlsemulation": result = contains(gGlobalOptions, optTlsEmulation)
|
||||||
of "implicitstatic": result = contains(gOptions, optImplicitStatic)
|
of "implicitstatic": result = contains(gOptions, optImplicitStatic)
|
||||||
of "patterns": result = contains(gOptions, optPatterns)
|
of "patterns": result = contains(gOptions, optPatterns)
|
||||||
of "experimental": result = gExperimentalMode
|
|
||||||
of "excessivestacktrace": result = contains(gGlobalOptions, optExcessiveStackTrace)
|
of "excessivestacktrace": result = contains(gGlobalOptions, optExcessiveStackTrace)
|
||||||
else: invalidCmdLineOption(passCmd1, switch, info)
|
else: invalidCmdLineOption(passCmd1, switch, info)
|
||||||
|
|
||||||
|
|
@ -339,7 +344,7 @@ proc dynlibOverride(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
||||||
options.inclDynlibOverride(arg)
|
options.inclDynlibOverride(arg)
|
||||||
|
|
||||||
proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
config: ConfigRef = nil) =
|
config: ConfigRef) =
|
||||||
var
|
var
|
||||||
theOS: TSystemOS
|
theOS: TSystemOS
|
||||||
cpu: TSystemCPU
|
cpu: TSystemCPU
|
||||||
|
|
@ -694,8 +699,13 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
# only supported for compatibility. Does nothing.
|
# only supported for compatibility. Does nothing.
|
||||||
expectArg(switch, arg, pass, info)
|
expectArg(switch, arg, pass, info)
|
||||||
of "experimental":
|
of "experimental":
|
||||||
expectNoArg(switch, arg, pass, info)
|
if arg.len == 0:
|
||||||
gExperimentalMode = true
|
config.features.incl oldExperimentalFeatures
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
config.features.incl parseEnum[Feature](arg)
|
||||||
|
except ValueError:
|
||||||
|
localError(info, "unknown experimental feature")
|
||||||
of "nocppexceptions":
|
of "nocppexceptions":
|
||||||
expectNoArg(switch, arg, pass, info)
|
expectNoArg(switch, arg, pass, info)
|
||||||
incl(gGlobalOptions, optNoCppExceptions)
|
incl(gGlobalOptions, optNoCppExceptions)
|
||||||
|
|
@ -706,7 +716,8 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
config.cppDefine(arg)
|
config.cppDefine(arg)
|
||||||
of "newruntime":
|
of "newruntime":
|
||||||
expectNoArg(switch, arg, pass, info)
|
expectNoArg(switch, arg, pass, info)
|
||||||
newDestructors = true
|
doAssert(config != nil)
|
||||||
|
incl(config.features, destructor)
|
||||||
defineSymbol("nimNewRuntime")
|
defineSymbol("nimNewRuntime")
|
||||||
of "cppcompiletonamespace":
|
of "cppcompiletonamespace":
|
||||||
expectNoArg(switch, arg, pass, info)
|
expectNoArg(switch, arg, pass, info)
|
||||||
|
|
@ -716,10 +727,10 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
|
if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
|
||||||
else: invalidCmdLineOption(pass, switch, info)
|
else: invalidCmdLineOption(pass, switch, info)
|
||||||
|
|
||||||
proc processCommand(switch: string, pass: TCmdLinePass) =
|
proc processCommand(switch: string, pass: TCmdLinePass; config: ConfigRef) =
|
||||||
var cmd, arg: string
|
var cmd, arg: string
|
||||||
splitSwitch(switch, cmd, arg, pass, gCmdLineInfo)
|
splitSwitch(switch, cmd, arg, pass, gCmdLineInfo)
|
||||||
processSwitch(cmd, arg, pass, gCmdLineInfo)
|
processSwitch(cmd, arg, pass, gCmdLineInfo, config)
|
||||||
|
|
||||||
|
|
||||||
var
|
var
|
||||||
|
|
@ -727,19 +738,19 @@ var
|
||||||
# the arguments to be passed to the program that
|
# the arguments to be passed to the program that
|
||||||
# should be run
|
# should be run
|
||||||
|
|
||||||
proc processSwitch*(pass: TCmdLinePass; p: OptParser) =
|
proc processSwitch*(pass: TCmdLinePass; p: OptParser; config: ConfigRef) =
|
||||||
# hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off")
|
# hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off")
|
||||||
# we fix this here
|
# we fix this here
|
||||||
var bracketLe = strutils.find(p.key, '[')
|
var bracketLe = strutils.find(p.key, '[')
|
||||||
if bracketLe >= 0:
|
if bracketLe >= 0:
|
||||||
var key = substr(p.key, 0, bracketLe - 1)
|
var key = substr(p.key, 0, bracketLe - 1)
|
||||||
var val = substr(p.key, bracketLe + 1) & ':' & p.val
|
var val = substr(p.key, bracketLe + 1) & ':' & p.val
|
||||||
processSwitch(key, val, pass, gCmdLineInfo)
|
processSwitch(key, val, pass, gCmdLineInfo, config)
|
||||||
else:
|
else:
|
||||||
processSwitch(p.key, p.val, pass, gCmdLineInfo)
|
processSwitch(p.key, p.val, pass, gCmdLineInfo, config)
|
||||||
|
|
||||||
proc processArgument*(pass: TCmdLinePass; p: OptParser;
|
proc processArgument*(pass: TCmdLinePass; p: OptParser;
|
||||||
argsCount: var int): bool =
|
argsCount: var int; config: ConfigRef): bool =
|
||||||
if argsCount == 0:
|
if argsCount == 0:
|
||||||
# nim filename.nims is the same as "nim e filename.nims":
|
# nim filename.nims is the same as "nim e filename.nims":
|
||||||
if p.key.endswith(".nims"):
|
if p.key.endswith(".nims"):
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
|
||||||
writeCommandLineUsage()
|
writeCommandLineUsage()
|
||||||
else:
|
else:
|
||||||
# Process command line arguments:
|
# Process command line arguments:
|
||||||
processCmdLine(passCmd1, "")
|
processCmdLine(passCmd1, "", config)
|
||||||
if gProjectName == "-":
|
if gProjectName == "-":
|
||||||
gProjectName = "stdinfile"
|
gProjectName = "stdinfile"
|
||||||
gProjectFull = "stdinfile"
|
gProjectFull = "stdinfile"
|
||||||
|
|
@ -71,7 +71,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
|
||||||
# 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
|
||||||
extccomp.initVars()
|
extccomp.initVars()
|
||||||
processCmdLine(passCmd2, "")
|
processCmdLine(passCmd2, "", config)
|
||||||
if options.command == "":
|
if options.command == "":
|
||||||
rawMessage(errNoCommand, command)
|
rawMessage(errNoCommand, command)
|
||||||
mainCommand(newModuleGraph(config), cache)
|
mainCommand(newModuleGraph(config), cache)
|
||||||
|
|
|
||||||
|
|
@ -103,13 +103,23 @@ type
|
||||||
ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideMod,
|
ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideMod,
|
||||||
ideHighlight, ideOutline, ideKnown, ideMsg
|
ideHighlight, ideOutline, ideKnown, ideMsg
|
||||||
|
|
||||||
|
Feature* = enum ## experimental features
|
||||||
|
implicitDeref,
|
||||||
|
dotOperators,
|
||||||
|
callOperator,
|
||||||
|
parallel,
|
||||||
|
destructor
|
||||||
|
|
||||||
ConfigRef* = ref object ## eventually all global configuration should be moved here
|
ConfigRef* = ref object ## eventually all global configuration should be moved here
|
||||||
cppDefines*: HashSet[string]
|
cppDefines*: HashSet[string]
|
||||||
headerFile*: string
|
headerFile*: string
|
||||||
|
features*: set[Feature]
|
||||||
|
|
||||||
|
const oldExperimentalFeatures* = {implicitDeref, dotOperators, callOperator, parallel}
|
||||||
|
|
||||||
proc newConfigRef*(): ConfigRef =
|
proc newConfigRef*(): ConfigRef =
|
||||||
result = ConfigRef(cppDefines: initSet[string](),
|
result = ConfigRef(cppDefines: initSet[string](),
|
||||||
headerFile: "")
|
headerFile: "", features: {})
|
||||||
|
|
||||||
proc cppDefine*(c: ConfigRef; define: string) =
|
proc cppDefine*(c: ConfigRef; define: string) =
|
||||||
c.cppDefines.incl define
|
c.cppDefines.incl define
|
||||||
|
|
@ -146,8 +156,6 @@ var
|
||||||
gListFullPaths*: bool
|
gListFullPaths*: bool
|
||||||
gPreciseStack*: bool = false
|
gPreciseStack*: bool = false
|
||||||
gNoNimblePath* = false
|
gNoNimblePath* = false
|
||||||
gExperimentalMode*: bool
|
|
||||||
newDestructors*: bool
|
|
||||||
gDynlibOverrideAll*: bool
|
gDynlibOverrideAll*: bool
|
||||||
useNimNamespace*: bool
|
useNimNamespace*: bool
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -680,6 +680,22 @@ proc semCustomPragma(c: PContext, n: PNode): PNode =
|
||||||
elif n.kind == nkExprColonExpr:
|
elif n.kind == nkExprColonExpr:
|
||||||
result.kind = n.kind # pragma(arg) -> pragma: arg
|
result.kind = n.kind # pragma(arg) -> pragma: arg
|
||||||
|
|
||||||
|
proc processExperimental(c: PContext; n: PNode; s: PSym) =
|
||||||
|
if not isTopLevel(c):
|
||||||
|
localError(n.info, "'experimental' pragma only valid as toplevel statement")
|
||||||
|
if n.kind notin nkPragmaCallKinds or n.len != 2:
|
||||||
|
c.features.incl oldExperimentalFeatures
|
||||||
|
else:
|
||||||
|
n[1] = c.semConstExpr(c, n[1])
|
||||||
|
case n[1].kind
|
||||||
|
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
||||||
|
try:
|
||||||
|
c.features.incl parseEnum[Feature](n[1].strVal)
|
||||||
|
except ValueError:
|
||||||
|
localError(n[1].info, "unknown experimental feature")
|
||||||
|
else:
|
||||||
|
localError(n.info, errStringLiteralExpected)
|
||||||
|
|
||||||
proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||||
validPragmas: TSpecialWords): bool =
|
validPragmas: TSpecialWords): bool =
|
||||||
var it = n.sons[i]
|
var it = n.sons[i]
|
||||||
|
|
@ -993,11 +1009,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||||
else:
|
else:
|
||||||
it.sons[1] = c.semExpr(c, it.sons[1])
|
it.sons[1] = c.semExpr(c, it.sons[1])
|
||||||
of wExperimental:
|
of wExperimental:
|
||||||
noVal(it)
|
processExperimental(c, it, sym)
|
||||||
if isTopLevel(c):
|
|
||||||
c.module.flags.incl sfExperimental
|
|
||||||
else:
|
|
||||||
localError(it.info, "'experimental' pragma only valid as toplevel statement")
|
|
||||||
of wThis:
|
of wThis:
|
||||||
if it.kind in nkPragmaCallKinds and it.len == 2:
|
if it.kind in nkPragmaCallKinds and it.len == 2:
|
||||||
c.selfName = considerQuotedIdent(it[1])
|
c.selfName = considerQuotedIdent(it[1])
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ proc listDirs(a: VmArgs, filter: set[PathComponent]) =
|
||||||
setResult(a, result)
|
setResult(a, result)
|
||||||
|
|
||||||
proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
|
proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
|
||||||
config: ConfigRef = nil): PEvalContext =
|
config: ConfigRef): PEvalContext =
|
||||||
# For Nimble we need to export 'setupVM'.
|
# For Nimble we need to export 'setupVM'.
|
||||||
result = newCtx(module, cache)
|
result = newCtx(module, cache)
|
||||||
result.mode = emRepl
|
result.mode = emRepl
|
||||||
|
|
@ -128,7 +128,7 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
|
||||||
cbconf getCommand:
|
cbconf getCommand:
|
||||||
setResult(a, options.command)
|
setResult(a, options.command)
|
||||||
cbconf switch:
|
cbconf switch:
|
||||||
processSwitch(a.getString 0, a.getString 1, passPP, module.info)
|
processSwitch(a.getString 0, a.getString 1, passPP, module.info, config)
|
||||||
cbconf hintImpl:
|
cbconf hintImpl:
|
||||||
processSpecificNote(a.getString 0, wHint, passPP, module.info,
|
processSpecificNote(a.getString 0, wHint, passPP, module.info,
|
||||||
a.getString 1)
|
a.getString 1)
|
||||||
|
|
@ -150,7 +150,7 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
|
||||||
options.cppDefine(config, a.getString(0))
|
options.cppDefine(config, a.getString(0))
|
||||||
|
|
||||||
proc runNimScript*(cache: IdentCache; scriptName: string;
|
proc runNimScript*(cache: IdentCache; scriptName: string;
|
||||||
freshDefines=true; config: ConfigRef=nil) =
|
freshDefines=true; config: ConfigRef) =
|
||||||
rawMessage(hintConf, scriptName)
|
rawMessage(hintConf, scriptName)
|
||||||
passes.gIncludeFile = includeModule
|
passes.gIncludeFile = includeModule
|
||||||
passes.gImportModule = importModule
|
passes.gImportModule = importModule
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ proc newOpCall(op: PSym; x: PNode): PNode =
|
||||||
proc destructorCall(c: PContext; op: PSym; x: PNode): PNode =
|
proc destructorCall(c: PContext; op: PSym; x: PNode): PNode =
|
||||||
result = newNodeIT(nkCall, x.info, op.typ.sons[0])
|
result = newNodeIT(nkCall, x.info, op.typ.sons[0])
|
||||||
result.add(newSymNode(op))
|
result.add(newSymNode(op))
|
||||||
if newDestructors:
|
if destructor in c.features:
|
||||||
result.add genAddr(c, x)
|
result.add genAddr(c, x)
|
||||||
else:
|
else:
|
||||||
result.add x
|
result.add x
|
||||||
|
|
@ -319,7 +319,7 @@ proc liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
|
||||||
## In the semantic pass this is called in strategic places
|
## In the semantic pass this is called in strategic places
|
||||||
## to ensure we lift assignment, destructors and moves properly.
|
## to ensure we lift assignment, destructors and moves properly.
|
||||||
## The later 'destroyer' pass depends on it.
|
## The later 'destroyer' pass depends on it.
|
||||||
if not newDestructors or not hasDestructor(typ): return
|
if destructor notin c.features or not hasDestructor(typ): return
|
||||||
when false:
|
when false:
|
||||||
# do not produce wrong liftings while we're still instantiating generics:
|
# do not produce wrong liftings while we're still instantiating generics:
|
||||||
# now disabled; breaks topttree.nim!
|
# now disabled; breaks topttree.nim!
|
||||||
|
|
|
||||||
|
|
@ -434,7 +434,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||||
"Non-matching candidates for " & renderTree(n) & "\n" &
|
"Non-matching candidates for " & renderTree(n) & "\n" &
|
||||||
candidates)
|
candidates)
|
||||||
result = semResolvedCall(c, n, r)
|
result = semResolvedCall(c, n, r)
|
||||||
elif experimentalMode(c) and canDeref(n):
|
elif implicitDeref in c.features and canDeref(n):
|
||||||
# try to deref the first argument and then try overloading resolution again:
|
# try to deref the first argument and then try overloading resolution again:
|
||||||
#
|
#
|
||||||
# XXX: why is this here?
|
# XXX: why is this here?
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,7 @@ type
|
||||||
signatures*: TStrTable
|
signatures*: TStrTable
|
||||||
recursiveDep*: string
|
recursiveDep*: string
|
||||||
suggestionsMade*: bool
|
suggestionsMade*: bool
|
||||||
|
features*: set[Feature]
|
||||||
inTypeContext*: int
|
inTypeContext*: int
|
||||||
typesWithOps*: seq[(PType, PType)] #\
|
typesWithOps*: seq[(PType, PType)] #\
|
||||||
# We need to instantiate the type bound ops lazily after
|
# We need to instantiate the type bound ops lazily after
|
||||||
|
|
@ -225,7 +226,7 @@ proc newContext*(graph: ModuleGraph; module: PSym; cache: IdentCache): PContext
|
||||||
result.graph = graph
|
result.graph = graph
|
||||||
initStrTable(result.signatures)
|
initStrTable(result.signatures)
|
||||||
result.typesWithOps = @[]
|
result.typesWithOps = @[]
|
||||||
|
result.features = graph.config.features
|
||||||
|
|
||||||
proc inclSym(sq: var TSymSeq, s: PSym) =
|
proc inclSym(sq: var TSymSeq, s: PSym) =
|
||||||
var L = len(sq)
|
var L = len(sq)
|
||||||
|
|
@ -398,6 +399,3 @@ proc checkMinSonsLen*(n: PNode, length: int) =
|
||||||
|
|
||||||
proc isTopLevel*(c: PContext): bool {.inline.} =
|
proc isTopLevel*(c: PContext): bool {.inline.} =
|
||||||
result = c.currentScope.depthLevel <= 2
|
result = c.currentScope.depthLevel <= 2
|
||||||
|
|
||||||
proc experimentalMode*(c: PContext): bool {.inline.} =
|
|
||||||
result = gExperimentalMode or sfExperimental in c.module.flags
|
|
||||||
|
|
|
||||||
|
|
@ -663,7 +663,7 @@ proc resolveIndirectCall(c: PContext; n, nOrig: PNode;
|
||||||
matches(c, n, nOrig, result)
|
matches(c, n, nOrig, result)
|
||||||
if result.state != csMatch:
|
if result.state != csMatch:
|
||||||
# try to deref the first argument:
|
# try to deref the first argument:
|
||||||
if experimentalMode(c) and canDeref(n):
|
if implicitDeref in c.features and canDeref(n):
|
||||||
n.sons[1] = n.sons[1].tryDeref
|
n.sons[1] = n.sons[1].tryDeref
|
||||||
initCandidate(c, result, t)
|
initCandidate(c, result, t)
|
||||||
matches(c, n, nOrig, result)
|
matches(c, n, nOrig, result)
|
||||||
|
|
@ -1452,7 +1452,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
|
||||||
typeMismatch(n.info, lhs.typ, rhsTyp)
|
typeMismatch(n.info, lhs.typ, rhsTyp)
|
||||||
|
|
||||||
n.sons[1] = fitNode(c, le, rhs, n.info)
|
n.sons[1] = fitNode(c, le, rhs, n.info)
|
||||||
if not newDestructors:
|
if destructor notin c.features:
|
||||||
if tfHasAsgn in lhs.typ.flags and not lhsIsResult and
|
if tfHasAsgn in lhs.typ.flags and not lhsIsResult and
|
||||||
mode != noOverloadedAsgn:
|
mode != noOverloadedAsgn:
|
||||||
return overloadedAsgn(c, lhs, n.sons[1])
|
return overloadedAsgn(c, lhs, n.sons[1])
|
||||||
|
|
@ -1884,7 +1884,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n)
|
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n)
|
||||||
result.typ = getSysType(tyString)
|
result.typ = getSysType(tyString)
|
||||||
of mParallel:
|
of mParallel:
|
||||||
if not experimentalMode(c):
|
if parallel notin c.features:
|
||||||
localError(n.info, "use the {.experimental.} pragma to enable 'parallel'")
|
localError(n.info, "use the {.experimental.} pragma to enable 'parallel'")
|
||||||
result = setMs(n, s)
|
result = setMs(n, s)
|
||||||
var x = n.lastSon
|
var x = n.lastSon
|
||||||
|
|
|
||||||
|
|
@ -385,30 +385,9 @@ proc checkNilable(v: PSym) =
|
||||||
include semasgn
|
include semasgn
|
||||||
|
|
||||||
proc addToVarSection(c: PContext; result: var PNode; orig, identDefs: PNode) =
|
proc addToVarSection(c: PContext; result: var PNode; orig, identDefs: PNode) =
|
||||||
# consider this:
|
|
||||||
# var
|
|
||||||
# x = 0
|
|
||||||
# withOverloadedAssignment = foo()
|
|
||||||
# y = use(withOverloadedAssignment)
|
|
||||||
# We need to split this into a statement list with multiple 'var' sections
|
|
||||||
# in order for this transformation to be correct.
|
|
||||||
let L = identDefs.len
|
let L = identDefs.len
|
||||||
let value = identDefs[L-1]
|
let value = identDefs[L-1]
|
||||||
if value.typ != nil and tfHasAsgn in value.typ.flags and not newDestructors:
|
if result.kind == nkStmtList:
|
||||||
# the spec says we need to rewrite 'var x = T()' to 'var x: T; x = T()':
|
|
||||||
identDefs.sons[L-1] = emptyNode
|
|
||||||
if result.kind != nkStmtList:
|
|
||||||
let oldResult = result
|
|
||||||
oldResult.add identDefs
|
|
||||||
result = newNodeI(nkStmtList, result.info)
|
|
||||||
result.add oldResult
|
|
||||||
else:
|
|
||||||
let o = copyNode(orig)
|
|
||||||
o.add identDefs
|
|
||||||
result.add o
|
|
||||||
for i in 0 .. L-3:
|
|
||||||
result.add overloadedAsgn(c, identDefs[i], value)
|
|
||||||
elif result.kind == nkStmtList:
|
|
||||||
let o = copyNode(orig)
|
let o = copyNode(orig)
|
||||||
o.add identDefs
|
o.add identDefs
|
||||||
result.add o
|
result.add o
|
||||||
|
|
@ -1267,9 +1246,6 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
gp = newNodeI(nkGenericParams, n.info)
|
gp = newNodeI(nkGenericParams, n.info)
|
||||||
|
|
||||||
if n.sons[paramsPos].kind != nkEmpty:
|
if n.sons[paramsPos].kind != nkEmpty:
|
||||||
#if n.kind == nkDo and not experimentalMode(c):
|
|
||||||
# localError(n.sons[paramsPos].info,
|
|
||||||
# "use the {.experimental.} pragma to enable 'do' with parameters")
|
|
||||||
semParamList(c, n.sons[paramsPos], gp, s)
|
semParamList(c, n.sons[paramsPos], gp, s)
|
||||||
# paramsTypeCheck(c, s.typ)
|
# paramsTypeCheck(c, s.typ)
|
||||||
if sonsLen(gp) > 0 and n.sons[genericParamsPos].kind == nkEmpty:
|
if sonsLen(gp) > 0 and n.sons[genericParamsPos].kind == nkEmpty:
|
||||||
|
|
@ -1363,8 +1339,7 @@ proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
|
||||||
|
|
||||||
proc semOverride(c: PContext, s: PSym, n: PNode) =
|
proc semOverride(c: PContext, s: PSym, n: PNode) =
|
||||||
case s.name.s.normalize
|
case s.name.s.normalize
|
||||||
of "destroy", "=destroy":
|
of "=destroy":
|
||||||
if newDestructors:
|
|
||||||
let t = s.typ
|
let t = s.typ
|
||||||
var noError = false
|
var noError = false
|
||||||
if t.len == 2 and t.sons[0] == nil and t.sons[1].kind == tyVar:
|
if t.len == 2 and t.sons[0] == nil and t.sons[1].kind == tyVar:
|
||||||
|
|
@ -1612,9 +1587,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
s.options = gOptions
|
s.options = gOptions
|
||||||
if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n)
|
if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n)
|
||||||
if s.name.s[0] in {'.', '('}:
|
if s.name.s[0] in {'.', '('}:
|
||||||
if s.name.s in [".", ".()", ".="] and not experimentalMode(c) and not newDestructors:
|
if s.name.s in [".", ".()", ".="] and {destructor, dotOperators} * c.features == {}:
|
||||||
message(n.info, warnDeprecated, "overloaded '.' and '()' operators are now .experimental; " & s.name.s)
|
message(n.info, warnDeprecated, "overloaded '.' and '()' operators are now .experimental; " & s.name.s)
|
||||||
elif s.name.s == "()" and not experimentalMode(c):
|
elif s.name.s == "()" and callOperator notin c.features:
|
||||||
message(n.info, warnDeprecated, "overloaded '()' operators are now .experimental; " & s.name.s)
|
message(n.info, warnDeprecated, "overloaded '()' operators are now .experimental; " & s.name.s)
|
||||||
|
|
||||||
if n.sons[bodyPos].kind != nkEmpty:
|
if n.sons[bodyPos].kind != nkEmpty:
|
||||||
|
|
|
||||||
|
|
@ -368,7 +368,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
||||||
assert newbody.kind in {tyRef, tyPtr}
|
assert newbody.kind in {tyRef, tyPtr}
|
||||||
assert newbody.lastSon.typeInst == nil
|
assert newbody.lastSon.typeInst == nil
|
||||||
newbody.lastSon.typeInst = result
|
newbody.lastSon.typeInst = result
|
||||||
if newDestructors:
|
if destructor in cl.c.features:
|
||||||
cl.c.typesWithOps.add((newbody, result))
|
cl.c.typesWithOps.add((newbody, result))
|
||||||
else:
|
else:
|
||||||
typeBound(cl.c, newbody, result, assignment, cl.info)
|
typeBound(cl.c, newbody, result, assignment, cl.info)
|
||||||
|
|
@ -545,7 +545,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc instAllTypeBoundOp*(c: PContext, info: TLineInfo) =
|
proc instAllTypeBoundOp*(c: PContext, info: TLineInfo) =
|
||||||
if not newDestructors: return
|
if destructor notin c.features: return
|
||||||
var i = 0
|
var i = 0
|
||||||
while i < c.typesWithOps.len:
|
while i < c.typesWithOps.len:
|
||||||
let (newty, oldty) = c.typesWithOps[i]
|
let (newty, oldty) = c.typesWithOps[i]
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ var
|
||||||
# in caas mode, the list of defines and options will be given at start-up?
|
# in caas mode, the list of defines and options will be given at start-up?
|
||||||
# it's enough to check that the previous compilation command is the same?
|
# it's enough to check that the previous compilation command is the same?
|
||||||
|
|
||||||
proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
|
proc processCmdLine*(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
|
||||||
var p = parseopt.initOptParser(cmd)
|
var p = parseopt.initOptParser(cmd)
|
||||||
var argsCount = 0
|
var argsCount = 0
|
||||||
while true:
|
while true:
|
||||||
|
|
@ -36,19 +36,19 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
|
||||||
of cmdLongoption, cmdShortOption:
|
of cmdLongoption, cmdShortOption:
|
||||||
if p.key == " ":
|
if p.key == " ":
|
||||||
p.key = "-"
|
p.key = "-"
|
||||||
if processArgument(pass, p, argsCount): break
|
if processArgument(pass, p, argsCount, config): break
|
||||||
else:
|
else:
|
||||||
processSwitch(pass, p)
|
processSwitch(pass, p, config)
|
||||||
of cmdArgument:
|
of cmdArgument:
|
||||||
if processArgument(pass, p, argsCount): break
|
if processArgument(pass, p, argsCount, config): break
|
||||||
if pass == passCmd2:
|
if pass == passCmd2:
|
||||||
if optRun notin gGlobalOptions and arguments != "" and options.command.normalize != "run":
|
if optRun notin gGlobalOptions and arguments != "" and options.command.normalize != "run":
|
||||||
rawMessage(errArgsNeedRunOption, [])
|
rawMessage(errArgsNeedRunOption, [])
|
||||||
|
|
||||||
proc serve*(cache: IdentCache; action: proc (cache: IdentCache){.nimcall.}) =
|
proc serve*(cache: IdentCache; action: proc (cache: IdentCache){.nimcall.}; config: ConfigRef) =
|
||||||
template execute(cmd) =
|
template execute(cmd) =
|
||||||
curCaasCmd = cmd
|
curCaasCmd = cmd
|
||||||
processCmdLine(passCmd2, cmd)
|
processCmdLine(passCmd2, cmd, config)
|
||||||
action(cache)
|
action(cache)
|
||||||
gErrorCounter = 0
|
gErrorCounter = 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -979,7 +979,7 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode =
|
||||||
#result = liftLambdas(prc, result)
|
#result = liftLambdas(prc, result)
|
||||||
when useEffectSystem: trackProc(prc, result)
|
when useEffectSystem: trackProc(prc, result)
|
||||||
result = liftLocalsIfRequested(prc, result)
|
result = liftLocalsIfRequested(prc, result)
|
||||||
if c.needsDestroyPass and newDestructors:
|
if c.needsDestroyPass: #and newDestructors:
|
||||||
result = injectDestructorCalls(prc, result)
|
result = injectDestructorCalls(prc, result)
|
||||||
incl(result.flags, nfTransf)
|
incl(result.flags, nfTransf)
|
||||||
#if prc.name.s == "testbody":
|
#if prc.name.s == "testbody":
|
||||||
|
|
@ -996,7 +996,7 @@ proc transformStmt*(module: PSym, n: PNode): PNode =
|
||||||
when useEffectSystem: trackTopLevelStmt(module, result)
|
when useEffectSystem: trackTopLevelStmt(module, result)
|
||||||
#if n.info ?? "temp.nim":
|
#if n.info ?? "temp.nim":
|
||||||
# echo renderTree(result, {renderIds})
|
# echo renderTree(result, {renderIds})
|
||||||
if c.needsDestroyPass and newDestructors:
|
if c.needsDestroyPass:
|
||||||
result = injectDestructorCalls(module, result)
|
result = injectDestructorCalls(module, result)
|
||||||
incl(result.flags, nfTransf)
|
incl(result.flags, nfTransf)
|
||||||
|
|
||||||
|
|
@ -1007,6 +1007,6 @@ proc transformExpr*(module: PSym, n: PNode): PNode =
|
||||||
var c = openTransf(module, "")
|
var c = openTransf(module, "")
|
||||||
result = processTransf(c, n, module)
|
result = processTransf(c, n, module)
|
||||||
liftDefer(c, result)
|
liftDefer(c, result)
|
||||||
if c.needsDestroyPass and newDestructors:
|
if c.needsDestroyPass:
|
||||||
result = injectDestructorCalls(module, result)
|
result = injectDestructorCalls(module, result)
|
||||||
incl(result.flags, nfTransf)
|
incl(result.flags, nfTransf)
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ Advanced options:
|
||||||
--noLinking compile Nim and generated files but do not link
|
--noLinking compile Nim and generated files but do not link
|
||||||
--noMain do not generate a main procedure
|
--noMain do not generate a main procedure
|
||||||
--genScript generate a compile script (in the 'nimcache'
|
--genScript generate a compile script (in the 'nimcache'
|
||||||
subdirectory named 'compile_$project$scriptext')
|
subdirectory named 'compile_$$project$$scriptext')
|
||||||
--genDeps generate a '.deps' file containing the dependencies
|
--genDeps generate a '.deps' file containing the dependencies
|
||||||
--os:SYMBOL set the target operating system (cross-compilation)
|
--os:SYMBOL set the target operating system (cross-compilation)
|
||||||
--cpu:SYMBOL set the target processor (cross-compilation)
|
--cpu:SYMBOL set the target processor (cross-compilation)
|
||||||
|
|
@ -88,5 +88,6 @@ Advanced options:
|
||||||
--parallelBuild:0|1|... perform a parallel build
|
--parallelBuild:0|1|... perform a parallel build
|
||||||
value = number of processors (0 for auto-detect)
|
value = number of processors (0 for auto-detect)
|
||||||
--verbosity:0|1|2|3 set Nim's verbosity level (1 is default)
|
--verbosity:0|1|2|3 set Nim's verbosity level (1 is default)
|
||||||
--experimental enable experimental language features
|
--experimental:$1
|
||||||
|
enable experimental language feature
|
||||||
-v, --version show detailed version information
|
-v, --version show detailed version information
|
||||||
|
|
|
||||||
|
|
@ -1397,10 +1397,10 @@ dereferencing operations for reference types:
|
||||||
|
|
||||||
Automatic dereferencing is also performed for the first argument of a routine
|
Automatic dereferencing is also performed for the first argument of a routine
|
||||||
call. But currently this feature has to be only enabled
|
call. But currently this feature has to be only enabled
|
||||||
via ``{.experimental.}``:
|
via ``{.experimental: "implicitDeref".}``:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
{.experimental.}
|
{.experimental: "implicitDeref".}
|
||||||
|
|
||||||
proc depth(x: NodeObj): int = ...
|
proc depth(x: NodeObj): int = ...
|
||||||
|
|
||||||
|
|
@ -5588,7 +5588,7 @@ dot operators
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
**Note**: Dot operators are still experimental and so need to be enabled
|
**Note**: Dot operators are still experimental and so need to be enabled
|
||||||
via ``{.experimental.}``.
|
via ``{.experimental: "dotOperators".}``.
|
||||||
|
|
||||||
Nim offers a special family of dot operators that can be used to
|
Nim offers a special family of dot operators that can be used to
|
||||||
intercept and rewrite proc call and field access attempts, referring
|
intercept and rewrite proc call and field access attempts, referring
|
||||||
|
|
@ -6885,17 +6885,12 @@ is uncertain (it may be removed any time).
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
{.experimental.}
|
{.experimental: "parallel".}
|
||||||
type
|
|
||||||
FooId = distinct int
|
|
||||||
BarId = distinct int
|
|
||||||
using
|
|
||||||
foo: FooId
|
|
||||||
bar: BarId
|
|
||||||
|
|
||||||
proc useUsing(bar, foo) =
|
proc useUsing(bar, foo) =
|
||||||
echo "bar is of type BarId"
|
parallel:
|
||||||
echo "foo is of type FooId"
|
for i in 0..4:
|
||||||
|
echo "echo in parallel"
|
||||||
|
|
||||||
|
|
||||||
Implementation Specific Pragmas
|
Implementation Specific Pragmas
|
||||||
|
|
@ -7917,7 +7912,7 @@ Example:
|
||||||
|
|
||||||
# Compute PI in an inefficient way
|
# Compute PI in an inefficient way
|
||||||
import strutils, math, threadpool
|
import strutils, math, threadpool
|
||||||
{.experimental.}
|
{.experimental: "parallel".}
|
||||||
|
|
||||||
proc term(k: float): float = 4 * math.pow(-1, k) / (2*k + 1)
|
proc term(k: float): float = 4 * math.pow(-1, k) / (2*k + 1)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -518,7 +518,7 @@ proc mainCommand(graph: ModuleGraph; cache: IdentCache) =
|
||||||
close(requests)
|
close(requests)
|
||||||
close(results)
|
close(results)
|
||||||
|
|
||||||
proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
|
proc processCmdLine*(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
|
||||||
var p = parseopt.initOptParser(cmd)
|
var p = parseopt.initOptParser(cmd)
|
||||||
while true:
|
while true:
|
||||||
parseopt.next(p)
|
parseopt.next(p)
|
||||||
|
|
@ -562,7 +562,7 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
|
||||||
gRefresh = true
|
gRefresh = true
|
||||||
of "maxresults":
|
of "maxresults":
|
||||||
suggestMaxResults = parseInt(p.val)
|
suggestMaxResults = parseInt(p.val)
|
||||||
else: processSwitch(pass, p)
|
else: processSwitch(pass, p, config)
|
||||||
of cmdArgument:
|
of cmdArgument:
|
||||||
let a = unixToNativePath(p.key)
|
let a = unixToNativePath(p.key)
|
||||||
if dirExists(a) and not fileExists(a.addFileExt("nim")):
|
if dirExists(a) and not fileExists(a.addFileExt("nim")):
|
||||||
|
|
@ -577,7 +577,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
|
||||||
if paramCount() == 0:
|
if paramCount() == 0:
|
||||||
stdout.writeline(Usage)
|
stdout.writeline(Usage)
|
||||||
else:
|
else:
|
||||||
processCmdLine(passCmd1, "")
|
processCmdLine(passCmd1, "", config)
|
||||||
if gMode != mstdin:
|
if gMode != mstdin:
|
||||||
msgs.writelnHook = proc (msg: string) = discard
|
msgs.writelnHook = proc (msg: string) = discard
|
||||||
if gProjectName != "":
|
if gProjectName != "":
|
||||||
|
|
@ -616,7 +616,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
|
||||||
runNimScript(cache, gProjectPath / "config.nims", freshDefines=false, config)
|
runNimScript(cache, gProjectPath / "config.nims", freshDefines=false, config)
|
||||||
|
|
||||||
extccomp.initVars()
|
extccomp.initVars()
|
||||||
processCmdLine(passCmd2, "")
|
processCmdLine(passCmd2, "", config)
|
||||||
|
|
||||||
let graph = newModuleGraph(config)
|
let graph = newModuleGraph(config)
|
||||||
graph.suggestMode = true
|
graph.suggestMode = true
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ discard """
|
||||||
|
|
||||||
import threadpool, sequtils
|
import threadpool, sequtils
|
||||||
|
|
||||||
{.experimental.}
|
{.experimental: "parallel".}
|
||||||
|
|
||||||
proc linearFind(a: openArray[int]; x, offset: int): int =
|
proc linearFind(a: openArray[int]; x, offset: int): int =
|
||||||
for i, y in a:
|
for i, y in a:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue