Move reserved word mangling, implement conditionals, unary operations

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

@ -5,20 +5,29 @@ const assert = require("assert");
const acceptableFirstCharacters = /^[a-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.
// TODO: This can probably be made more performant...
function mangleCharacter(character) {
return (character === "$")
? "$$"
: `$${character.codePointAt(0)}`
: `$${character.codePointAt(0)}`;
}
module.exports = function mangleName(name) {
assert(name.length > 0);
// FIXME: Tag an identifier of this type with an internal property instead
if (name.startsWith("$")) {
if (reservedWords.has(name)) {
return "$" + name;
} else if (name.startsWith("$")) {
// FIXME: Tag an identifier of this type with an internal property instead
return name;
} else {
let completedFirstCharacter = false;

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

@ -34,6 +34,16 @@ let tmplImplicitContextTop = templateExpression(`
Object.assign({}, %%environment%%)
`);
let tmplConditionalExpression = templateExpression(`
(() => {
if (%%condition%%) {
return %%consequence%%;
} else {
return %%alternative%%;
}
})()
`);
let implicitContextCounter = 0;
let trivial = {
@ -56,9 +66,10 @@ let trivial = {
},
NixIdentifier: (node, { getContext }) => {
// FIXME: Mangle reserved keywords like `const`
let safeName = (node.name === "import")
? "$import"
: node.name;
// let safeName = (node.name === "import")
// ? "$import"
// : node.name;
let safeName = node.name;
if (getContext("identifierType") === "define") {
return types.identifier(safeName);
@ -69,6 +80,15 @@ let trivial = {
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 }) => {
return defer((node) => {
// FIXME: Verify that all the 'operator' values match between Nix and JS!
@ -94,9 +114,9 @@ let trivial = {
setContext(null, "implicitContext", contextName);
return defer((node) => {
let setupCode = (hasParent)
? tmplImplicitContextNested({ environment: node.environment, parent: parentContext })
: tmplImplicitContextTop({ environment: node.environment });
let setupCode = (hasParent)
? tmplImplicitContextNested({ environment: node.environment, parent: parentContext })
: tmplImplicitContextTop({ environment: node.environment });
return tmplWithWrapper({
contextName: contextName,
@ -104,6 +124,16 @@ let trivial = {
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