[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
314/376: Allow external code using libnixexpr to add types
From: |
Ludovic Courtès |
Subject: |
314/376: Allow external code using libnixexpr to add types |
Date: |
Wed, 28 Jan 2015 22:05:51 +0000 |
civodul pushed a commit to tag 1.8
in repository guix.
commit 320659b0cd161249c95e736c3fb309b1a73ea728
Author: Shea Levy <address@hidden>
Date: Sun Nov 30 13:16:19 2014 -0500
Allow external code using libnixexpr to add types
Code that links to libnixexpr (e.g. plugins loaded with importNative, or
nix-exec) may want to provide custom value types and operations on
values of those types. For example, nix-exec is currently using sets
where a custom IO value type would be more appropriate. This commit
provides a generic hook for such types in the form of tExternal and the
ExternalBase virtual class, which contains all functions necessary for
libnixexpr's type-polymorphic functions (e.g. `showType`) to be
implemented.
---
src/libexpr/eval.cc | 33 +++++++++++++++++++++++++++
src/libexpr/primops.cc | 3 ++
src/libexpr/value-to-json.cc | 11 +++++++++
src/libexpr/value-to-xml.cc | 11 +++++++++
src/libexpr/value.hh | 50 ++++++++++++++++++++++++++++++++++++++++++
5 files changed, 108 insertions(+), 0 deletions(-)
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index ebb2802..b0afccd 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -104,6 +104,9 @@ static void printValue(std::ostream & str, std::set<const
Value *> & active, con
case tPrimOpApp:
str << "<PRIMOP-APP>";
break;
+ case tExternal:
+ str << *v.external;
+ break;
default:
throw Error("invalid value");
}
@@ -136,6 +139,7 @@ string showType(const Value & v)
case tBlackhole: return "a black hole";
case tPrimOp: return "a built-in function";
case tPrimOpApp: return "a partially applied built-in function";
+ case tExternal: return v.external->showType();
}
abort();
}
@@ -1314,6 +1318,9 @@ string EvalState::coerceToString(const Pos & pos, Value &
v, PathSet & context,
return coerceToString(pos, *i->value, context, coerceMore,
copyToStore);
}
+ if (v.type == tExternal)
+ return v.external->coerceToString(pos, context, coerceMore,
copyToStore);
+
if (coerceMore) {
/* Note that `false' is represented as an empty string for
@@ -1434,6 +1441,9 @@ bool EvalState::eqValues(Value & v1, Value & v2)
case tPrimOpApp:
return false;
+ case tExternal:
+ return *v1.external == *v2.external;
+
default:
throwEvalError("cannot compare %1% with %2%", showType(v1),
showType(v2));
}
@@ -1575,6 +1585,11 @@ size_t valueSize(Value & v)
sz += doValue(*v.primOpApp.left);
sz += doValue(*v.primOpApp.right);
break;
+ case tExternal:
+ if (seen.find(v.external) != seen.end()) break;
+ seen.insert(v.external);
+ sz += v.external->valueSize(seen);
+ break;
default:
;
}
@@ -1601,4 +1616,22 @@ size_t valueSize(Value & v)
}
+string ExternalValueBase::coerceToString(const Pos & pos, PathSet & context,
bool copyMore, bool copyToStore)
+{
+ throw TypeError(format("cannot coerce %1% to a string, at %2%") %
+ showType() % pos);
+}
+
+
+bool ExternalValueBase::operator==(const ExternalValueBase & b)
+{
+ return false;
+}
+
+
+std::ostream & operator << (std::ostream & str, ExternalValueBase & v) {
+ return v.print(str);
+}
+
+
}
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index b0596da..e7b7960 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -187,6 +187,9 @@ static void prim_typeOf(EvalState & state, const Pos & pos,
Value * * args, Valu
case tPrimOpApp:
t = "lambda";
break;
+ case tExternal:
+ t = args[0]->external->typeOf();
+ break;
default: abort();
}
mkString(v, state.symbols.create(t));
diff --git a/src/libexpr/value-to-json.cc b/src/libexpr/value-to-json.cc
index d1ec9b5..b9f3e65 100644
--- a/src/libexpr/value-to-json.cc
+++ b/src/libexpr/value-to-json.cc
@@ -80,10 +80,21 @@ void printValueAsJSON(EvalState & state, bool strict,
break;
}
+ case tExternal:
+ v.external->printValueAsJSON(state, strict, str, context);
+ break;
+
default:
throw TypeError(format("cannot convert %1% to JSON") %
showType(v));
}
}
+void ExternalValueBase::printValueAsJSON(EvalState & state, bool strict,
+ std::ostream & str, PathSet & context)
+{
+ throw TypeError(format("cannot convert %1% to JSON") % showType());
+}
+
+
}
diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc
index 3934a83..3cecc33 100644
--- a/src/libexpr/value-to-xml.cc
+++ b/src/libexpr/value-to-xml.cc
@@ -144,12 +144,23 @@ static void printValueAsXML(EvalState & state, bool
strict, bool location,
break;
}
+ case tExternal:
+ v.external->printValueAsXML(state, strict, location, doc, context,
drvsSeen);
+ break;
+
default:
doc.writeEmptyElement("unevaluated");
}
}
+void ExternalValueBase::printValueAsXML(EvalState & state, bool strict,
+ bool location, XMLWriter & doc, PathSet & context, PathSet & drvsSeen)
+{
+ doc.writeEmptyElement("unevaluated");
+}
+
+
void printValueAsXML(EvalState & state, bool strict, bool location,
Value & v, std::ostream & out, PathSet & context)
{
diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh
index 5f18f62..227a81f 100644
--- a/src/libexpr/value.hh
+++ b/src/libexpr/value.hh
@@ -19,6 +19,7 @@ typedef enum {
tBlackhole,
tPrimOp,
tPrimOpApp,
+ tExternal,
} ValueType;
@@ -29,10 +30,58 @@ struct ExprLambda;
struct PrimOp;
struct PrimOp;
class Symbol;
+struct Pos;
+class EvalState;
+class XMLWriter;
typedef long NixInt;
+/* External values must descend from ExternalValueBase, so that
+ * type-agnostic nix functions (e.g. showType) can be implemented
+ */
+class ExternalValueBase
+{
+ friend std::ostream & operator << (std::ostream & str, ExternalValueBase &
v);
+ protected:
+ /* Print out the value */
+ virtual std::ostream & print(std::ostream & str) = 0;
+
+ public:
+ /* Return a simple string describing the type */
+ virtual string showType() = 0;
+
+ /* Return a string to be used in builtins.typeOf */
+ virtual string typeOf() = 0;
+
+ /* How much space does this value take up */
+ virtual size_t valueSize(std::set<const void *> & seen) = 0;
+
+ /* Coerce the value to a string. Defaults to uncoercable, i.e. throws an
+ * error
+ */
+ virtual string coerceToString(const Pos & pos, PathSet & context, bool
copyMore, bool copyToStore);
+
+ /* Compare to another value of the same type. Defaults to uncomparable,
+ * i.e. always false.
+ */
+ virtual bool operator==(const ExternalValueBase & b);
+
+ /* Print the value as JSON. Defaults to unconvertable, i.e. throws an
error */
+ virtual void printValueAsJSON(EvalState & state, bool strict,
+ std::ostream & str, PathSet & context);
+
+ /* Print the value as XML. Defaults to unevaluated */
+ virtual void printValueAsXML(EvalState & state, bool strict, bool location,
+ XMLWriter & doc, PathSet & context, PathSet & drvsSeen);
+
+ virtual ~ExternalValueBase()
+ {
+ };
+};
+
+std::ostream & operator << (std::ostream & str, ExternalValueBase & v);
+
struct Value
{
@@ -88,6 +137,7 @@ struct Value
struct {
Value * left, * right;
} primOpApp;
+ ExternalValueBase * external;
};
};
- 313/376: Intro: Mention binary caches, (continued)
- 313/376: Intro: Mention binary caches, Ludovic Courtès, 2015/01/28
- 303/376: Manual: Bump date, Ludovic Courtès, 2015/01/28
- 315/376: Make all ExternalValueBase functions const, Ludovic Courtès, 2015/01/28
- 318/376: Shut up a warning, Ludovic Courtès, 2015/01/28
- 317/376: Fix another operator precedence issue found by Perl 5.20, Ludovic Courtès, 2015/01/28
- 322/376: Remove Fedora 18, 19 builds, Ludovic Courtès, 2015/01/28
- 319/376: Use posix_spawn to run the pager, Ludovic Courtès, 2015/01/28
- 321/376: Remove some platforms with too-old compilers, Ludovic Courtès, 2015/01/28
- 323/376: Explicitly include required C headers, Ludovic Courtès, 2015/01/28
- 316/376: Merge pull request #401 from shlevy/external-value, Ludovic Courtès, 2015/01/28
- 314/376: Allow external code using libnixexpr to add types,
Ludovic Courtès <=
- 328/376: Provide some fallback defaults for the CA bundle, Ludovic Courtès, 2015/01/28
- 329/376: Add option to disable binary cache certificate checking, Ludovic Courtès, 2015/01/28
- 330/376: Doh, Ludovic Courtès, 2015/01/28
- 327/376: Use https://cache.nixos.org instead of http://cache.nixos.org, Ludovic Courtès, 2015/01/28
- 331/376: Fix bad comment, Ludovic Courtès, 2015/01/28
- 320/376: Define ‘environ’, Ludovic Courtès, 2015/01/28
- 333/376: builtins.readFile: realise context associated with the path, Ludovic Courtès, 2015/01/28
- 332/376: Always use https to fetch the Nixpkgs channel, Ludovic Courtès, 2015/01/28
- 326/376: Link against perl.dll on Cygwin, Ludovic Courtès, 2015/01/28
- 324/376: Set custom compiler flags on Cygwin, Ludovic Courtès, 2015/01/28