<commit_before>/// <reference path="util.ts" />
/// <reference path="ast.ts" />
/// <reference path="type_elaborate.ts" />
/// <reference path="visit.ts" />

// Another type test for the specific kind of node we're interested in. We'll
// use this to follow one piece of advice from the "Scrap Your Boilerplate"
// paper: when you're interested in one kind of node, first write a function
// that dynamically tests for that kind and does its action. Then use separate
// code to lift it to a recursive traversal.
function is_lookup(tree: SyntaxNode): tree is LookupNode {
  return tree.tag === "lookup";
}

// An inheritance layer on ASTTranslate that desugars auto-persists. This
// *updates* the type_table with information about any newly generated nodes.
function gen_desugar(type_table: TypeTable, check: Gen<TypeCheck>):
  Gen<ASTTranslate>
{
  return function (fsuper: ASTTranslate): ASTTranslate {
    return function (tree: SyntaxNode): SyntaxNode {
      if (is_lookup(tree)) {
        let [type, env] = type_table[tree.id];
        let [stack, _] = env;
        let [__, index] = stack_lookup(stack, tree.ident);

        if (index === 0) {
          // A variable from the current stage. This is a normal access.
          return fsuper(tree);
        } else {
          // A variable from any other stage is an auto-persist. Construct a
          // persist escape that looks up `index` stages.
          let lookup : LookupNode = { tag: "lookup", ident: tree.ident };
          let escape : EscapeNode = {
            tag: "escape", kind: "persist", expr: lookup, count: index
          };

          // Now we elaborate the subtree to preserve the restrictions of the
          // IR.
          let elaborated = elaborate_subtree(escape, env, type_table, check);

          return elaborated;
        }
      } else {
        return fsuper(tree);
      }
    }
  }
}

// Get a copy of the *elaborated* AST with syntactic sugar removed. For now,
// the only sugar is "auto-persists", i.e., references to variables from other
// stages.
function desugar(tree: SyntaxNode, type_table: TypeTable,
    check: Gen<TypeCheck>): SyntaxNode
{
  let _desugar = fix(compose(gen_desugar(type_table, check), gen_translate));
  return _desugar(tree);
}
<commit_msg>Do not desugar extern accesses<commit_after>/// <reference path="util.ts" />
/// <reference path="ast.ts" />
/// <reference path="type_elaborate.ts" />
/// <reference path="visit.ts" />

// Another type test for the specific kind of node we're interested in. We'll
// use this to follow one piece of advice from the "Scrap Your Boilerplate"
// paper: when you're interested in one kind of node, first write a function
// that dynamically tests for that kind and does its action. Then use separate
// code to lift it to a recursive traversal.
function is_lookup(tree: SyntaxNode): tree is LookupNode {
  return tree.tag === "lookup";
}

// An inheritance layer on ASTTranslate that desugars auto-persists. This
// *updates* the type_table with information about any newly generated nodes.
function gen_desugar(type_table: TypeTable, check: Gen<TypeCheck>):
  Gen<ASTTranslate>
{
  return function (fsuper: ASTTranslate): ASTTranslate {
    return function (tree: SyntaxNode): SyntaxNode {
      if (is_lookup(tree)) {
        let [type, env] = type_table[tree.id];
        let [stack, _, externs, __] = env;
        if (tree.ident in externs) {
          // Extern accesses are not desugared.
          return fsuper(tree);
        }

        let [___, index] = stack_lookup(stack, tree.ident);

        if (index === 0) {
          // A variable from the current stage. This is a normal access.
          return fsuper(tree);
        } else {
          // A variable from any other stage is an auto-persist. Construct a
          // persist escape that looks up `index` stages.
          let lookup : LookupNode = { tag: "lookup", ident: tree.ident };
          let escape : EscapeNode = {
            tag: "escape", kind: "persist", expr: lookup, count: index
          };

          // Now we elaborate the subtree to preserve the restrictions of the
          // IR.
          let elaborated = elaborate_subtree(escape, env, type_table, check);

          return elaborated;
        }
      } else {
        return fsuper(tree);
      }
    }
  }
}

// Get a copy of the *elaborated* AST with syntactic sugar removed. For now,
// the only sugar is "auto-persists", i.e., references to variables from other
// stages.
function desugar(tree: SyntaxNode, type_table: TypeTable,
    check: Gen<TypeCheck>): SyntaxNode
{
  let _desugar = fix(compose(gen_desugar(type_table, check), gen_translate));
  return _desugar(tree);
}

{'fraction_non_alphanumeric': 0.1093816631130064, 'fraction_numerical': 0.00042643923240938164, 'mean_word_length': 2.740829346092504, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2701080', 'n_tokens_mistral': 1371, 'n_tokens_neox': 1333, 'n_words': 500}