fix(3p/nix): inherit Expr from gc, make parser state traceable

The parser contained vectors, and the primary parser state, that
were not participating in GC tracing.

Change-Id: Ie198592cd7acffd390e3e2ae9595138b56416838
Reviewed-on: https://cl.tvl.fyi/c/depot/+/1706
Tested-by: BuildkiteCI
Reviewed-by: tazjin <mail@tazj.in>
Reviewed-by: glittershark <grfn@gws.fyi>
This commit is contained in:
Kane York 2020-08-09 22:42:00 -07:00 committed by kanepyork
parent 42bdaacca6
commit 906f5c1d2d
4 changed files with 56 additions and 40 deletions

View file

@ -74,13 +74,18 @@ struct StaticEnv;
/* An attribute path is a sequence of attribute names. */ /* An attribute path is a sequence of attribute names. */
using AttrName = std::variant<Symbol, Expr*>; using AttrName = std::variant<Symbol, Expr*>;
typedef std::vector<AttrName> AttrPath; typedef std::vector<AttrName, traceable_allocator<AttrName>> AttrPath;
using AttrNameVector =
std::vector<nix::AttrName, traceable_allocator<nix::AttrName>>;
using VectorExprs = std::vector<nix::Expr*, traceable_allocator<nix::Expr*>>;
std::string showAttrPath(const AttrPath& attrPath); std::string showAttrPath(const AttrPath& attrPath);
/* Abstract syntax of Nix expressions. */ /* Abstract syntax of Nix expressions. */
struct Expr { struct Expr : public gc {
virtual ~Expr(){}; virtual ~Expr(){};
virtual void show(std::ostream& str) const; virtual void show(std::ostream& str) const;
virtual void bindVars(const StaticEnv& env); virtual void bindVars(const StaticEnv& env);
@ -186,7 +191,7 @@ struct ExprOpHasAttr : Expr {
struct ExprAttrs : Expr { struct ExprAttrs : Expr {
bool recursive; bool recursive;
struct AttrDef { struct AttrDef : public gc {
bool inherited; bool inherited;
Expr* e; Expr* e;
Pos pos; Pos pos;
@ -196,17 +201,22 @@ struct ExprAttrs : Expr {
AttrDef(){}; AttrDef(){};
}; };
typedef absl::flat_hash_map<Symbol, AttrDef> AttrDefs; typedef absl::flat_hash_map<
Symbol, AttrDef, absl::container_internal::hash_default_hash<Symbol>,
absl::container_internal::hash_default_eq<Symbol>,
traceable_allocator<std::pair<const Symbol, AttrDef>>>
AttrDefs;
AttrDefs attrs; AttrDefs attrs;
struct DynamicAttrDef { struct DynamicAttrDef : public gc {
Expr *nameExpr, *valueExpr; Expr *nameExpr, *valueExpr;
Pos pos; Pos pos;
DynamicAttrDef(Expr* nameExpr, Expr* valueExpr, const Pos& pos) DynamicAttrDef(Expr* nameExpr, Expr* valueExpr, const Pos& pos)
: nameExpr(nameExpr), valueExpr(valueExpr), pos(pos){}; : nameExpr(nameExpr), valueExpr(valueExpr), pos(pos){};
}; };
typedef std::vector<DynamicAttrDef> DynamicAttrDefs; typedef std::vector<DynamicAttrDef, traceable_allocator<DynamicAttrDef>>
DynamicAttrDefs;
DynamicAttrDefs dynamicAttrs; DynamicAttrDefs dynamicAttrs;
ExprAttrs() : recursive(false){}; ExprAttrs() : recursive(false){};
@ -214,20 +224,20 @@ struct ExprAttrs : Expr {
}; };
struct ExprList : Expr { struct ExprList : Expr {
std::vector<Expr*> elems; VectorExprs elems;
ExprList(){}; ExprList(){};
COMMON_METHODS COMMON_METHODS
}; };
struct Formal { struct Formal : public gc {
Symbol name; Symbol name;
Expr* def; // def = default, not definition Expr* def; // def = default, not definition
Formal(const Symbol& name, Expr* def) : name(name), def(def){}; Formal(const Symbol& name, Expr* def) : name(name), def(def){};
}; };
// Describes structured function arguments (e.g. `{ a }: ...`) // Describes structured function arguments (e.g. `{ a }: ...`)
struct Formals { struct Formals : public gc {
typedef std::list<Formal> Formals_; typedef std::list<Formal, traceable_allocator<Formal>> Formals_;
Formals_ formals; Formals_ formals;
std::set<Symbol> argNames; // used during parsing std::set<Symbol> argNames; // used during parsing
bool ellipsis; bool ellipsis;
@ -325,8 +335,8 @@ MakeBinOp(ExprOpConcatLists, "++");
struct ExprConcatStrings : Expr { struct ExprConcatStrings : Expr {
Pos pos; Pos pos;
bool forceString; bool forceString;
std::vector<Expr*>* es; nix::VectorExprs* es;
ExprConcatStrings(const Pos& pos, bool forceString, std::vector<Expr*>* es) ExprConcatStrings(const Pos& pos, bool forceString, nix::VectorExprs* es)
: pos(pos), forceString(forceString), es(es){}; : pos(pos), forceString(forceString), es(es){};
COMMON_METHODS COMMON_METHODS
}; };

View file

@ -92,8 +92,7 @@ void addFormal(const Pos& pos, Formals* formals, const Formal& formal) {
formals->argNames.insert(formal.name); formals->argNames.insert(formal.name);
} }
Expr* stripIndentation(const Pos& pos, SymbolTable& symbols, Expr* stripIndentation(const Pos& pos, SymbolTable& symbols, VectorExprs& es) {
std::vector<Expr*>& es) {
if (es.empty()) { if (es.empty()) {
return new ExprString(symbols.Create("")); return new ExprString(symbols.Create(""));
} }
@ -138,11 +137,11 @@ Expr* stripIndentation(const Pos& pos, SymbolTable& symbols,
} }
/* Strip spaces from each line. */ /* Strip spaces from each line. */
std::vector<Expr*>* es2 = new std::vector<Expr*>; VectorExprs* es2 = new VectorExprs;
atStartOfLine = true; atStartOfLine = true;
size_t curDropped = 0; size_t curDropped = 0;
size_t n = es.size(); size_t n = es.size();
for (std::vector<Expr*>::iterator i = es.begin(); i != es.end(); ++i, --n) { for (VectorExprs::iterator i = es.begin(); i != es.end(); ++i, --n) {
ExprIndStr* e = dynamic_cast<ExprIndStr*>(*i); ExprIndStr* e = dynamic_cast<ExprIndStr*>(*i);
if (!e) { if (!e) {
atStartOfLine = false; atStartOfLine = false;

View file

@ -5,6 +5,7 @@
#include <optional> #include <optional>
#include <variant> #include <variant>
#include <gc/gc.h>
#include <glog/logging.h> #include <glog/logging.h>
#include "libexpr/eval.hh" #include "libexpr/eval.hh"
@ -59,8 +60,7 @@ void addAttr(ExprAttrs* attrs, AttrPath& attrPath, Expr* e, const Pos& pos);
void addFormal(const Pos& pos, Formals* formals, const Formal& formal); void addFormal(const Pos& pos, Formals* formals, const Formal& formal);
Expr* stripIndentation(const Pos& pos, SymbolTable& symbols, Expr* stripIndentation(const Pos& pos, SymbolTable& symbols, VectorExprs& es);
std::vector<Expr*>& es);
Path resolveExprPath(Path path); Path resolveExprPath(Path path);

View file

@ -14,6 +14,29 @@
%code requires { %code requires {
#define YY_NO_INPUT 1 // disable unused yyinput features #define YY_NO_INPUT 1 // disable unused yyinput features
#include "libexpr/parser.hh" #include "libexpr/parser.hh"
// Allow GC tracing of YY-allocated structures
#define YYMALLOC GC_MALLOC_UNCOLLECTABLE
#define YYFREE GC_FREE
#define YYREALLOC GC_REALLOC
struct YYSTYPE : public gc {
union {
nix::Expr * e;
nix::ExprList * list;
nix::ExprAttrs * attrs;
nix::Formals * formals;
nix::Formal * formal;
nix::NixInt n;
nix::NixFloat nf;
const char * id; // !!! -> Symbol
char * path;
char * uri;
nix::AttrNameVector * attrNames;
nix::VectorExprs * string_parts;
};
};
} }
%{ %{
@ -40,22 +63,6 @@ void yyerror(YYLTYPE* loc, yyscan_t scanner, ParseData* data,
%} %}
%union {
// !!! We're probably leaking stuff here.
nix::Expr * e;
nix::ExprList * list;
nix::ExprAttrs * attrs;
nix::Formals * formals;
nix::Formal * formal;
nix::NixInt n;
nix::NixFloat nf;
const char * id; // !!! -> Symbol
char * path;
char * uri;
std::vector<nix::AttrName> * attrNames;
std::vector<nix::Expr *> * string_parts;
}
%type <e> start expr expr_function expr_if expr_op %type <e> start expr expr_function expr_if expr_op
%type <e> expr_app expr_select expr_simple %type <e> expr_app expr_select expr_simple
%type <list> expr_list %type <list> expr_list
@ -138,7 +145,7 @@ expr_op
| expr_op UPDATE expr_op { $$ = new ExprOpUpdate(CUR_POS, $1, $3); } | expr_op UPDATE expr_op { $$ = new ExprOpUpdate(CUR_POS, $1, $3); }
| expr_op '?' attrpath { $$ = new ExprOpHasAttr($1, *$3); } | expr_op '?' attrpath { $$ = new ExprOpHasAttr($1, *$3); }
| expr_op '+' expr_op | expr_op '+' expr_op
{ $$ = new ExprConcatStrings(CUR_POS, false, new std::vector<Expr *>({$1, $3})); } { $$ = new ExprConcatStrings(CUR_POS, false, new nix::VectorExprs({$1, $3})); }
| expr_op '-' expr_op { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprVar(data->symbols.Create("__sub")), $1), $3); } | expr_op '-' expr_op { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprVar(data->symbols.Create("__sub")), $1), $3); }
| expr_op '*' expr_op { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprVar(data->symbols.Create("__mul")), $1), $3); } | expr_op '*' expr_op { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprVar(data->symbols.Create("__mul")), $1), $3); }
| expr_op '/' expr_op { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprVar(data->symbols.Create("__div")), $1), $3); } | expr_op '/' expr_op { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprVar(data->symbols.Create("__div")), $1), $3); }
@ -208,9 +215,9 @@ string_parts
string_parts_interpolated string_parts_interpolated
: string_parts_interpolated STR { $$ = $1; $1->push_back($2); } : string_parts_interpolated STR { $$ = $1; $1->push_back($2); }
| string_parts_interpolated DOLLAR_CURLY expr '}' { $$ = $1; $1->push_back($3); } | string_parts_interpolated DOLLAR_CURLY expr '}' { $$ = $1; $1->push_back($3); }
| DOLLAR_CURLY expr '}' { $$ = new std::vector<Expr *>; $$->push_back($2); } | DOLLAR_CURLY expr '}' { $$ = new nix::VectorExprs; $$->push_back($2); }
| STR DOLLAR_CURLY expr '}' { | STR DOLLAR_CURLY expr '}' {
$$ = new std::vector<Expr *>; $$ = new nix::VectorExprs;
$$->push_back($1); $$->push_back($1);
$$->push_back($3); $$->push_back($3);
} }
@ -219,7 +226,7 @@ string_parts_interpolated
ind_string_parts ind_string_parts
: ind_string_parts IND_STR { $$ = $1; $1->push_back($2); } : ind_string_parts IND_STR { $$ = $1; $1->push_back($2); }
| ind_string_parts DOLLAR_CURLY expr '}' { $$ = $1; $1->push_back($3); } | ind_string_parts DOLLAR_CURLY expr '}' { $$ = $1; $1->push_back($3); }
| { $$ = new std::vector<Expr *>; } | { $$ = new nix::VectorExprs; }
; ;
binds binds
@ -276,9 +283,9 @@ attrpath
$$->push_back(AttrName($3)); $$->push_back(AttrName($3));
} }
} }
| attr { $$ = new std::vector<AttrName>; $$->push_back(AttrName(data->symbols.Create($1))); } | attr { $$ = new nix::AttrNameVector; $$->push_back(AttrName(data->symbols.Create($1))); }
| string_attr | string_attr
{ $$ = new std::vector<AttrName>; { $$ = new nix::AttrNameVector;
ExprString *str = dynamic_cast<ExprString *>($1); ExprString *str = dynamic_cast<ExprString *>($1);
if (str) { if (str) {
$$->push_back(AttrName(str->s)); $$->push_back(AttrName(str->s));