about summary refs log tree commit diff
path: root/src/libexpr
diff options
context:
space:
mode:
authorShea Levy <shea@shealevy.com>2013-09-13T20·55-0400
committerShea Levy <shea@shealevy.com>2013-12-31T17·45+0000
commit136f2f7046dfed18fde0b5f9933ddfafc1518ef5 (patch)
tree203804716694587a810096af3d75ea3a41c9bbe1 /src/libexpr
parent5ba5993470a6ad532fc8e842084a574a88876b0a (diff)
Add the ExprBuiltin Expr type to the AST
Certain desugaring schemes may require the parser to use some builtin
function to do some of the work (e.g. currently `throw` is used to
lazily cause an error if a `<>`-style path is not in the search path)
Unfortunately, these names are not reserved keywords, so an expression
that uses such a syntactic sugar will not see the expected behavior
(see tests/lang/eval-okay-redefine-builtin.nix for an example).

This adds the ExprBuiltin AST type, which when evaluated uses the value
from the rootmost variable scope (which of course is initialized
internally and can't shadow any of the builtins).

Signed-off-by: Shea Levy <shea@shealevy.com>
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/eval.cc11
-rw-r--r--src/libexpr/nixexpr.cc9
-rw-r--r--src/libexpr/nixexpr.hh7
-rw-r--r--src/libexpr/parser.y18
4 files changed, 36 insertions, 9 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 3db4bb66f435..538325601b9e 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -908,6 +908,17 @@ void ExprOpNot::eval(EvalState & state, Env & env, Value & v)
 }
 
 
+void ExprBuiltin::eval(EvalState & state, Env & env, Value & v)
+{
+    // Not a hot path at all, but would be nice to access state.baseEnv directly
+    Env *baseEnv = &env;
+    while (baseEnv->up) baseEnv = baseEnv->up;
+    Bindings::iterator binding = baseEnv->values[0]->attrs->find(name);
+    assert(binding != baseEnv->values[0]->attrs->end());
+    v = *binding->value;
+}
+
+
 void ExprOpEq::eval(EvalState & state, Env & env, Value & v)
 {
     Value v1; e1->eval(state, env, v1);
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index f4b4295e290c..c7ac967968d7 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -121,6 +121,11 @@ void ExprOpNot::show(std::ostream & str)
     str << "! " << *e;
 }
 
+void ExprBuiltin::show(std::ostream & str)
+{
+    str << "builtins." << name;
+}
+
 void ExprConcatStrings::show(std::ostream & str)
 {
     bool first = true;
@@ -314,6 +319,10 @@ void ExprOpNot::bindVars(const StaticEnv & env)
     e->bindVars(env);
 }
 
+void ExprBuiltin::bindVars(const StaticEnv & env)
+{
+}
+
 void ExprConcatStrings::bindVars(const StaticEnv & env)
 {
     foreach (vector<Expr *>::iterator, i, *es)
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index 61eb81fab138..2ae2e2e96fcf 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -248,6 +248,13 @@ struct ExprOpNot : Expr
     COMMON_METHODS
 };
 
+struct ExprBuiltin : Expr
+{
+    Symbol name;
+    ExprBuiltin(Symbol name) : name(name) { };
+    COMMON_METHODS
+};
+
 #define MakeBinOp(name, s) \
     struct Expr##name : Expr \
     { \
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 7699cf502b79..d30882ac84ab 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -311,13 +311,13 @@ expr_if
 
 expr_op
   : '!' expr_op %prec NOT { $$ = new ExprOpNot($2); }
-| '-' expr_op %prec NEGATE { $$ = new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__sub")), new ExprInt(0)), $2); }
+| '-' expr_op %prec NEGATE { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("sub")), new ExprInt(0)), $2); }
   | expr_op EQ expr_op { $$ = new ExprOpEq($1, $3); }
   | expr_op NEQ expr_op { $$ = new ExprOpNEq($1, $3); }
-  | expr_op '<' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__lessThan")), $1), $3); }
-  | expr_op LEQ expr_op { $$ = new ExprOpNot(new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__lessThan")), $3), $1)); }
-  | expr_op '>' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__lessThan")), $3), $1); }
-  | expr_op GEQ expr_op { $$ = new ExprOpNot(new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__lessThan")), $1), $3)); }
+  | expr_op '<' expr_op { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $1), $3); }
+  | expr_op LEQ expr_op { $$ = new ExprOpNot(new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $3), $1)); }
+  | expr_op '>' expr_op { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $3), $1); }
+  | expr_op GEQ expr_op { $$ = new ExprOpNot(new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $1), $3)); }
   | expr_op AND expr_op { $$ = new ExprOpAnd($1, $3); }
   | expr_op OR expr_op { $$ = new ExprOpOr($1, $3); }
   | expr_op IMPL expr_op { $$ = new ExprOpImpl($1, $3); }
@@ -329,9 +329,9 @@ expr_op
       l->push_back($3);
       $$ = new ExprConcatStrings(false, l);
     }
-  | expr_op '-' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__sub")), $1), $3); }
-  | expr_op '*' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__mul")), $1), $3); }
-  | expr_op '/' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__div")), $1), $3); }
+  | expr_op '-' expr_op { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("sub")), $1), $3); }
+  | expr_op '*' expr_op { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("mul")), $1), $3); }
+  | expr_op '/' expr_op { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("div")), $1), $3); }
   | expr_op CONCAT expr_op { $$ = new ExprOpConcatLists($1, $3); }
   | expr_app
   ;
@@ -381,7 +381,7 @@ expr_simple
          ‘throw’. */
       $$ = path2 == ""
           ? (Expr * ) new ExprApp(
-              new ExprVar(noPos, data->symbols.create("throw")),
+              new ExprBuiltin(data->symbols.create("throw")),
               new ExprString(data->symbols.create(
                       (format("file `%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)") % path).str())))
           : (Expr * ) new ExprPath(path2);