Move reserved word mangling, implement conditionals, unary operations

master
Sven Slootweg 9 months ago
parent 5a13358ef8
commit 2dc3ce056e

@ -5,20 +5,29 @@ const assert = require("assert");
const acceptableFirstCharacters = /^[a-zA-Z_]$/; const acceptableFirstCharacters = /^[a-zA-Z_]$/;
const acceptableSubsequentCharacters = /^[0-9a-zA-Z_]$/; const acceptableSubsequentCharacters = /^[0-9a-zA-Z_]$/;
const reservedWords = new Set([
"import",
"const",
"let",
"var"
]);
// This function deterministically and statelessly translates a name such that it is guaranteed to be valid in all identifier positions in JS. // This function deterministically and statelessly translates a name such that it is guaranteed to be valid in all identifier positions in JS.
// TODO: This can probably be made more performant... // TODO: This can probably be made more performant...
function mangleCharacter(character) { function mangleCharacter(character) {
return (character === "$") return (character === "$")
? "$$" ? "$$"
: `$${character.codePointAt(0)}` : `$${character.codePointAt(0)}`;
} }
module.exports = function mangleName(name) { module.exports = function mangleName(name) {
assert(name.length > 0); assert(name.length > 0);
if (reservedWords.has(name)) {
return "$" + name;
} else if (name.startsWith("$")) {
// FIXME: Tag an identifier of this type with an internal property instead // FIXME: Tag an identifier of this type with an internal property instead
if (name.startsWith("$")) {
return name; return name;
} else { } else {
let completedFirstCharacter = false; let completedFirstCharacter = false;

@ -150,7 +150,7 @@ function convertNode(node) {
result.uri = node.text; result.uri = node.text;
} }
if (type === "binary_expression") { if (type === "binary_expression" || type === "unary_expression") {
// Unpack the anonymous token // Unpack the anonymous token
result.operator = result.operator.text; result.operator = result.operator.text;
} }
@ -201,12 +201,14 @@ function convertNode(node) {
inherited_attrs: "NixInheritAttributes", inherited_attrs: "NixInheritAttributes",
attrs_inherited_from: "NixInheritAttributes", // FIXME: Gone? attrs_inherited_from: "NixInheritAttributes", // FIXME: Gone?
binding: "NixBinding", binding: "NixBinding",
unary_expression: "NixUnaryOperation",
binary_expression: "NixBinaryOperation", binary_expression: "NixBinaryOperation",
apply_expression: "NixFunctionCall", apply_expression: "NixFunctionCall",
select_expression: "NixAttributeSelection", select_expression: "NixAttributeSelection",
interpolation: "NixInterpolationExpression", interpolation: "NixInterpolationExpression",
list_expression: "NixListLiteral", list_expression: "NixListLiteral",
with_expression: "NixWithExpression", with_expression: "NixWithExpression",
if_expression: "NixConditional",
// Function definitions // Function definitions
function_expression: "NixFunctionDefinition", function_expression: "NixFunctionDefinition",
formals: "NixUnpackedAttributes", formals: "NixUnpackedAttributes",

@ -34,6 +34,16 @@ let tmplImplicitContextTop = templateExpression(`
Object.assign({}, %%environment%%) Object.assign({}, %%environment%%)
`); `);
let tmplConditionalExpression = templateExpression(`
(() => {
if (%%condition%%) {
return %%consequence%%;
} else {
return %%alternative%%;
}
})()
`);
let implicitContextCounter = 0; let implicitContextCounter = 0;
let trivial = { let trivial = {
@ -56,9 +66,10 @@ let trivial = {
}, },
NixIdentifier: (node, { getContext }) => { NixIdentifier: (node, { getContext }) => {
// FIXME: Mangle reserved keywords like `const` // FIXME: Mangle reserved keywords like `const`
let safeName = (node.name === "import") // let safeName = (node.name === "import")
? "$import" // ? "$import"
: node.name; // : node.name;
let safeName = node.name;
if (getContext("identifierType") === "define") { if (getContext("identifierType") === "define") {
return types.identifier(safeName); return types.identifier(safeName);
@ -69,6 +80,15 @@ let trivial = {
return tmplIdentifierReference({ name: safeName }); return tmplIdentifierReference({ name: safeName });
} }
}, },
NixUnaryOperation: (_node, { defer }) => {
return defer((node) => {
if (node.operator === "-") {
return types.unaryExpression(node.operator, node.argument, true);
} else {
throw new Error(`Unsupported operator: ${node.operator}`);
}
});
},
NixBinaryOperation: (_node, { defer }) => { NixBinaryOperation: (_node, { defer }) => {
return defer((node) => { return defer((node) => {
// FIXME: Verify that all the 'operator' values match between Nix and JS! // FIXME: Verify that all the 'operator' values match between Nix and JS!
@ -104,6 +124,16 @@ let trivial = {
body: node.body body: node.body
}); });
}); });
},
NixConditional: (_node, { defer }) => {
// condition, consequence, alternative
return defer((node) => {
return tmplConditionalExpression({
condition: node.condition,
consequence: node.consequence,
alternative: node.alternative
});
});
} }
} }
}; };

Loading…
Cancel
Save