Move reserved word mangling, implement conditionals, unary operations
This commit is contained in:
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…
Reference in a new issue