various: format with clang-format
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ib9abc9d2dcd036d3680c5aa3dc919bfa6a6a6964
This commit is contained in:
parent
63a9eddc49
commit
98fd1bfc52
12 changed files with 1923 additions and 1819 deletions
|
|
@ -9,7 +9,7 @@ namespace nix {
|
||||||
class EvalState;
|
class EvalState;
|
||||||
class Value;
|
class Value;
|
||||||
class PosIdx;
|
class PosIdx;
|
||||||
}
|
} // namespace nix
|
||||||
|
|
||||||
namespace nix_irc {
|
namespace nix_irc {
|
||||||
|
|
||||||
|
|
@ -21,8 +21,7 @@ public:
|
||||||
explicit Evaluator(nix::EvalState& state);
|
explicit Evaluator(nix::EvalState& state);
|
||||||
~Evaluator();
|
~Evaluator();
|
||||||
|
|
||||||
void eval_to_nix(const std::shared_ptr<Node>& ir_node,
|
void eval_to_nix(const std::shared_ptr<Node>& ir_node, nix::Value& result,
|
||||||
nix::Value& result,
|
|
||||||
IREnvironment* env = nullptr);
|
IREnvironment* env = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -30,6 +29,6 @@ private:
|
||||||
std::unique_ptr<Impl> pImpl;
|
std::unique_ptr<Impl> pImpl;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace nix_irc
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "ir_gen.h"
|
#include "ir_gen.h"
|
||||||
|
#include <algorithm>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace nix_irc {
|
namespace nix_irc {
|
||||||
|
|
||||||
|
|
@ -31,7 +31,8 @@ void NameResolver::exit_scope() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NameResolver::bind(const std::string& name) {
|
void NameResolver::bind(const std::string& name) {
|
||||||
if (pImpl->scopes.empty()) return;
|
if (pImpl->scopes.empty())
|
||||||
|
return;
|
||||||
uint32_t idx = pImpl->scope_names.back().size();
|
uint32_t idx = pImpl->scope_names.back().size();
|
||||||
pImpl->scopes.back()[name] = idx;
|
pImpl->scopes.back()[name] = idx;
|
||||||
pImpl->scope_names.back().push_back(name);
|
pImpl->scope_names.back().push_back(name);
|
||||||
|
|
@ -51,7 +52,8 @@ uint32_t NameResolver::resolve(const std::string& name) {
|
||||||
|
|
||||||
bool NameResolver::is_bound(const std::string& name) const {
|
bool NameResolver::is_bound(const std::string& name) const {
|
||||||
for (auto it = pImpl->scopes.rbegin(); it != pImpl->scopes.rend(); ++it) {
|
for (auto it = pImpl->scopes.rbegin(); it != pImpl->scopes.rend(); ++it) {
|
||||||
if (it->count(name)) return true;
|
if (it->count(name))
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +76,8 @@ struct IRGenerator::Impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Node> convert(const std::shared_ptr<Node>& node_ptr) {
|
std::shared_ptr<Node> convert(const std::shared_ptr<Node>& node_ptr) {
|
||||||
if (!node_ptr) return std::make_shared<Node>(ConstNullNode{});
|
if (!node_ptr)
|
||||||
|
return std::make_shared<Node>(ConstNullNode{});
|
||||||
|
|
||||||
const Node& node = *node_ptr;
|
const Node& node = *node_ptr;
|
||||||
|
|
||||||
|
|
@ -216,4 +219,4 @@ std::shared_ptr<Node> IRGenerator::generate(const std::shared_ptr<Node>& ast) {
|
||||||
return pImpl->convert(ast);
|
return pImpl->convert(ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace nix_irc
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@
|
||||||
#define NIX_IRC_IR_GEN_H
|
#define NIX_IRC_IR_GEN_H
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace nix_irc {
|
namespace nix_irc {
|
||||||
|
|
||||||
|
|
@ -40,6 +40,6 @@ private:
|
||||||
std::unique_ptr<Impl> pImpl;
|
std::unique_ptr<Impl> pImpl;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace nix_irc
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
#include <iostream>
|
#include "ir_gen.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "resolver.h"
|
#include "resolver.h"
|
||||||
#include "ir_gen.h"
|
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
namespace nix_irc {
|
namespace nix_irc {
|
||||||
|
|
||||||
|
|
@ -127,7 +127,7 @@ int run_decompile(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace nix_irc
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,20 @@
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include <iostream>
|
#include <array>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
|
||||||
#include <sstream>
|
|
||||||
#include <vector>
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <array>
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace nix_irc {
|
namespace nix_irc {
|
||||||
|
|
||||||
static std::string trim(const std::string& s) {
|
static std::string trim(const std::string& s) {
|
||||||
size_t start = s.find_first_not_of(" \t\n\r");
|
size_t start = s.find_first_not_of(" \t\n\r");
|
||||||
if (start == std::string::npos) return "";
|
if (start == std::string::npos)
|
||||||
|
return "";
|
||||||
size_t end = s.find_last_not_of(" \t\n\r");
|
size_t end = s.find_last_not_of(" \t\n\r");
|
||||||
return s.substr(start, end - start + 1);
|
return s.substr(start, end - start + 1);
|
||||||
}
|
}
|
||||||
|
|
@ -41,7 +42,8 @@ static std::pair<std::string, std::string> run_command(const std::string& cmd) {
|
||||||
std::string error;
|
std::string error;
|
||||||
|
|
||||||
FILE* pipe = popen(cmd.c_str(), "r");
|
FILE* pipe = popen(cmd.c_str(), "r");
|
||||||
if (!pipe) throw std::runtime_error("popen failed");
|
if (!pipe)
|
||||||
|
throw std::runtime_error("popen failed");
|
||||||
|
|
||||||
while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) {
|
while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) {
|
||||||
result += buffer.data();
|
result += buffer.data();
|
||||||
|
|
@ -56,14 +58,51 @@ static std::pair<std::string, std::string> run_command(const std::string& cmd) {
|
||||||
|
|
||||||
struct Token {
|
struct Token {
|
||||||
enum Type {
|
enum Type {
|
||||||
LPAREN, RPAREN, LBRACE, RBRACE, LBRACKET, RBRACKET,
|
LPAREN,
|
||||||
IDENT, STRING, STRING_INTERP, PATH, INT, BOOL,
|
RPAREN,
|
||||||
LET, IN, REC, IF, THEN, ELSE, ASSERT, WITH, INHERIT,
|
LBRACE,
|
||||||
DOT, SEMICOLON, COLON, EQUALS, AT, COMMA, QUESTION, ELLIPSIS,
|
RBRACE,
|
||||||
|
LBRACKET,
|
||||||
|
RBRACKET,
|
||||||
|
IDENT,
|
||||||
|
STRING,
|
||||||
|
STRING_INTERP,
|
||||||
|
PATH,
|
||||||
|
INT,
|
||||||
|
BOOL,
|
||||||
|
LET,
|
||||||
|
IN,
|
||||||
|
REC,
|
||||||
|
IF,
|
||||||
|
THEN,
|
||||||
|
ELSE,
|
||||||
|
ASSERT,
|
||||||
|
WITH,
|
||||||
|
INHERIT,
|
||||||
|
DOT,
|
||||||
|
SEMICOLON,
|
||||||
|
COLON,
|
||||||
|
EQUALS,
|
||||||
|
AT,
|
||||||
|
COMMA,
|
||||||
|
QUESTION,
|
||||||
|
ELLIPSIS,
|
||||||
// Operators
|
// Operators
|
||||||
PLUS, MINUS, STAR, SLASH, CONCAT,
|
PLUS,
|
||||||
EQEQ, NE, LT, GT, LE, GE,
|
MINUS,
|
||||||
AND, OR, IMPL, NOT,
|
STAR,
|
||||||
|
SLASH,
|
||||||
|
CONCAT,
|
||||||
|
EQEQ,
|
||||||
|
NE,
|
||||||
|
LT,
|
||||||
|
GT,
|
||||||
|
LE,
|
||||||
|
GE,
|
||||||
|
AND,
|
||||||
|
OR,
|
||||||
|
IMPL,
|
||||||
|
NOT,
|
||||||
EOF_
|
EOF_
|
||||||
} type;
|
} type;
|
||||||
std::string value;
|
std::string value;
|
||||||
|
|
@ -76,94 +115,119 @@ public:
|
||||||
Lexer(const std::string& input) : input(input), pos(0), line(1), col(1) {}
|
Lexer(const std::string& input) : input(input), pos(0), line(1), col(1) {}
|
||||||
|
|
||||||
std::vector<Token> tokenize() {
|
std::vector<Token> tokenize() {
|
||||||
#define TOKEN(t) Token{Token::t, "", line, col}
|
#define TOKEN(t) \
|
||||||
|
Token { Token::t, "", line, col }
|
||||||
|
|
||||||
while (pos < input.size()) {
|
while (pos < input.size()) {
|
||||||
skip_whitespace();
|
skip_whitespace();
|
||||||
if (pos >= input.size()) break;
|
if (pos >= input.size())
|
||||||
|
break;
|
||||||
|
|
||||||
char c = input[pos];
|
char c = input[pos];
|
||||||
|
|
||||||
if (c == '(') { emit(TOKEN(LPAREN)); }
|
if (c == '(') {
|
||||||
else if (c == ')') { emit(TOKEN(RPAREN)); }
|
emit(TOKEN(LPAREN));
|
||||||
else if (c == '{') { emit(TOKEN(LBRACE)); }
|
} else if (c == ')') {
|
||||||
else if (c == '}') { emit(TOKEN(RBRACE)); }
|
emit(TOKEN(RPAREN));
|
||||||
else if (c == '[') { emit(TOKEN(LBRACKET)); }
|
} else if (c == '{') {
|
||||||
else if (c == ']') { emit(TOKEN(RBRACKET)); }
|
emit(TOKEN(LBRACE));
|
||||||
else if (c == ';') { emit(TOKEN(SEMICOLON)); }
|
} else if (c == '}') {
|
||||||
else if (c == ':') { emit(TOKEN(COLON)); }
|
emit(TOKEN(RBRACE));
|
||||||
else if (c == '@') { emit(TOKEN(AT)); }
|
} else if (c == '[') {
|
||||||
else if (c == ',') { emit(TOKEN(COMMA)); }
|
emit(TOKEN(LBRACKET));
|
||||||
else if (c == '"') { tokenize_string(); }
|
} else if (c == ']') {
|
||||||
|
emit(TOKEN(RBRACKET));
|
||||||
|
} else if (c == ';') {
|
||||||
|
emit(TOKEN(SEMICOLON));
|
||||||
|
} else if (c == ':') {
|
||||||
|
emit(TOKEN(COLON));
|
||||||
|
} else if (c == '@') {
|
||||||
|
emit(TOKEN(AT));
|
||||||
|
} else if (c == ',') {
|
||||||
|
emit(TOKEN(COMMA));
|
||||||
|
} else if (c == '"') {
|
||||||
|
tokenize_string();
|
||||||
|
}
|
||||||
// Two-char operators
|
// Two-char operators
|
||||||
else if (c == '=' && pos + 1 < input.size() && input[pos + 1] == '=') {
|
else if (c == '=' && pos + 1 < input.size() && input[pos + 1] == '=') {
|
||||||
tokens.push_back(TOKEN(EQEQ));
|
tokens.push_back(TOKEN(EQEQ));
|
||||||
pos += 2; col += 2;
|
pos += 2;
|
||||||
}
|
col += 2;
|
||||||
else if (c == '=') { emit(TOKEN(EQUALS)); }
|
} else if (c == '=') {
|
||||||
else if (c == '!' && pos + 1 < input.size() && input[pos + 1] == '=') {
|
emit(TOKEN(EQUALS));
|
||||||
|
} else if (c == '!' && pos + 1 < input.size() && input[pos + 1] == '=') {
|
||||||
tokens.push_back(TOKEN(NE));
|
tokens.push_back(TOKEN(NE));
|
||||||
pos += 2; col += 2;
|
pos += 2;
|
||||||
}
|
col += 2;
|
||||||
else if (c == '<' && pos + 1 < input.size() && input[pos + 1] == '=') {
|
} else if (c == '<' && pos + 1 < input.size() && input[pos + 1] == '=') {
|
||||||
tokens.push_back(TOKEN(LE));
|
tokens.push_back(TOKEN(LE));
|
||||||
pos += 2; col += 2;
|
pos += 2;
|
||||||
}
|
col += 2;
|
||||||
else if (c == '>' && pos + 1 < input.size() && input[pos + 1] == '=') {
|
} else if (c == '>' && pos + 1 < input.size() && input[pos + 1] == '=') {
|
||||||
tokens.push_back(TOKEN(GE));
|
tokens.push_back(TOKEN(GE));
|
||||||
pos += 2; col += 2;
|
pos += 2;
|
||||||
}
|
col += 2;
|
||||||
else if (c == '+' && pos + 1 < input.size() && input[pos + 1] == '+') {
|
} else if (c == '+' && pos + 1 < input.size() && input[pos + 1] == '+') {
|
||||||
tokens.push_back(TOKEN(CONCAT));
|
tokens.push_back(TOKEN(CONCAT));
|
||||||
pos += 2; col += 2;
|
pos += 2;
|
||||||
}
|
col += 2;
|
||||||
else if (c == '&' && pos + 1 < input.size() && input[pos + 1] == '&') {
|
} else if (c == '&' && pos + 1 < input.size() && input[pos + 1] == '&') {
|
||||||
tokens.push_back(TOKEN(AND));
|
tokens.push_back(TOKEN(AND));
|
||||||
pos += 2; col += 2;
|
pos += 2;
|
||||||
}
|
col += 2;
|
||||||
else if (c == '|' && pos + 1 < input.size() && input[pos + 1] == '|') {
|
} else if (c == '|' && pos + 1 < input.size() && input[pos + 1] == '|') {
|
||||||
tokens.push_back(TOKEN(OR));
|
tokens.push_back(TOKEN(OR));
|
||||||
pos += 2; col += 2;
|
pos += 2;
|
||||||
}
|
col += 2;
|
||||||
else if (c == '-' && pos + 1 < input.size() && input[pos + 1] == '>') {
|
} else if (c == '-' && pos + 1 < input.size() && input[pos + 1] == '>') {
|
||||||
tokens.push_back(TOKEN(IMPL));
|
tokens.push_back(TOKEN(IMPL));
|
||||||
pos += 2; col += 2;
|
pos += 2;
|
||||||
|
col += 2;
|
||||||
}
|
}
|
||||||
// Single-char operators
|
// Single-char operators
|
||||||
else if (c == '+') { emit(TOKEN(PLUS)); }
|
else if (c == '+') {
|
||||||
else if (c == '*') { emit(TOKEN(STAR)); }
|
emit(TOKEN(PLUS));
|
||||||
else if (c == '/') {
|
} else if (c == '*') {
|
||||||
|
emit(TOKEN(STAR));
|
||||||
|
} else if (c == '/') {
|
||||||
// Check if it's a path or division
|
// Check if it's a path or division
|
||||||
if (pos + 1 < input.size() && (isalnum(input[pos + 1]) || input[pos + 1] == '.')) {
|
if (pos + 1 < input.size() && (isalnum(input[pos + 1]) || input[pos + 1] == '.')) {
|
||||||
tokenize_path();
|
tokenize_path();
|
||||||
} else {
|
} else {
|
||||||
emit(TOKEN(SLASH));
|
emit(TOKEN(SLASH));
|
||||||
}
|
}
|
||||||
}
|
} else if (c == '<') {
|
||||||
else if (c == '<') { emit(TOKEN(LT)); }
|
emit(TOKEN(LT));
|
||||||
else if (c == '>') { emit(TOKEN(GT)); }
|
} else if (c == '>') {
|
||||||
else if (c == '!') { emit(TOKEN(NOT)); }
|
emit(TOKEN(GT));
|
||||||
else if (c == '.') {
|
} else if (c == '!') {
|
||||||
|
emit(TOKEN(NOT));
|
||||||
|
} else if (c == '.') {
|
||||||
// Check for ellipsis (...)
|
// Check for ellipsis (...)
|
||||||
if (pos + 2 < input.size() && input[pos + 1] == '.' && input[pos + 2] == '.') {
|
if (pos + 2 < input.size() && input[pos + 1] == '.' && input[pos + 2] == '.') {
|
||||||
tokens.push_back(TOKEN(ELLIPSIS));
|
tokens.push_back(TOKEN(ELLIPSIS));
|
||||||
pos += 3; col += 3;
|
pos += 3;
|
||||||
|
col += 3;
|
||||||
} else {
|
} else {
|
||||||
emit(TOKEN(DOT));
|
emit(TOKEN(DOT));
|
||||||
}
|
}
|
||||||
}
|
} else if (c == '?') {
|
||||||
else if (c == '?') { emit(TOKEN(QUESTION)); }
|
emit(TOKEN(QUESTION));
|
||||||
else if (c == '-') {
|
} else if (c == '-') {
|
||||||
// Check if it's a negative number or minus operator
|
// Check if it's a negative number or minus operator
|
||||||
if (pos + 1 < input.size() && isdigit(input[pos + 1])) {
|
if (pos + 1 < input.size() && isdigit(input[pos + 1])) {
|
||||||
tokenize_int();
|
tokenize_int();
|
||||||
} else {
|
} else {
|
||||||
emit(TOKEN(MINUS));
|
emit(TOKEN(MINUS));
|
||||||
}
|
}
|
||||||
|
} else if (isdigit(c)) {
|
||||||
|
tokenize_int();
|
||||||
|
} else if (isalpha(c) || c == '_') {
|
||||||
|
tokenize_ident();
|
||||||
|
} else {
|
||||||
|
pos++;
|
||||||
|
col++;
|
||||||
}
|
}
|
||||||
else if (isdigit(c)) { tokenize_int(); }
|
|
||||||
else if (isalpha(c) || c == '_') { tokenize_ident(); }
|
|
||||||
else { pos++; col++; }
|
|
||||||
}
|
}
|
||||||
tokens.push_back({Token::EOF_, "", line, col});
|
tokens.push_back({Token::EOF_, "", line, col});
|
||||||
|
|
||||||
|
|
@ -188,11 +252,16 @@ private:
|
||||||
while (pos < input.size()) {
|
while (pos < input.size()) {
|
||||||
char c = input[pos];
|
char c = input[pos];
|
||||||
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
|
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
|
||||||
if (c == '\n') { line++; col = 1; }
|
if (c == '\n') {
|
||||||
else { col++; }
|
line++;
|
||||||
|
col = 1;
|
||||||
|
} else {
|
||||||
|
col++;
|
||||||
|
}
|
||||||
pos++;
|
pos++;
|
||||||
} else if (c == '#') {
|
} else if (c == '#') {
|
||||||
while (pos < input.size() && input[pos] != '\n') pos++;
|
while (pos < input.size() && input[pos] != '\n')
|
||||||
|
pos++;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -208,13 +277,27 @@ private:
|
||||||
if (input[pos] == '\\' && pos + 1 < input.size()) {
|
if (input[pos] == '\\' && pos + 1 < input.size()) {
|
||||||
pos++;
|
pos++;
|
||||||
switch (input[pos]) {
|
switch (input[pos]) {
|
||||||
case 'n': s += '\n'; break;
|
case 'n':
|
||||||
case 't': s += '\t'; break;
|
s += '\n';
|
||||||
case 'r': s += '\r'; break;
|
break;
|
||||||
case '"': s += '"'; break;
|
case 't':
|
||||||
case '\\': s += '\\'; break;
|
s += '\t';
|
||||||
case '$': s += '$'; break; // Escaped $
|
break;
|
||||||
default: s += input[pos]; break;
|
case 'r':
|
||||||
|
s += '\r';
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
s += '"';
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
s += '\\';
|
||||||
|
break;
|
||||||
|
case '$':
|
||||||
|
s += '$';
|
||||||
|
break; // Escaped $
|
||||||
|
default:
|
||||||
|
s += input[pos];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
} else if (input[pos] == '$' && pos + 1 < input.size() && input[pos + 1] == '{') {
|
} else if (input[pos] == '$' && pos + 1 < input.size() && input[pos + 1] == '{') {
|
||||||
|
|
@ -236,10 +319,8 @@ private:
|
||||||
|
|
||||||
void tokenize_path() {
|
void tokenize_path() {
|
||||||
size_t start = pos;
|
size_t start = pos;
|
||||||
while (pos < input.size() && !isspace(input[pos]) &&
|
while (pos < input.size() && !isspace(input[pos]) && input[pos] != '(' && input[pos] != ')' &&
|
||||||
input[pos] != '(' && input[pos] != ')' &&
|
input[pos] != '{' && input[pos] != '}' && input[pos] != '[' && input[pos] != ']') {
|
||||||
input[pos] != '{' && input[pos] != '}' &&
|
|
||||||
input[pos] != '[' && input[pos] != ']') {
|
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
std::string path = input.substr(start, pos - start);
|
std::string path = input.substr(start, pos - start);
|
||||||
|
|
@ -249,8 +330,10 @@ private:
|
||||||
|
|
||||||
void tokenize_int() {
|
void tokenize_int() {
|
||||||
size_t start = pos;
|
size_t start = pos;
|
||||||
if (input[pos] == '-') pos++;
|
if (input[pos] == '-')
|
||||||
while (pos < input.size() && isdigit(input[pos])) pos++;
|
pos++;
|
||||||
|
while (pos < input.size() && isdigit(input[pos]))
|
||||||
|
pos++;
|
||||||
std::string num = input.substr(start, pos - start);
|
std::string num = input.substr(start, pos - start);
|
||||||
tokens.push_back({Token::INT, num, line, col});
|
tokens.push_back({Token::INT, num, line, col});
|
||||||
col += num.size();
|
col += num.size();
|
||||||
|
|
@ -258,21 +341,33 @@ private:
|
||||||
|
|
||||||
void tokenize_ident() {
|
void tokenize_ident() {
|
||||||
size_t start = pos;
|
size_t start = pos;
|
||||||
while (pos < input.size() && (isalnum(input[pos]) || input[pos] == '_' || input[pos] == '-')) pos++;
|
while (pos < input.size() && (isalnum(input[pos]) || input[pos] == '_' || input[pos] == '-'))
|
||||||
|
pos++;
|
||||||
std::string ident = input.substr(start, pos - start);
|
std::string ident = input.substr(start, pos - start);
|
||||||
|
|
||||||
Token::Type type = Token::IDENT;
|
Token::Type type = Token::IDENT;
|
||||||
if (ident == "let") type = Token::LET;
|
if (ident == "let")
|
||||||
else if (ident == "in") type = Token::IN;
|
type = Token::LET;
|
||||||
else if (ident == "rec") type = Token::REC;
|
else if (ident == "in")
|
||||||
else if (ident == "if") type = Token::IF;
|
type = Token::IN;
|
||||||
else if (ident == "then") type = Token::THEN;
|
else if (ident == "rec")
|
||||||
else if (ident == "else") type = Token::ELSE;
|
type = Token::REC;
|
||||||
else if (ident == "assert") type = Token::ASSERT;
|
else if (ident == "if")
|
||||||
else if (ident == "with") type = Token::WITH;
|
type = Token::IF;
|
||||||
else if (ident == "inherit") type = Token::INHERIT;
|
else if (ident == "then")
|
||||||
else if (ident == "true") type = Token::BOOL;
|
type = Token::THEN;
|
||||||
else if (ident == "false") type = Token::BOOL;
|
else if (ident == "else")
|
||||||
|
type = Token::ELSE;
|
||||||
|
else if (ident == "assert")
|
||||||
|
type = Token::ASSERT;
|
||||||
|
else if (ident == "with")
|
||||||
|
type = Token::WITH;
|
||||||
|
else if (ident == "inherit")
|
||||||
|
type = Token::INHERIT;
|
||||||
|
else if (ident == "true")
|
||||||
|
type = Token::BOOL;
|
||||||
|
else if (ident == "false")
|
||||||
|
type = Token::BOOL;
|
||||||
|
|
||||||
tokens.push_back({type, ident, line, col});
|
tokens.push_back({type, ident, line, col});
|
||||||
col += ident.size();
|
col += ident.size();
|
||||||
|
|
@ -286,7 +381,8 @@ public:
|
||||||
std::string current_file;
|
std::string current_file;
|
||||||
|
|
||||||
const Token& current() {
|
const Token& current() {
|
||||||
if (pos < tokens.size()) return tokens[pos];
|
if (pos < tokens.size())
|
||||||
|
return tokens[pos];
|
||||||
static Token eof{Token::EOF_, "", 0, 0};
|
static Token eof{Token::EOF_, "", 0, 0};
|
||||||
return eof;
|
return eof;
|
||||||
}
|
}
|
||||||
|
|
@ -303,8 +399,8 @@ public:
|
||||||
|
|
||||||
bool expect(Token::Type type) {
|
bool expect(Token::Type type) {
|
||||||
if (current().type != type) {
|
if (current().type != type) {
|
||||||
std::cerr << "Expected token " << type << " but got " << current().type
|
std::cerr << "Expected token " << type << " but got " << current().type << " at "
|
||||||
<< " at " << current().line << ":" << current().col << "\n";
|
<< current().line << ":" << current().col << "\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
advance();
|
advance();
|
||||||
|
|
@ -314,43 +410,74 @@ public:
|
||||||
// Get operator precedence (higher = tighter binding)
|
// Get operator precedence (higher = tighter binding)
|
||||||
int get_precedence(Token::Type type) {
|
int get_precedence(Token::Type type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Token::OR: return 1;
|
case Token::OR:
|
||||||
case Token::AND: return 2;
|
return 1;
|
||||||
case Token::IMPL: return 3;
|
case Token::AND:
|
||||||
case Token::EQEQ: case Token::NE: return 4;
|
return 2;
|
||||||
case Token::LT: case Token::GT: case Token::LE: case Token::GE: return 5;
|
case Token::IMPL:
|
||||||
case Token::CONCAT: return 6;
|
return 3;
|
||||||
case Token::PLUS: case Token::MINUS: return 7;
|
case Token::EQEQ:
|
||||||
case Token::STAR: case Token::SLASH: return 8;
|
case Token::NE:
|
||||||
default: return 0;
|
return 4;
|
||||||
|
case Token::LT:
|
||||||
|
case Token::GT:
|
||||||
|
case Token::LE:
|
||||||
|
case Token::GE:
|
||||||
|
return 5;
|
||||||
|
case Token::CONCAT:
|
||||||
|
return 6;
|
||||||
|
case Token::PLUS:
|
||||||
|
case Token::MINUS:
|
||||||
|
return 7;
|
||||||
|
case Token::STAR:
|
||||||
|
case Token::SLASH:
|
||||||
|
return 8;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert token type to binary operator
|
// Convert token type to binary operator
|
||||||
BinaryOp token_to_binop(Token::Type type) {
|
BinaryOp token_to_binop(Token::Type type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Token::PLUS: return BinaryOp::ADD;
|
case Token::PLUS:
|
||||||
case Token::MINUS: return BinaryOp::SUB;
|
return BinaryOp::ADD;
|
||||||
case Token::STAR: return BinaryOp::MUL;
|
case Token::MINUS:
|
||||||
case Token::SLASH: return BinaryOp::DIV;
|
return BinaryOp::SUB;
|
||||||
case Token::CONCAT: return BinaryOp::CONCAT;
|
case Token::STAR:
|
||||||
case Token::EQEQ: return BinaryOp::EQ;
|
return BinaryOp::MUL;
|
||||||
case Token::NE: return BinaryOp::NE;
|
case Token::SLASH:
|
||||||
case Token::LT: return BinaryOp::LT;
|
return BinaryOp::DIV;
|
||||||
case Token::GT: return BinaryOp::GT;
|
case Token::CONCAT:
|
||||||
case Token::LE: return BinaryOp::LE;
|
return BinaryOp::CONCAT;
|
||||||
case Token::GE: return BinaryOp::GE;
|
case Token::EQEQ:
|
||||||
case Token::AND: return BinaryOp::AND;
|
return BinaryOp::EQ;
|
||||||
case Token::OR: return BinaryOp::OR;
|
case Token::NE:
|
||||||
case Token::IMPL: return BinaryOp::IMPL;
|
return BinaryOp::NE;
|
||||||
default: throw std::runtime_error("Invalid binary operator");
|
case Token::LT:
|
||||||
|
return BinaryOp::LT;
|
||||||
|
case Token::GT:
|
||||||
|
return BinaryOp::GT;
|
||||||
|
case Token::LE:
|
||||||
|
return BinaryOp::LE;
|
||||||
|
case Token::GE:
|
||||||
|
return BinaryOp::GE;
|
||||||
|
case Token::AND:
|
||||||
|
return BinaryOp::AND;
|
||||||
|
case Token::OR:
|
||||||
|
return BinaryOp::OR;
|
||||||
|
case Token::IMPL:
|
||||||
|
return BinaryOp::IMPL;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Invalid binary operator");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Node> parse_expr() {
|
std::shared_ptr<Node> parse_expr() {
|
||||||
// Try to parse lambda
|
// Try to parse lambda
|
||||||
auto lambda = try_parse_lambda();
|
auto lambda = try_parse_lambda();
|
||||||
if (lambda) return lambda;
|
if (lambda)
|
||||||
|
return lambda;
|
||||||
|
|
||||||
if (consume(Token::IF)) {
|
if (consume(Token::IF)) {
|
||||||
auto cond = parse_expr();
|
auto cond = parse_expr();
|
||||||
|
|
@ -393,9 +520,7 @@ public:
|
||||||
return parse_expr1();
|
return parse_expr1();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Node> parse_expr1() {
|
std::shared_ptr<Node> parse_expr1() { return parse_binary_op(0); }
|
||||||
return parse_binary_op(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Precedence climbing for binary operators
|
// Precedence climbing for binary operators
|
||||||
std::shared_ptr<Node> parse_binary_op(int min_prec) {
|
std::shared_ptr<Node> parse_binary_op(int min_prec) {
|
||||||
|
|
@ -403,17 +528,14 @@ public:
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
int prec = get_precedence(current().type);
|
int prec = get_precedence(current().type);
|
||||||
if (prec == 0 || prec < min_prec) break;
|
if (prec == 0 || prec < min_prec)
|
||||||
|
break;
|
||||||
|
|
||||||
Token op_token = current();
|
Token op_token = current();
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
auto right = parse_binary_op(prec + 1);
|
auto right = parse_binary_op(prec + 1);
|
||||||
left = std::make_shared<Node>(BinaryOpNode(
|
left = std::make_shared<Node>(BinaryOpNode(token_to_binop(op_token.type), left, right));
|
||||||
token_to_binop(op_token.type),
|
|
||||||
left,
|
|
||||||
right
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return left;
|
return left;
|
||||||
|
|
@ -440,16 +562,16 @@ public:
|
||||||
Token n = current();
|
Token n = current();
|
||||||
expect(Token::IDENT);
|
expect(Token::IDENT);
|
||||||
auto a = std::make_shared<Node>(ConstStringNode(n.value));
|
auto a = std::make_shared<Node>(ConstStringNode(n.value));
|
||||||
curr->attr = std::make_shared<Node>(AppNode(
|
curr->attr =
|
||||||
std::make_shared<Node>(AppNode(curr->attr, a)),
|
std::make_shared<Node>(AppNode(std::make_shared<Node>(AppNode(curr->attr, a)),
|
||||||
std::make_shared<Node>(ConstNullNode())
|
std::make_shared<Node>(ConstNullNode())));
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else if (consume(Token::LBRACE)) {
|
} else if (consume(Token::LBRACE)) {
|
||||||
auto result = std::make_shared<Node>(SelectNode(left, std::make_shared<Node>(ConstStringNode(name.value))));
|
auto result = std::make_shared<Node>(
|
||||||
|
SelectNode(left, std::make_shared<Node>(ConstStringNode(name.value))));
|
||||||
parse_expr_attrs(result);
|
parse_expr_attrs(result);
|
||||||
expect(Token::RBRACE);
|
expect(Token::RBRACE);
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -576,10 +698,8 @@ public:
|
||||||
|
|
||||||
if (source) {
|
if (source) {
|
||||||
// inherit (expr) x → x = expr.x
|
// inherit (expr) x → x = expr.x
|
||||||
auto select = std::make_shared<Node>(SelectNode(
|
auto select = std::make_shared<Node>(
|
||||||
source,
|
SelectNode(source, std::make_shared<Node>(ConstStringNode(name.value))));
|
||||||
std::make_shared<Node>(ConstStringNode(name.value))
|
|
||||||
));
|
|
||||||
attrs.attrs.push_back({name.value, select});
|
attrs.attrs.push_back({name.value, select});
|
||||||
} else {
|
} else {
|
||||||
// inherit x → x = x
|
// inherit x → x = x
|
||||||
|
|
@ -607,8 +727,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (consume(Token::COMMA)) continue;
|
if (consume(Token::COMMA))
|
||||||
if (consume(Token::SEMICOLON)) continue;
|
continue;
|
||||||
|
if (consume(Token::SEMICOLON))
|
||||||
|
continue;
|
||||||
|
|
||||||
// If we get here and haven't handled the token, break
|
// If we get here and haven't handled the token, break
|
||||||
if (current().type != Token::RBRACE && current().type != Token::EOF_) {
|
if (current().type != Token::RBRACE && current().type != Token::EOF_) {
|
||||||
|
|
@ -630,18 +752,15 @@ public:
|
||||||
std::vector<std::shared_ptr<Node>> elements;
|
std::vector<std::shared_ptr<Node>> elements;
|
||||||
while (current().type != Token::RBRACKET) {
|
while (current().type != Token::RBRACKET) {
|
||||||
elements.push_back(parse_expr());
|
elements.push_back(parse_expr());
|
||||||
if (!consume(Token::COMMA)) break;
|
if (!consume(Token::COMMA))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
expect(Token::RBRACKET);
|
expect(Token::RBRACKET);
|
||||||
|
|
||||||
for (auto it = elements.rbegin(); it != elements.rend(); ++it) {
|
for (auto it = elements.rbegin(); it != elements.rend(); ++it) {
|
||||||
list = std::make_shared<Node>(AppNode(
|
list = std::make_shared<Node>(AppNode(
|
||||||
std::make_shared<Node>(AppNode(
|
std::make_shared<Node>(AppNode(std::make_shared<Node>(VarNode(0, "__list")), *it)),
|
||||||
std::make_shared<Node>(VarNode(0, "__list")),
|
list));
|
||||||
*it
|
|
||||||
)),
|
|
||||||
list
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
|
|
@ -666,10 +785,8 @@ public:
|
||||||
|
|
||||||
if (source) {
|
if (source) {
|
||||||
// inherit (expr) x → x = expr.x
|
// inherit (expr) x → x = expr.x
|
||||||
auto select = std::make_shared<Node>(SelectNode(
|
auto select = std::make_shared<Node>(
|
||||||
source,
|
SelectNode(source, std::make_shared<Node>(ConstStringNode(name.value))));
|
||||||
std::make_shared<Node>(ConstStringNode(name.value))
|
|
||||||
));
|
|
||||||
bindings.push_back({name.value, select});
|
bindings.push_back({name.value, select});
|
||||||
} else {
|
} else {
|
||||||
// inherit x → x = x
|
// inherit x → x = x
|
||||||
|
|
@ -682,7 +799,8 @@ public:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current().type != Token::IDENT) break;
|
if (current().type != Token::IDENT)
|
||||||
|
break;
|
||||||
Token key = current();
|
Token key = current();
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
|
|
@ -696,7 +814,8 @@ public:
|
||||||
bindings.push_back({key.value, value});
|
bindings.push_back({key.value, value});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!consume(Token::SEMICOLON)) break;
|
if (!consume(Token::SEMICOLON))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -739,7 +858,8 @@ public:
|
||||||
while (current().type != Token::RBRACE && current().type != Token::EOF_) {
|
while (current().type != Token::RBRACE && current().type != Token::EOF_) {
|
||||||
if (consume(Token::ELLIPSIS)) {
|
if (consume(Token::ELLIPSIS)) {
|
||||||
has_ellipsis = true;
|
has_ellipsis = true;
|
||||||
if (consume(Token::COMMA)) continue;
|
if (consume(Token::COMMA))
|
||||||
|
continue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -757,7 +877,8 @@ public:
|
||||||
|
|
||||||
fields.push_back(field);
|
fields.push_back(field);
|
||||||
|
|
||||||
if (consume(Token::COMMA)) continue;
|
if (consume(Token::COMMA))
|
||||||
|
continue;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
|
@ -789,22 +910,14 @@ public:
|
||||||
|
|
||||||
for (const auto& field : fields) {
|
for (const auto& field : fields) {
|
||||||
// Create arg.field selection
|
// Create arg.field selection
|
||||||
auto select = std::make_shared<Node>(SelectNode(
|
auto select = std::make_shared<Node>(
|
||||||
arg_var,
|
SelectNode(arg_var, std::make_shared<Node>(ConstStringNode(field.name))));
|
||||||
std::make_shared<Node>(ConstStringNode(field.name))
|
|
||||||
));
|
|
||||||
|
|
||||||
if (field.default_val) {
|
if (field.default_val) {
|
||||||
// if arg ? field then arg.field else default
|
// if arg ? field then arg.field else default
|
||||||
auto has_attr = std::make_shared<Node>(HasAttrNode(
|
auto has_attr = std::make_shared<Node>(
|
||||||
arg_var,
|
HasAttrNode(arg_var, std::make_shared<Node>(ConstStringNode(field.name))));
|
||||||
std::make_shared<Node>(ConstStringNode(field.name))
|
auto if_node = std::make_shared<Node>(IfNode(has_attr, select, *field.default_val));
|
||||||
));
|
|
||||||
auto if_node = std::make_shared<Node>(IfNode(
|
|
||||||
has_attr,
|
|
||||||
select,
|
|
||||||
*field.default_val
|
|
||||||
));
|
|
||||||
bindings.push_back({field.name, if_node});
|
bindings.push_back({field.name, if_node});
|
||||||
} else {
|
} else {
|
||||||
bindings.push_back({field.name, select});
|
bindings.push_back({field.name, select});
|
||||||
|
|
@ -870,7 +983,8 @@ public:
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (depth > 0) i++;
|
if (depth > 0)
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth > 0) {
|
if (depth > 0) {
|
||||||
|
|
@ -947,4 +1061,4 @@ std::shared_ptr<Node> Parser::parse_file(const std::string& path) {
|
||||||
return parse(content, path);
|
return parse(content, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace nix_irc
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
#define NIX_IRC_PARSER_H
|
#define NIX_IRC_PARSER_H
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace nix_irc {
|
namespace nix_irc {
|
||||||
|
|
||||||
|
|
@ -20,6 +20,6 @@ private:
|
||||||
std::unique_ptr<Impl> pImpl;
|
std::unique_ptr<Impl> pImpl;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace nix_irc
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
#include "resolver.h"
|
#include "resolver.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace nix_irc {
|
namespace nix_irc {
|
||||||
|
|
||||||
|
|
@ -22,17 +22,20 @@ struct Resolver::Impl {
|
||||||
fs::path p(path);
|
fs::path p(path);
|
||||||
|
|
||||||
if (p.is_absolute()) {
|
if (p.is_absolute()) {
|
||||||
if (fs::exists(p)) return path;
|
if (fs::exists(p))
|
||||||
|
return path;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path from_dir = fs::path(from_file).parent_path();
|
fs::path from_dir = fs::path(from_file).parent_path();
|
||||||
fs::path candidate = from_dir / p;
|
fs::path candidate = from_dir / p;
|
||||||
if (fs::exists(candidate)) return candidate.string();
|
if (fs::exists(candidate))
|
||||||
|
return candidate.string();
|
||||||
|
|
||||||
for (const auto& search : config.search_paths) {
|
for (const auto& search : config.search_paths) {
|
||||||
candidate = fs::path(search) / p;
|
candidate = fs::path(search) / p;
|
||||||
if (fs::exists(candidate)) return candidate.string();
|
if (fs::exists(candidate))
|
||||||
|
return candidate.string();
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
|
|
@ -108,4 +111,4 @@ std::string normalize_path(const std::string& path) {
|
||||||
return fs::absolute(p).string();
|
return fs::absolute(p).string();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace nix_irc
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@
|
||||||
#define NIX_IRC_RESOLVER_H
|
#define NIX_IRC_RESOLVER_H
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace nix_irc {
|
namespace nix_irc {
|
||||||
|
|
||||||
|
|
@ -43,6 +43,6 @@ private:
|
||||||
bool is_static_import(const Node& node);
|
bool is_static_import(const Node& node);
|
||||||
std::string normalize_path(const std::string& path);
|
std::string normalize_path(const std::string& path);
|
||||||
|
|
||||||
}
|
} // namespace nix_irc
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace nix_irc {
|
namespace nix_irc {
|
||||||
|
|
||||||
|
|
@ -21,9 +21,7 @@ struct Serializer::Impl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_u8(uint8_t val) {
|
void write_u8(uint8_t val) { buffer.push_back(val); }
|
||||||
buffer.push_back(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_string(const std::string& str) {
|
void write_string(const std::string& str) {
|
||||||
write_u32(str.size());
|
write_u32(str.size());
|
||||||
|
|
@ -31,24 +29,42 @@ struct Serializer::Impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeType get_node_type(const Node& node) {
|
NodeType get_node_type(const Node& node) {
|
||||||
if (node.holds<ConstIntNode>()) return NodeType::CONST_INT;
|
if (node.holds<ConstIntNode>())
|
||||||
if (node.holds<ConstStringNode>()) return NodeType::CONST_STRING;
|
return NodeType::CONST_INT;
|
||||||
if (node.holds<ConstPathNode>()) return NodeType::CONST_PATH;
|
if (node.holds<ConstStringNode>())
|
||||||
if (node.holds<ConstBoolNode>()) return NodeType::CONST_BOOL;
|
return NodeType::CONST_STRING;
|
||||||
if (node.holds<ConstNullNode>()) return NodeType::CONST_NULL;
|
if (node.holds<ConstPathNode>())
|
||||||
if (node.holds<VarNode>()) return NodeType::VAR;
|
return NodeType::CONST_PATH;
|
||||||
if (node.holds<LambdaNode>()) return NodeType::LAMBDA;
|
if (node.holds<ConstBoolNode>())
|
||||||
if (node.holds<AppNode>()) return NodeType::APP;
|
return NodeType::CONST_BOOL;
|
||||||
if (node.holds<BinaryOpNode>()) return NodeType::BINARY_OP;
|
if (node.holds<ConstNullNode>())
|
||||||
if (node.holds<UnaryOpNode>()) return NodeType::UNARY_OP;
|
return NodeType::CONST_NULL;
|
||||||
if (node.holds<AttrsetNode>()) return NodeType::ATTRSET;
|
if (node.holds<VarNode>())
|
||||||
if (node.holds<SelectNode>()) return NodeType::SELECT;
|
return NodeType::VAR;
|
||||||
if (node.holds<HasAttrNode>()) return NodeType::HAS_ATTR;
|
if (node.holds<LambdaNode>())
|
||||||
if (node.holds<WithNode>()) return NodeType::WITH;
|
return NodeType::LAMBDA;
|
||||||
if (node.holds<IfNode>()) return NodeType::IF;
|
if (node.holds<AppNode>())
|
||||||
if (node.holds<LetNode>()) return NodeType::LET;
|
return NodeType::APP;
|
||||||
if (node.holds<LetRecNode>()) return NodeType::LETREC;
|
if (node.holds<BinaryOpNode>())
|
||||||
if (node.holds<AssertNode>()) return NodeType::ASSERT;
|
return NodeType::BINARY_OP;
|
||||||
|
if (node.holds<UnaryOpNode>())
|
||||||
|
return NodeType::UNARY_OP;
|
||||||
|
if (node.holds<AttrsetNode>())
|
||||||
|
return NodeType::ATTRSET;
|
||||||
|
if (node.holds<SelectNode>())
|
||||||
|
return NodeType::SELECT;
|
||||||
|
if (node.holds<HasAttrNode>())
|
||||||
|
return NodeType::HAS_ATTR;
|
||||||
|
if (node.holds<WithNode>())
|
||||||
|
return NodeType::WITH;
|
||||||
|
if (node.holds<IfNode>())
|
||||||
|
return NodeType::IF;
|
||||||
|
if (node.holds<LetNode>())
|
||||||
|
return NodeType::LET;
|
||||||
|
if (node.holds<LetRecNode>())
|
||||||
|
return NodeType::LETREC;
|
||||||
|
if (node.holds<AssertNode>())
|
||||||
|
return NodeType::ASSERT;
|
||||||
return NodeType::ERROR;
|
return NodeType::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,27 +90,36 @@ struct Serializer::Impl {
|
||||||
write_u32(n->index);
|
write_u32(n->index);
|
||||||
} else if (auto* n = node.get_if<LambdaNode>()) {
|
} else if (auto* n = node.get_if<LambdaNode>()) {
|
||||||
write_u32(n->arity);
|
write_u32(n->arity);
|
||||||
if (n->body) write_node(*n->body);
|
if (n->body)
|
||||||
|
write_node(*n->body);
|
||||||
} else if (auto* n = node.get_if<AppNode>()) {
|
} else if (auto* n = node.get_if<AppNode>()) {
|
||||||
if (n->func) write_node(*n->func);
|
if (n->func)
|
||||||
if (n->arg) write_node(*n->arg);
|
write_node(*n->func);
|
||||||
|
if (n->arg)
|
||||||
|
write_node(*n->arg);
|
||||||
} else if (auto* n = node.get_if<BinaryOpNode>()) {
|
} else if (auto* n = node.get_if<BinaryOpNode>()) {
|
||||||
write_u8(static_cast<uint8_t>(n->op));
|
write_u8(static_cast<uint8_t>(n->op));
|
||||||
if (n->left) write_node(*n->left);
|
if (n->left)
|
||||||
if (n->right) write_node(*n->right);
|
write_node(*n->left);
|
||||||
|
if (n->right)
|
||||||
|
write_node(*n->right);
|
||||||
} else if (auto* n = node.get_if<UnaryOpNode>()) {
|
} else if (auto* n = node.get_if<UnaryOpNode>()) {
|
||||||
write_u8(static_cast<uint8_t>(n->op));
|
write_u8(static_cast<uint8_t>(n->op));
|
||||||
if (n->operand) write_node(*n->operand);
|
if (n->operand)
|
||||||
|
write_node(*n->operand);
|
||||||
} else if (auto* n = node.get_if<AttrsetNode>()) {
|
} else if (auto* n = node.get_if<AttrsetNode>()) {
|
||||||
write_u8(n->recursive ? 1 : 0);
|
write_u8(n->recursive ? 1 : 0);
|
||||||
write_u32(n->attrs.size());
|
write_u32(n->attrs.size());
|
||||||
for (const auto& [key, val] : n->attrs) {
|
for (const auto& [key, val] : n->attrs) {
|
||||||
write_string(key);
|
write_string(key);
|
||||||
if (val) write_node(*val);
|
if (val)
|
||||||
|
write_node(*val);
|
||||||
}
|
}
|
||||||
} else if (auto* n = node.get_if<SelectNode>()) {
|
} else if (auto* n = node.get_if<SelectNode>()) {
|
||||||
if (n->expr) write_node(*n->expr);
|
if (n->expr)
|
||||||
if (n->attr) write_node(*n->attr);
|
write_node(*n->expr);
|
||||||
|
if (n->attr)
|
||||||
|
write_node(*n->attr);
|
||||||
if (n->default_expr && *n->default_expr) {
|
if (n->default_expr && *n->default_expr) {
|
||||||
write_u8(1);
|
write_u8(1);
|
||||||
write_node(**n->default_expr);
|
write_node(**n->default_expr);
|
||||||
|
|
@ -102,32 +127,45 @@ struct Serializer::Impl {
|
||||||
write_u8(0);
|
write_u8(0);
|
||||||
}
|
}
|
||||||
} else if (auto* n = node.get_if<HasAttrNode>()) {
|
} else if (auto* n = node.get_if<HasAttrNode>()) {
|
||||||
if (n->expr) write_node(*n->expr);
|
if (n->expr)
|
||||||
if (n->attr) write_node(*n->attr);
|
write_node(*n->expr);
|
||||||
|
if (n->attr)
|
||||||
|
write_node(*n->attr);
|
||||||
} else if (auto* n = node.get_if<WithNode>()) {
|
} else if (auto* n = node.get_if<WithNode>()) {
|
||||||
if (n->attrs) write_node(*n->attrs);
|
if (n->attrs)
|
||||||
if (n->body) write_node(*n->body);
|
write_node(*n->attrs);
|
||||||
|
if (n->body)
|
||||||
|
write_node(*n->body);
|
||||||
} else if (auto* n = node.get_if<IfNode>()) {
|
} else if (auto* n = node.get_if<IfNode>()) {
|
||||||
if (n->cond) write_node(*n->cond);
|
if (n->cond)
|
||||||
if (n->then_branch) write_node(*n->then_branch);
|
write_node(*n->cond);
|
||||||
if (n->else_branch) write_node(*n->else_branch);
|
if (n->then_branch)
|
||||||
|
write_node(*n->then_branch);
|
||||||
|
if (n->else_branch)
|
||||||
|
write_node(*n->else_branch);
|
||||||
} else if (auto* n = node.get_if<LetNode>()) {
|
} else if (auto* n = node.get_if<LetNode>()) {
|
||||||
write_u32(n->bindings.size());
|
write_u32(n->bindings.size());
|
||||||
for (const auto& [key, val] : n->bindings) {
|
for (const auto& [key, val] : n->bindings) {
|
||||||
write_string(key);
|
write_string(key);
|
||||||
if (val) write_node(*val);
|
if (val)
|
||||||
|
write_node(*val);
|
||||||
}
|
}
|
||||||
if (n->body) write_node(*n->body);
|
if (n->body)
|
||||||
|
write_node(*n->body);
|
||||||
} else if (auto* n = node.get_if<LetRecNode>()) {
|
} else if (auto* n = node.get_if<LetRecNode>()) {
|
||||||
write_u32(n->bindings.size());
|
write_u32(n->bindings.size());
|
||||||
for (const auto& [key, val] : n->bindings) {
|
for (const auto& [key, val] : n->bindings) {
|
||||||
write_string(key);
|
write_string(key);
|
||||||
if (val) write_node(*val);
|
if (val)
|
||||||
|
write_node(*val);
|
||||||
}
|
}
|
||||||
if (n->body) write_node(*n->body);
|
if (n->body)
|
||||||
|
write_node(*n->body);
|
||||||
} else if (auto* n = node.get_if<AssertNode>()) {
|
} else if (auto* n = node.get_if<AssertNode>()) {
|
||||||
if (n->cond) write_node(*n->cond);
|
if (n->cond)
|
||||||
if (n->body) write_node(*n->body);
|
write_node(*n->cond);
|
||||||
|
if (n->body)
|
||||||
|
write_node(*n->body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -198,9 +236,7 @@ struct Deserializer::Impl {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t read_u8() {
|
uint8_t read_u8() { return buffer[pos++]; }
|
||||||
return buffer[pos++];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string read_string() {
|
std::string read_string() {
|
||||||
uint32_t len = read_u32();
|
uint32_t len = read_u32();
|
||||||
|
|
@ -389,4 +425,4 @@ IRModule Deserializer::deserialize(const std::vector<uint8_t>& data) {
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace nix_irc
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
#define NIX_IRC_SERIALIZER_H
|
#define NIX_IRC_SERIALIZER_H
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
namespace nix_irc {
|
namespace nix_irc {
|
||||||
|
|
||||||
|
|
@ -34,6 +34,6 @@ private:
|
||||||
std::unique_ptr<Impl> pImpl;
|
std::unique_ptr<Impl> pImpl;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace nix_irc
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -2,14 +2,14 @@
|
||||||
#define NIX_IRC_TYPES_H
|
#define NIX_IRC_TYPES_H
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <optional>
|
|
||||||
#include <memory>
|
|
||||||
#include <variant>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <variant>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace nix_irc {
|
namespace nix_irc {
|
||||||
|
|
||||||
|
|
@ -40,15 +40,9 @@ enum class NodeType : uint8_t {
|
||||||
ERROR = 0xFF
|
ERROR = 0xFF
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class BinaryOp : uint8_t {
|
enum class BinaryOp : uint8_t { ADD, SUB, MUL, DIV, CONCAT, EQ, NE, LT, GT, LE, GE, AND, OR, IMPL };
|
||||||
ADD, SUB, MUL, DIV, CONCAT,
|
|
||||||
EQ, NE, LT, GT, LE, GE,
|
|
||||||
AND, OR, IMPL
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class UnaryOp : uint8_t {
|
enum class UnaryOp : uint8_t { NEG, NOT };
|
||||||
NEG, NOT
|
|
||||||
};
|
|
||||||
|
|
||||||
// Forward declare Node for use in shared_ptr
|
// Forward declare Node for use in shared_ptr
|
||||||
class Node;
|
class Node;
|
||||||
|
|
@ -194,42 +188,20 @@ struct ForceNode {
|
||||||
// Node wraps a variant for type-safe AST
|
// Node wraps a variant for type-safe AST
|
||||||
class Node {
|
class Node {
|
||||||
public:
|
public:
|
||||||
using Variant = std::variant<
|
using Variant = std::variant<ConstIntNode, ConstStringNode, ConstPathNode, ConstBoolNode,
|
||||||
ConstIntNode,
|
ConstNullNode, VarNode, LambdaNode, AppNode, BinaryOpNode,
|
||||||
ConstStringNode,
|
UnaryOpNode, AttrsetNode, SelectNode, HasAttrNode, WithNode, IfNode,
|
||||||
ConstPathNode,
|
LetNode, LetRecNode, AssertNode, ThunkNode, ForceNode>;
|
||||||
ConstBoolNode,
|
|
||||||
ConstNullNode,
|
|
||||||
VarNode,
|
|
||||||
LambdaNode,
|
|
||||||
AppNode,
|
|
||||||
BinaryOpNode,
|
|
||||||
UnaryOpNode,
|
|
||||||
AttrsetNode,
|
|
||||||
SelectNode,
|
|
||||||
HasAttrNode,
|
|
||||||
WithNode,
|
|
||||||
IfNode,
|
|
||||||
LetNode,
|
|
||||||
LetRecNode,
|
|
||||||
AssertNode,
|
|
||||||
ThunkNode,
|
|
||||||
ForceNode
|
|
||||||
>;
|
|
||||||
|
|
||||||
Variant data;
|
Variant data;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T> Node(T&& value) : data(std::forward<T>(value)) {}
|
||||||
Node(T&& value) : data(std::forward<T>(value)) {}
|
|
||||||
|
|
||||||
template<typename T>
|
template <typename T> T* get_if() { return std::get_if<T>(&data); }
|
||||||
T* get_if() { return std::get_if<T>(&data); }
|
|
||||||
|
|
||||||
template<typename T>
|
template <typename T> const T* get_if() const { return std::get_if<T>(&data); }
|
||||||
const T* get_if() const { return std::get_if<T>(&data); }
|
|
||||||
|
|
||||||
template<typename T>
|
template <typename T> bool holds() const { return std::holds_alternative<T>(data); }
|
||||||
bool holds() const { return std::holds_alternative<T>(data); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constructor implementations
|
// Constructor implementations
|
||||||
|
|
@ -239,7 +211,8 @@ inline LambdaNode::LambdaNode(uint32_t a, std::shared_ptr<Node> b, uint32_t l)
|
||||||
inline AppNode::AppNode(std::shared_ptr<Node> f, std::shared_ptr<Node> a, uint32_t l)
|
inline AppNode::AppNode(std::shared_ptr<Node> f, std::shared_ptr<Node> a, uint32_t l)
|
||||||
: func(f), arg(a), line(l) {}
|
: func(f), arg(a), line(l) {}
|
||||||
|
|
||||||
inline BinaryOpNode::BinaryOpNode(BinaryOp o, std::shared_ptr<Node> l, std::shared_ptr<Node> r, uint32_t ln)
|
inline BinaryOpNode::BinaryOpNode(BinaryOp o, std::shared_ptr<Node> l, std::shared_ptr<Node> r,
|
||||||
|
uint32_t ln)
|
||||||
: op(o), left(l), right(r), line(ln) {}
|
: op(o), left(l), right(r), line(ln) {}
|
||||||
|
|
||||||
inline UnaryOpNode::UnaryOpNode(UnaryOp o, std::shared_ptr<Node> operand, uint32_t l)
|
inline UnaryOpNode::UnaryOpNode(UnaryOp o, std::shared_ptr<Node> operand, uint32_t l)
|
||||||
|
|
@ -254,23 +227,20 @@ inline HasAttrNode::HasAttrNode(std::shared_ptr<Node> e, std::shared_ptr<Node> a
|
||||||
inline WithNode::WithNode(std::shared_ptr<Node> a, std::shared_ptr<Node> b, uint32_t l)
|
inline WithNode::WithNode(std::shared_ptr<Node> a, std::shared_ptr<Node> b, uint32_t l)
|
||||||
: attrs(a), body(b), line(l) {}
|
: attrs(a), body(b), line(l) {}
|
||||||
|
|
||||||
inline IfNode::IfNode(std::shared_ptr<Node> c, std::shared_ptr<Node> t, std::shared_ptr<Node> e, uint32_t l)
|
inline IfNode::IfNode(std::shared_ptr<Node> c, std::shared_ptr<Node> t, std::shared_ptr<Node> e,
|
||||||
|
uint32_t l)
|
||||||
: cond(c), then_branch(t), else_branch(e), line(l) {}
|
: cond(c), then_branch(t), else_branch(e), line(l) {}
|
||||||
|
|
||||||
inline LetNode::LetNode(std::shared_ptr<Node> b, uint32_t l)
|
inline LetNode::LetNode(std::shared_ptr<Node> b, uint32_t l) : body(b), line(l) {}
|
||||||
: body(b), line(l) {}
|
|
||||||
|
|
||||||
inline LetRecNode::LetRecNode(std::shared_ptr<Node> b, uint32_t l)
|
inline LetRecNode::LetRecNode(std::shared_ptr<Node> b, uint32_t l) : body(b), line(l) {}
|
||||||
: body(b), line(l) {}
|
|
||||||
|
|
||||||
inline AssertNode::AssertNode(std::shared_ptr<Node> c, std::shared_ptr<Node> b, uint32_t l)
|
inline AssertNode::AssertNode(std::shared_ptr<Node> c, std::shared_ptr<Node> b, uint32_t l)
|
||||||
: cond(c), body(b), line(l) {}
|
: cond(c), body(b), line(l) {}
|
||||||
|
|
||||||
inline ThunkNode::ThunkNode(std::shared_ptr<Node> e, uint32_t l)
|
inline ThunkNode::ThunkNode(std::shared_ptr<Node> e, uint32_t l) : expr(e), line(l) {}
|
||||||
: expr(e), line(l) {}
|
|
||||||
|
|
||||||
inline ForceNode::ForceNode(std::shared_ptr<Node> e, uint32_t l)
|
inline ForceNode::ForceNode(std::shared_ptr<Node> e, uint32_t l) : expr(e), line(l) {}
|
||||||
: expr(e), line(l) {}
|
|
||||||
|
|
||||||
struct SourceFile {
|
struct SourceFile {
|
||||||
std::string path;
|
std::string path;
|
||||||
|
|
@ -286,5 +256,5 @@ struct IRModule {
|
||||||
std::unordered_map<std::string, uint32_t> string_table;
|
std::unordered_map<std::string, uint32_t> string_table;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace nix_irc
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -5,20 +5,14 @@
|
||||||
#include "nix/expr/eval.hh"
|
#include "nix/expr/eval.hh"
|
||||||
#include "nix/expr/primops.hh"
|
#include "nix/expr/primops.hh"
|
||||||
#include "nix/expr/value.hh"
|
#include "nix/expr/value.hh"
|
||||||
#include "nix/store/store-api.hh"
|
|
||||||
#include "nix/util/source-path.hh"
|
|
||||||
|
|
||||||
|
#include "irc/evaluator.h"
|
||||||
#include "irc/ir_gen.h"
|
#include "irc/ir_gen.h"
|
||||||
#include "irc/parser.h"
|
#include "irc/parser.h"
|
||||||
#include "irc/resolver.h"
|
|
||||||
#include "irc/serializer.h"
|
#include "irc/serializer.h"
|
||||||
#include "irc/types.h"
|
#include "irc/types.h"
|
||||||
#include "irc/evaluator.h"
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
namespace nix_ir_plugin {
|
namespace nix_ir_plugin {
|
||||||
|
|
||||||
|
|
@ -29,11 +23,9 @@ using namespace nix_irc;
|
||||||
* Load and evaluate a pre-compiled IR bundle
|
* Load and evaluate a pre-compiled IR bundle
|
||||||
* Usage: builtins.nixIR.loadIR "/path/to/file.nixir"
|
* Usage: builtins.nixIR.loadIR "/path/to/file.nixir"
|
||||||
*/
|
*/
|
||||||
static void prim_loadIR(EvalState &state, const PosIdx pos, Value **args,
|
static void prim_loadIR(EvalState& state, const PosIdx pos, Value** args, Value& v) {
|
||||||
Value &v) {
|
|
||||||
auto path = state.forceStringNoCtx(
|
auto path = state.forceStringNoCtx(
|
||||||
*args[0], pos,
|
*args[0], pos, "while evaluating the first argument to builtins.nixIR.loadIR");
|
||||||
"while evaluating the first argument to builtins.nixIR.loadIR");
|
|
||||||
|
|
||||||
std::string pathStr(path);
|
std::string pathStr(path);
|
||||||
|
|
||||||
|
|
@ -43,24 +35,18 @@ static void prim_loadIR(EvalState &state, const PosIdx pos, Value **args,
|
||||||
try {
|
try {
|
||||||
module = deserializer.deserialize(pathStr);
|
module = deserializer.deserialize(pathStr);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
state.error<EvalError>("failed to deserialize IR bundle: %s", e.what())
|
state.error<EvalError>("failed to deserialize IR bundle: %s", e.what()).atPos(pos).debugThrow();
|
||||||
.atPos(pos)
|
|
||||||
.debugThrow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!module.entry) {
|
if (!module.entry) {
|
||||||
state.error<EvalError>("IR bundle has no entry point")
|
state.error<EvalError>("IR bundle has no entry point").atPos(pos).debugThrow();
|
||||||
.atPos(pos)
|
|
||||||
.debugThrow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Evaluator evaluator(state);
|
Evaluator evaluator(state);
|
||||||
evaluator.eval_to_nix(module.entry, v);
|
evaluator.eval_to_nix(module.entry, v);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
state.error<EvalError>("failed to evaluate IR: %s", e.what())
|
state.error<EvalError>("failed to evaluate IR: %s", e.what()).atPos(pos).debugThrow();
|
||||||
.atPos(pos)
|
|
||||||
.debugThrow();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,11 +54,9 @@ static void prim_loadIR(EvalState &state, const PosIdx pos, Value **args,
|
||||||
* Compile Nix source to IR on-the-fly
|
* Compile Nix source to IR on-the-fly
|
||||||
* Usage: builtins.nixIR.compile "{ x = 1; }"
|
* Usage: builtins.nixIR.compile "{ x = 1; }"
|
||||||
*/
|
*/
|
||||||
static void prim_compileNix(EvalState &state, const PosIdx pos, Value **args,
|
static void prim_compileNix(EvalState& state, const PosIdx pos, Value** args, Value& v) {
|
||||||
Value &v) {
|
|
||||||
auto source = state.forceStringNoCtx(
|
auto source = state.forceStringNoCtx(
|
||||||
*args[0], pos,
|
*args[0], pos, "while evaluating the first argument to builtins.nixIR.compile");
|
||||||
"while evaluating the first argument to builtins.nixIR.compile");
|
|
||||||
|
|
||||||
std::string sourceStr(source);
|
std::string sourceStr(source);
|
||||||
|
|
||||||
|
|
@ -81,9 +65,7 @@ static void prim_compileNix(EvalState &state, const PosIdx pos, Value **args,
|
||||||
auto ast = parser.parse(sourceStr, "<inline>");
|
auto ast = parser.parse(sourceStr, "<inline>");
|
||||||
|
|
||||||
if (!ast) {
|
if (!ast) {
|
||||||
state.error<EvalError>("failed to parse Nix expression")
|
state.error<EvalError>("failed to parse Nix expression").atPos(pos).debugThrow();
|
||||||
.atPos(pos)
|
|
||||||
.debugThrow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IRGenerator ir_gen;
|
IRGenerator ir_gen;
|
||||||
|
|
@ -93,9 +75,7 @@ static void prim_compileNix(EvalState &state, const PosIdx pos, Value **args,
|
||||||
evaluator.eval_to_nix(ir, v);
|
evaluator.eval_to_nix(ir, v);
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
state.error<EvalError>("IR compilation failed: %s", e.what())
|
state.error<EvalError>("IR compilation failed: %s", e.what()).atPos(pos).debugThrow();
|
||||||
.atPos(pos)
|
|
||||||
.debugThrow();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,8 +83,7 @@ static void prim_compileNix(EvalState &state, const PosIdx pos, Value **args,
|
||||||
* Get information about the IR plugin
|
* Get information about the IR plugin
|
||||||
* Usage: builtins.nixIR.info
|
* Usage: builtins.nixIR.info
|
||||||
*/
|
*/
|
||||||
static void prim_info(EvalState &state, const PosIdx pos, Value **args,
|
static void prim_info(EvalState& state, const PosIdx pos, Value** args, Value& v) {
|
||||||
Value &v) {
|
|
||||||
auto bindings = state.buildBindings(3);
|
auto bindings = state.buildBindings(3);
|
||||||
|
|
||||||
Value* vName = state.allocValue();
|
Value* vName = state.allocValue();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue