tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

import-plan.js (1645B)


      1 import { sourceText } from './compiler.js';
      2 // Header meaning comes from the native compiler. Insert at the beginning, which
      3 // preserves every original character and keeps the directive in the header.
      4 export function importPlan(source, stage, manifest, alias) {
      5     if (!/^[a-f0-9]{64}$/u.test(manifest))
      6         throw new Error('Invalid module manifest');
      7     if (!/^[A-Za-z_][A-Za-z0-9_]*$/u.test(alias) || alias.length > 128)
      8         throw new Error('Use a namespace starting with a letter or underscore, followed by letters, digits or underscores.');
      9     const statement = `!import ${manifest} as ${alias}\n`;
     10     const existing = stage.imports.find(([ref]) => ref === manifest);
     11     if (existing) {
     12         // Locate a display selection in the compiler-masked header; this has no role
     13         // in parsing or compiling source. Fall back to selecting the whole source.
     14         let offset = 0, range = { start: 0, end: source.length };
     15         const masked = stage.body.split('\n');
     16         for (const [i, line] of source.split('\n').entries()) {
     17             if (line !== masked[i] && line.trimStart().startsWith('!import ') && line.includes(manifest)) {
     18                 range = { start: offset, end: offset + line.length };
     19                 break;
     20             }
     21             offset += line.length + 1;
     22         }
     23         return { source, statement, existing: { alias: existing[1], ...range } };
     24     }
     25     if (stage.imports.some(([, name]) => name === alias))
     26         throw new Error(`Namespace ${alias} is already used by another import.`);
     27     const next = statement + source;
     28     sourceText(next);
     29     return { source: next, statement };
     30 }