about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2013-09-09T11·56+0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2013-09-09T11·56+0200
commit3c67df928f8d311d7dfd565e8c3a16db9d6a0278 (patch)
treedc99f30389a34901836c034f733d3c1944c3a9f0
parent4b33c2dd4cac95151ca5d99ceb3161fdb460ec0a (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.cc55
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);
 }