From 1dd01e5891804c703019ed26d0ccd922a3bf810b Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 2 May 2013 00:36:06 +0200 Subject: [PATCH] revert new scope for 'if' --- compiler/ccgstmts.nim | 3 +- compiler/options.nim | 3 +- compiler/sem.nim | 2 +- compiler/semexprs.nim | 3 +- doc/manual.txt | 4 +- tests/manyloc/argument_parser/ex_wget.nim | 87 +++++++++++++++++++++++ tests/manyloc/nake/nake.nim | 83 +++++++++++++++++++++ tests/specials.nim | 3 +- 8 files changed, 182 insertions(+), 6 deletions(-) create mode 100644 tests/manyloc/argument_parser/ex_wget.nim create mode 100644 tests/manyloc/nake/nake.nim diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 5fc06edfbe..59cdbbef41 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -232,13 +232,14 @@ proc genIfStmt(p: BProc, n: PNode) = for i in countup(0, sonsLen(n) - 1): var it = n.sons[i] if it.len == 2: - startBlock(p) + when newScopeForIf: startBlock(p) initLocExpr(p, it.sons[0], a) Lelse = getLabel(p) inc(p.labels) lineFF(p, cpsStmts, "if (!$1) goto $2;$n", "br i1 $1, label %LOC$3, label %$2$n" & "LOC$3: $n", [rdLoc(a), Lelse, toRope(p.labels)]) + when not newScopeForIf: startBlock(p) genStmts(p, it.sons[1]) endBlock(p) if sonsLen(n) > 1: diff --git a/compiler/options.nim b/compiler/options.nim index 9d75ba7a6f..ca20d7c835 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -7,13 +7,14 @@ # distribution, for details about the copyright. # -import +import os, lists, strutils, strtabs const hasTinyCBackend* = defined(tinyc) useEffectSystem* = true hasFFI* = defined(useFFI) + newScopeForIf* = false # XXX activate for 0.9.4 type # please make sure we have under 32 options # (improves code efficiency a lot!) diff --git a/compiler/sem.nim b/compiler/sem.nim index 0e4b65d9ff..791ca27930 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -100,7 +100,7 @@ proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = # like newSymS, but considers gensym'ed symbols - if n.kind == nkSym: + if n.kind == nkSym: result = n.sym InternalAssert sfGenSym in result.flags InternalAssert result.kind == kind diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 477cc98b40..e2a3c0978d 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1504,8 +1504,9 @@ proc semIf(c: PContext, n: PNode): PNode = for i in countup(0, sonsLen(n) - 1): var it = n.sons[i] if it.len == 2: - openScope(c.tab) + when newScopeForIf: openScope(c.tab) it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0])) + when not newScopeForIf: openScope(c.tab) it.sons[1] = semExprBranch(c, it.sons[1]) typ = commonType(typ, it.sons[1].typ) closeScope(c.tab) diff --git a/doc/manual.txt b/doc/manual.txt index 2cbf50f2ca..132f6d038d 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -1918,7 +1918,9 @@ the corresponding *then* block: else: # 'm' not declared here -In the example the scopes have been enclosed in ``{| |}``. +In the example the scopes have been enclosed in ``{| |}``. + +**Note**: These scoping rules will be active in 0.9.4. Case statement diff --git a/tests/manyloc/argument_parser/ex_wget.nim b/tests/manyloc/argument_parser/ex_wget.nim new file mode 100644 index 0000000000..d36947b346 --- /dev/null +++ b/tests/manyloc/argument_parser/ex_wget.nim @@ -0,0 +1,87 @@ +import argument_parser, tables, strutils, parseutils + +## Example defining a subset of wget's functionality + +const + PARAM_VERSION = @["-V", "--version"] + PARAM_HELP = @["-h", "--help"] + PARAM_BACKGROUND = @["-b", "--background"] + PARAM_OUTPUT = @["-o", "--output"] + PARAM_NO_CLOBBER = @["-nc", "--no-clobber"] + PARAM_PROGRESS = "--progress" + PARAM_NO_PROXY = "--no-proxy" + + +template P(tnames: varargs[string], thelp: string, ttype = PK_EMPTY, + tcallback: Tparameter_callback = nil) = + ## Helper to avoid repetition of parameter adding boilerplate. + params.add(new_parameter_specification(ttype, custom_validator = tcallback, + help_text = thelp, names = tnames)) + + +template got(param: varargs[string]) = + ## Just dump the detected options on output. + if result.options.hasKey(param[0]): echo("Found option '$1'." % [param[0]]) + + +proc parse_progress(parameter: string; value: var Tparsed_parameter): string = + ## Custom parser and validator of progress types for PARAM_PROGRESS. + ## + ## If the user specifies the PARAM_PROGRESS option this proc will be called + ## so we can validate the input. The proc returns a non empty string if + ## something went wrong with the description of the error, otherwise + ## execution goes ahead. + ## + ## This validator only accepts values without changing the final output. + if value.str_val == "bar" or value.str_val == "dot": + return + + result = "The string $1 is not valid, use bar or dot." % [value.str_val] + + +proc process_commandline(): Tcommandline_results = + ## Parses the commandline. + ## + ## Returns a Tcommandline_results with at least two positional parameter, + ## where the last parameter is implied to be the destination of the copying. + var params: seq[Tparameter_specification] = @[] + + P(PARAM_VERSION, "Shows the version of the program") + P(PARAM_HELP, "Shows this help on the commandline", PK_HELP) + P(PARAM_BACKGROUND, "Continues execution in the background") + P(PARAM_OUTPUT, "Specifies a specific output file name", PK_STRING) + P(PARAM_NO_CLOBBER, "Skip downloads that would overwrite existing files") + P(PARAM_PROGRESS, "Select progress look (bar or dot)", + PK_STRING, parse_progress) + P(PARAM_NO_PROXY, "Don't use proxies even if available") + + result = parse(params) + + if result.positional_parameters.len < 1: + echo "Missing URL(s) to download" + echo_help(params) + quit() + + got(PARAM_NO_CLOBBER) + got(PARAM_BACKGROUND) + got(PARAM_NO_PROXY) + + if result.options.hasKey(PARAM_VERSION[0]): + echo "Version 3.1415" + quit() + + if result.options.hasKey(PARAM_OUTPUT[0]): + if result.positional_parameters.len > 1: + echo "Error: can't use $1 option with multiple URLs" % [PARAM_OUTPUT[0]] + echo_help(params) + quit() + echo "Will download to $1" % [result.options[PARAM_OUTPUT[0]].str_val] + + if result.options.hasKey(PARAM_PROGRESS): + echo "Will use progress type $1" % [result.options[PARAM_PROGRESS].str_val] + + +when isMainModule: + let args = process_commandline() + for param in args.positional_parameters: + echo "Downloading $1" % param.str_val diff --git a/tests/manyloc/nake/nake.nim b/tests/manyloc/nake/nake.nim new file mode 100644 index 0000000000..eade28c70d --- /dev/null +++ b/tests/manyloc/nake/nake.nim @@ -0,0 +1,83 @@ +discard """ +DO AS THOU WILST PUBLIC LICENSE + +Whoever should stumble upon this document is henceforth and forever +entitled to DO AS THOU WILST with aforementioned document and the +contents thereof. + +As said in the Olde Country, `Keepe it Gangster'.""" + +import strutils, parseopt, tables, os + +type + PTask* = ref object + desc*: string + action*: TTaskFunction + TTaskFunction* = proc() {.closure.} +var + tasks* = initTable[string, PTask](16) + +proc newTask*(desc: string; action: TTaskFunction): PTask +proc runTask*(name: string) {.inline.} +proc shell*(cmd: varargs[string, `$`]): int {.discardable.} +proc cd*(dir: string) {.inline.} + +template nakeImports*(): stmt {.immediate.} = + import tables, parseopt, strutils, os + +template task*(name: string; description: string; body: stmt): stmt {.dirty, immediate.} = + block: + var t = newTask(description, proc() {.closure.} = + body) + tasks[name] = t + +proc newTask*(desc: string; action: TTaskFunction): PTask = + new(result) + result.desc = desc + result.action = action +proc runTask*(name: string) = tasks[name].action() + +proc shell*(cmd: varargs[string, `$`]): int = + result = execShellCmd(cmd.join(" ")) +proc cd*(dir: string) = setCurrentDir(dir) +template withDir*(dir: string; body: stmt): stmt = + ## temporary cd + ## withDir "foo": + ## # inside foo + ## #back to last dir + var curDir = getCurrentDir() + cd(dir) + body + cd(curDir) + +when isMainModule: + if not existsFile("nakefile.nim"): + echo "No nakefile.nim found. Current working dir is ", getCurrentDir() + quit 1 + var args = "" + for i in 1..paramCount(): + args.add paramStr(i) + args.add " " + quit(shell("nimrod", "c", "-r", "nakefile.nim", args)) +else: + addQuitProc(proc() {.noconv.} = + var + task: string + printTaskList: bool + for kind, key, val in getOpt(): + case kind + of cmdLongOption, cmdShortOption: + case key.tolower + of "tasks", "t": + printTaskList = true + else: + echo "Unknown option: ", key, ": ", val + of cmdArgument: + task = key + else: nil + if printTaskList or task.isNil or not(tasks.hasKey(task)): + echo "Available tasks:" + for name, task in pairs(tasks): + echo name, " - ", task.desc + quit 0 + tasks[task].action()) diff --git a/tests/specials.nim b/tests/specials.nim index 30bb6f4237..156a289d26 100644 --- a/tests/specials.nim +++ b/tests/specials.nim @@ -216,7 +216,8 @@ proc compileManyLoc(r: var TResults, options: string) = for kind, dir in os.walkDir("tests/manyloc"): if kind == pcDir: let mainfile = findMainFile(dir) - compileSingleTest(r, mainfile, options) + if mainfile != ".nim": + compileSingleTest(r, mainfile, options) proc compileSpecialTests(r: var TResults, options: string) = compileRodFiles(r, options)