Skip to content

Commit

Permalink
encapsulation of Document
Browse files Browse the repository at this point in the history
  • Loading branch information
jm8 committed Jan 22, 2024
1 parent 66d494e commit f1aebac
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 112 deletions.
82 changes: 34 additions & 48 deletions src/parser/bindvars.cpp → src/document/bindvars.cpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
#include "na_config.h"
#include "bindvars.h"
#include <nix/nixexpr.hh>
#include <unordered_map>
#include "nixexpr.hh"
#include "document/document.h"

// Copy+paste of Expr::bindVars modified to not throw exception
// Sets exprData staticEnv and parent

void bindVars(
nix::EvalState& state,
Document& document,
void Document::bindVars(
std::shared_ptr<nix::StaticEnv> env,
nix::Expr* expr,
std::optional<nix::Expr*> parent
) {
document.exprData[expr].staticEnv = env;
document.exprData[expr].parent = parent;
exprData[expr].staticEnv = env;
exprData[expr].parent = parent;

if (auto e = dynamic_cast<nix::ExprVar*>(expr)) {
/* Check whether the variable appears in the environment. If so,
Expand Down Expand Up @@ -42,10 +40,10 @@ void bindVars(
enclosing `with'. If there is no `with', then we can issue an
"undefined variable" error now. */
if (withLevel == -1) {
document.parseErrors.push_back(
parseErrors.push_back(
{hintfmt("undefined variable '%1%'", state.symbols[e->name])
.str(),
document.tokenRangeToRange(document.exprData[e].range)}
tokenRangeToRange(exprData[e].range)}
);
}
for (nix::StaticEnv const* currEnv = env.get(); currEnv && !e->fromWith;
Expand All @@ -55,19 +53,19 @@ void bindVars(
}

if (auto e = dynamic_cast<nix::ExprSelect*>(expr)) {
bindVars(state, document, env, e->e, expr);
bindVars(env, e->e, expr);
if (e->def)
bindVars(state, document, env, e->def, expr);
bindVars(env, e->def, expr);
for (auto& i : e->attrPath)
if (!i.symbol)
bindVars(state, document, env, i.expr, expr);
bindVars(env, i.expr, expr);
}

if (auto e = dynamic_cast<nix::ExprOpHasAttr*>(expr)) {
bindVars(state, document, env, e->e, expr);
bindVars(env, e->e, expr);
for (auto& i : e->attrPath)
if (!i.symbol)
bindVars(state, document, env, i.expr, expr);
bindVars(env, i.expr, expr);
}

if (auto e = dynamic_cast<nix::ExprAttrs*>(expr)) {
Expand All @@ -83,32 +81,26 @@ void bindVars(
// No need to sort newEnv since attrs is in sorted order.

for (auto& i : e->attrs)
bindVars(
state,
document,
i.second.inherited ? env : newEnv,
i.second.e,
expr
);
bindVars(i.second.inherited ? env : newEnv, i.second.e, expr);

for (auto& i : e->dynamicAttrs) {
bindVars(state, document, newEnv, i.nameExpr, expr);
bindVars(state, document, newEnv, i.valueExpr, expr);
bindVars(newEnv, i.nameExpr, expr);
bindVars(newEnv, i.valueExpr, expr);
}
} else {
for (auto& i : e->attrs)
bindVars(state, document, env, i.second.e, expr);
bindVars(env, i.second.e, expr);

for (auto& i : e->dynamicAttrs) {
bindVars(state, document, env, i.nameExpr, expr);
bindVars(state, document, env, i.valueExpr, expr);
bindVars(env, i.nameExpr, expr);
bindVars(env, i.valueExpr, expr);
}
}
}

if (auto e = dynamic_cast<nix::ExprList*>(expr)) {
for (auto& i : e->elems)
bindVars(state, document, env, i, expr);
bindVars(env, i, expr);
}

if (auto e = dynamic_cast<nix::ExprLambda*>(expr)) {
Expand All @@ -132,16 +124,16 @@ void bindVars(

for (auto& i : e->formals->formals)
if (i.def)
bindVars(state, document, newEnv, i.def, expr);
bindVars(newEnv, i.def, expr);
}

bindVars(state, document, newEnv, e->body, expr);
bindVars(newEnv, e->body, expr);
}

if (auto e = dynamic_cast<nix::ExprCall*>(expr)) {
bindVars(state, document, env, e->fun, expr);
bindVars(env, e->fun, expr);
for (auto item : e->args)
bindVars(state, document, env, item, expr);
bindVars(env, item, expr);
}

if (auto e = dynamic_cast<nix::ExprLet*>(expr)) {
Expand All @@ -156,15 +148,9 @@ void bindVars(
// No need to sort newEnv since attrs->attrs is in sorted order.

for (auto& i : e->attrs->attrs)
bindVars(
state,
document,
i.second.inherited ? env : newEnv,
i.second.e,
expr
);
bindVars(i.second.inherited ? env : newEnv, i.second.e, expr);

bindVars(state, document, newEnv, e->body, expr);
bindVars(newEnv, e->body, expr);
}

if (auto e = dynamic_cast<nix::ExprWith*>(expr)) {
Expand All @@ -181,29 +167,29 @@ void bindVars(
break;
}

bindVars(state, document, env, e->attrs, expr);
bindVars(env, e->attrs, expr);
auto newEnv = std::make_shared<nix::StaticEnv>(e, env.get());
bindVars(state, document, newEnv, e->body, expr);
bindVars(newEnv, e->body, expr);
}

if (auto e = dynamic_cast<nix::ExprIf*>(expr)) {
bindVars(state, document, env, e->cond, expr);
bindVars(state, document, env, e->then, expr);
bindVars(state, document, env, e->else_, expr);
bindVars(env, e->cond, expr);
bindVars(env, e->then, expr);
bindVars(env, e->else_, expr);
}

if (auto e = dynamic_cast<nix::ExprAssert*>(expr)) {
bindVars(state, document, env, e->cond, expr);
bindVars(state, document, env, e->body, expr);
bindVars(env, e->cond, expr);
bindVars(env, e->body, expr);
}

if (auto e = dynamic_cast<nix::ExprOpNot*>(expr)) {
bindVars(state, document, env, e->e, expr);
bindVars(env, e->e, expr);
}

if (auto e = dynamic_cast<nix::ExprConcatStrings*>(expr)) {
for (auto& i : *e->es)
bindVars(state, document, env, i.second, expr);
bindVars(env, i.second, expr);
}

if (auto e = dynamic_cast<nix::ExprPos*>(expr)) {
Expand Down
12 changes: 5 additions & 7 deletions src/eval/calculateenv.cpp → src/document/calculateenv.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
#include "eval/calculateenv.h"
#include "na_config.h"
#include <nix/eval.hh>
#include <iostream>
#include "common/logging.h"
#include "common/stringify.h"
#include "document/document.h"

nix::Env* updateEnv(
Document& document,
nix::Env* Document::updateEnv(
nix::Expr* parent,
nix::Expr* child,
nix::Env* up
) {
auto& state = document.state;
if (auto let = dynamic_cast<nix::ExprLet*>(parent)) {
nix::Env* env2 = &state.allocEnv(let->attrs->attrs.size());
env2->up = up;
Expand All @@ -24,7 +22,7 @@ nix::Env* updateEnv(

for (auto& [symbol, attrDef] : let->attrs->attrs) {
env2->values[displ] =
document.thunk(attrDef.e, attrDef.inherited ? up : env2);
thunk(attrDef.e, attrDef.inherited ? up : env2);
displ++;
if (attrDef.e == child && attrDef.inherited)
useSuperEnv = true;
Expand Down Expand Up @@ -75,7 +73,7 @@ nix::Env* updateEnv(
if (!j) {
nix::Value* val;
if (i.def) {
val = document.thunk(i.def, env2);
val = thunk(i.def, env2);
} else {
val = state.allocValue();
val->mkNull();
Expand Down Expand Up @@ -105,7 +103,7 @@ nix::Env* updateEnv(
nix::Displacement displ = 0;
for (auto& i : exprAttrs->attrs) {
nix::Value* vAttr;
vAttr = document.thunk(i.second.e, i.second.inherited ? up : env2);
vAttr = thunk(i.second.e, i.second.inherited ? up : env2);
env2->values[displ] = vAttr;
displ++;
}
Expand Down
38 changes: 36 additions & 2 deletions src/document/document.cpp
Original file line number Diff line number Diff line change
@@ -1,26 +1,60 @@
#include "document/document.h"
#include "eval/calculateenv.h"
#include <nix/eval.hh>
#include <iostream>
#include "input-accessor.hh"
#include "nixexpr.hh"
#include "parser/parser.h"

Document::Document(
nix::EvalState& state,
nix::SourcePath path,
std::string source
)
: state(state), path(path), source(source) {}

void Document::_parse() {
if (root.has_value())
return;
auto result = parse(state, path, source);
tokens = result.tokens;
root = result.root;
parseErrors = result.parseErrors;
for (auto& it : result.exprData) {
exprData[it.first] = {it.second.range};
}
bindVars(state.staticBaseEnv, *root);
}

nix::Expr* Document::getRoot() {
_parse();
return *root;
}

Range Document::tokenRangeToRange(TokenRange tokenRange) {
return {
tokens[tokenRange.start].range.start, tokens[tokenRange.end].range.end};
}

std::shared_ptr<nix::StaticEnv> Document::getStaticEnv(nix::Expr* e) {
_parse();
return exprData[e].staticEnv;
}

std::optional<nix::Expr*> Document::getParent(nix::Expr* e) {
_parse();
return exprData[e].parent;
}

nix::Env* Document::getEnv(nix::Expr* e) {
_parse();
const auto& data = exprData[e];
if (data.env) {
return *data.env;
}
if (!data.parent) {
return &state.baseEnv;
}
return updateEnv(*this, *data.parent, e, getEnv(*data.parent));
return updateEnv(*data.parent, e, getEnv(*data.parent));
}

nix::Value* Document::thunk(nix::Expr* e, nix::Env* env) {
Expand Down
25 changes: 23 additions & 2 deletions src/document/document.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include "na_config.h"
#include <nix/input-accessor.hh>
#include <nix/nixexpr.hh>
#include <iostream>
Expand All @@ -25,18 +26,38 @@ struct ExprData {
std::optional<nix::Value*> v;
};

// Represents an immutable document at a particular time
// Represents an nix source file at a particular time with particular import
struct Document {
private:
nix::EvalState& state;
nix::SourcePath path;
std::string source;

std::vector<Token> tokens;
std::vector<Diagnostic> parseErrors;
std::unordered_map<nix::Expr*, ExprData> exprData;
nix::Expr* root;
std::optional<nix::Expr*> root;

private:
// initialize tokens, parseErrors, exprData, root
void _parse();

public:
Document(nix::EvalState& state, nix::SourcePath path, std::string source);

Range tokenRangeToRange(TokenRange tokenRange);

nix::Expr* getRoot();
std::shared_ptr<nix::StaticEnv> getStaticEnv(nix::Expr* e);
nix::Env* getEnv(nix::Expr* e);
std::optional<nix::Expr*> getParent(nix::Expr* e);
nix::Value* thunk(nix::Expr* e, nix::Env* env);

private:
nix::Env* updateEnv(nix::Expr* parent, nix::Expr* child, nix::Env* up);
void bindVars(
std::shared_ptr<nix::StaticEnv> staticEnv,
nix::Expr* e,
std::optional<nix::Expr*> parent = {}
);
};
14 changes: 0 additions & 14 deletions src/eval/calculateenv.h

This file was deleted.

14 changes: 0 additions & 14 deletions src/parser/bindvars.h

This file was deleted.

Loading

0 comments on commit f1aebac

Please sign in to comment.