diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2013-09-09T11·56+0200 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2013-09-09T11·56+0200 |
commit | 3c67df928f8d311d7dfd565e8c3a16db9d6a0278 (patch) | |
tree | dc99f30389a34901836c034f733d3c1944c3a9f0 | |
parent | 4b33c2dd4cac95151ca5d99ceb3161fdb460ec0a (diff) |
Add sugar for defining a variable
‘x = <expr>’ is short for ‘:a { x = <expr>; }’. Note that the right-hand side refers to the original scope, so you get: nix-repl> x = 1 nix-repl> x = x + 1 nix-repl> x 2 rather than an infinite recursion.
-rw-r--r-- | nix-repl.cc | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/nix-repl.cc b/nix-repl.cc index 72099f46e622..bcd80ffc7567 100644 --- a/nix-repl.cc +++ b/nix-repl.cc @@ -42,7 +42,7 @@ struct NixRepl void processLine(string line); void loadFile(const Path & path); void addAttrsToScope(Value & attrs); - void addVarToScope(const Symbol & name, Value * v); + void addVarToScope(const Symbol & name, Value & v); Expr * parseString(string s); void evalString(string s, Value & v); @@ -242,6 +242,19 @@ static int runProgram(const string & program, const Strings & args) } +bool isVarName(const string & s) +{ + // FIXME: not quite correct. + foreach (string::const_iterator, i, s) + if (!((*i >= 'a' && *i <= 'z') || + (*i >= 'A' && *i <= 'Z') || + (*i >= '0' && *i <= '9') || + *i == '_' || *i == '\'')) + return false; + return true; +} + + void NixRepl::processLine(string line) { if (line == "") return; @@ -251,13 +264,14 @@ void NixRepl::processLine(string line) if (command == ":?") { cout << "The following commands are available:\n" << "\n" - << " <expr> Evaluate and print expression\n" - << " :a <expr> Add attributes from resulting set to scope\n" - << " :b <expr> Build derivation\n" - << " :l <path> Load Nix expression and add it to scope\n" - << " :p <expr> Evaluate and print expression recursively\n" - << " :s <expr> Build dependencies of derivation, then start nix-shell\n" - << " :t <expr> Describe result of evaluation\n"; + << " <expr> Evaluate and print expression\n" + << " <x> = <expr> Bind expression to variable\n" + << " :a <expr> Add attributes from resulting set to scope\n" + << " :b <expr> Build derivation\n" + << " :l <path> Load Nix expression and add it to scope\n" + << " :p <expr> Evaluate and print expression recursively\n" + << " :s <expr> Build dependencies of derivation, then start nix-shell\n" + << " :t <expr> Describe result of evaluation\n"; } else if (command == ":a") { @@ -310,9 +324,22 @@ void NixRepl::processLine(string line) throw Error(format("unknown command ‘%1%’") % string(line, 0, 2)); else { - Value v; - evalString(line, v); - printValue(std::cout, v, 1) << std::endl; + size_t p = line.find('='); + string name; + if (p != string::npos && + isVarName(name = removeWhitespace(string(line, 0, p)))) + { + Expr * e = parseString(string(line, p + 1)); + Value & v(*state.allocValue()); + v.type = tThunk; + v.thunk.env = env; + v.thunk.expr = e; + addVarToScope(state.symbols.create(name), v); + } else { + Value v; + evalString(line, v); + printValue(std::cout, v, 1) << std::endl; + } } } @@ -331,15 +358,15 @@ void NixRepl::addAttrsToScope(Value & attrs) { state.forceAttrs(attrs); foreach (Bindings::iterator, i, *attrs.attrs) - addVarToScope(i->name, i->value); + addVarToScope(i->name, *i->value); std::cout << format("Added %1% variables.") % attrs.attrs->size() << std::endl; } -void NixRepl::addVarToScope(const Symbol & name, Value * v) +void NixRepl::addVarToScope(const Symbol & name, Value & v) { staticEnv.vars[name] = displ; - env->values[displ++] = v; + env->values[displ++] = &v; varNames.insert((string) name); } |