From 287c88ca59c5eae2b33874acc6271ca30b7b7e52 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 2 Sep 2013 17:53:58 +0200 Subject: [PATCH] Support adding variables to the scope The command ":a " evaluates and adds the attributes in the resulting attribute set to the interpreter scope. For instance: nix-repl> :a import {} nix-repl> lib.range 0 10 [ 0 1 2 3 4 5 6 7 8 9 10 ] --- nix-repl.cc | 95 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 9 deletions(-) diff --git a/nix-repl.cc b/nix-repl.cc index ea248b5ca..10e91ec53 100644 --- a/nix-repl.cc +++ b/nix-repl.cc @@ -6,6 +6,8 @@ #include "shared.hh" #include "eval.hh" +#include "eval-inline.hh" +#include "store-api.hh" using namespace std; using namespace nix; @@ -14,6 +16,23 @@ using namespace nix; string programId = "nix-repl"; +struct NixRepl +{ + string curDir; + EvalState state; + + StaticEnv staticEnv; + Env * env; + int displ; + + NixRepl(); + void mainLoop(); + void processLine(string line); + void addVar(const Symbol & name, Value * v); + Expr * parseString(string s); +}; + + void printHelp() { std::cout << "Usage: nix-repl\n"; @@ -22,7 +41,7 @@ void printHelp() bool getLine(string & line) { - char * s = readline ("nix-repl> "); + char * s = readline("nix-repl> "); if (!s) return false; line = chomp(string(s)); free(s); @@ -31,21 +50,33 @@ bool getLine(string & line) } -void run(nix::Strings args) +NixRepl::NixRepl() + : staticEnv(false, &state.staticBaseEnv) { - EvalState state; - Path curDir = absPath("."); + curDir = absPath("."); + + env = &state.allocEnv(32768); + env->up = &state.baseEnv; + displ = 0; + + store = openStore(); +} + + +void NixRepl::mainLoop() +{ + std::cerr << "Welcome to Nix version " << NIX_VERSION << ". Type :? for help." << std::endl << std::endl; while (true) { string line; if (!getLine(line)) break; + /* Remove preceeding whitespace. */ + size_t n = line.find_first_not_of(" \n\r\t"); + if (n != string::npos) line = string(line, n); + try { - Expr * e = state.parseExprFromString(line, curDir); - Value v; - state.eval(e, v); - state.strictForceValue(v); - std::cout << v << std::endl; + processLine(line); } catch (Error & e) { printMsg(lvlError, e.msg()); } @@ -55,3 +86,49 @@ void run(nix::Strings args) std::cout << std::endl; } + + +void NixRepl::processLine(string line) +{ + if (string(line, 0, 2) == ":a") { + Expr * e = parseString(string(line, 2)); + Value v; + e->eval(state, *env, v); + state.forceAttrs(v); + foreach (Bindings::iterator, i, *v.attrs) + addVar(i->name, i->value); + } + + else if (string(line, 0, 1) == ":") { + throw Error(format("unknown command ‘%1%’") % string(line, 0, 2)); + } + + else { + Expr * e = parseString(line); + Value v; + e->eval(state, *env, v); + state.strictForceValue(v); + std::cout << v << std::endl; + } +} + + +void NixRepl::addVar(const Symbol & name, Value * v) +{ + staticEnv.vars[name] = displ; + env->values[displ++] = v; +} + + +Expr * NixRepl::parseString(string s) +{ + Expr * e = state.parseExprFromString(s, curDir, staticEnv); + return e; +} + + +void run(nix::Strings args) +{ + NixRepl repl; + repl.mainLoop(); +}