"use strict";
(() => {
  var __defProp = Object.defineProperty;
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  var __decorateClass = (decorators, target, key, kind) => {
    var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
    for (var i = decorators.length - 1, decorator; i >= 0; i--)
      if (decorator = decorators[i])
        result = (kind ? decorator(target, key, result) : decorator(result)) || result;
    if (kind && result) __defProp(target, key, result);
    return result;
  };

  // src/compiler/elan-keywords.ts
  var abstractKeyword = "abstract";
  var andKeyword = "and";
  var asKeyword = "as";
  var assertKeyword = "assert";
  var beKeyword = "be";
  var callKeyword = "call";
  var catchKeyword = "catch";
  var classKeyword = "class";
  var constantKeyword = "constant";
  var constructorKeyword = "constructor";
  var elifKeyword = "elif";
  var elseKeyword = "else";
  var endKeyword = "end";
  var enumKeyword = "enum";
  var forKeyword = "for";
  var functionKeyword = "function";
  var ifKeyword = "if";
  var inKeyword = "in";
  var inheritsKeyword = "inherits";
  var interfaceKeyword = "interface";
  var isKeyword = "is";
  var lambdaKeyword = "lambda";
  var letKeyword = "let";
  var mainKeyword = "main";
  var newKeyword = "new";
  var notKeyword = "not";
  var ofKeyword = "of";
  var orKeyword = "or";
  var privateKeyword = "private";
  var procedureKeyword = "procedure";
  var propertyKeyword = "property";
  var reassignKeyword = "reassign";
  var returnKeyword = "return";
  var returnsKeyword = "returns";
  var setKeyword = "set";
  var testKeyword = "test";
  var thenKeyword = "then";
  var thisKeyword = "this";
  var throwKeyword = "throw";
  var toKeyword = "to";
  var tryKeyword = "try";
  var variableKeyword = "variable";
  var whileKeyword = "while";
  var withKeyword = "with";
  var abstractPropertyKeywords = abstractKeyword + " " + propertyKeyword;
  var abstractProcedureKeywords = abstractKeyword + " " + procedureKeyword;
  var abstractFunctionKeywords = abstractKeyword + " " + functionKeyword;
  var privatePropertyKeywords = privateKeyword + " " + propertyKeyword;
  var privateProcedureKeywords = privateKeyword + " " + procedureKeyword;
  var privateFunctionKeywords = privateKeyword + " " + functionKeyword;
  var abstractClassKeywords = abstractKeyword + " " + classKeyword;
  var commentMarker = "#";
  var ghostedAnnotation = "ghosted";

  // src/ide/frames/fields/regexes.ts
  var Regexes = class {
    static newLine = /^\r?\n/;
    static anythingToNewLineAsString = "^[^\r\n]*";
    static anythingToNewLineAsRegExp = /^[^\r\n]*/;
    static comment = /# [^\r\n]*/;
    static indent = /^\s*/;
    static ifClause = /^if[^\S\r\n]/;
    static intoClause = /^into[^\S\r\n]/;
    static identifier = /^\s*(([a-z][a-zA-Z0-9_]*)|(_[a-zA-Z0-9_]+))/;
    static literalInt = /^\s*[0-9]+/;
    static negatableLitInt = /^\s*-?((0b[0-1]+)|(0x[0-9a-fA-F]+)|([0-9]+))/;
    static negatableBase10Number = /^\s*-?[0-9]+/;
    static hexNumber = /[0-9a-fA-F]+/;
    static binaryNumber = /[0-1]+/;
    static negatableLitFloat = /^\s*-?[0-9]+\.[0-9]+((e|E)-?[0-9]+)?/;
    static charValue = /[^']/;
    static leadingSpaceNotNL = /^[^\S\r\n]+/;
    static anythingExceptUnescapedForwardSlash = /^([^\/\\]|\\.)+/;
    static flags = /^[dgimsuvy]*/;
    static whiteSpaceButNotNewline = /[^\S\r\n]/;
    static url = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&\/=]*)/;
    static compilerDirective = /^\[[A-Za-z]+\]\s/;
    static typeSimpleName = /^\s*[A-Z]\w*/;
  };

  // src/ide/frames/status-enums.ts
  var DisplayColour = /* @__PURE__ */ ((DisplayColour2) => {
    DisplayColour2[DisplayColour2["error"] = 0] = "error";
    DisplayColour2[DisplayColour2["warning"] = 1] = "warning";
    DisplayColour2[DisplayColour2["advisory"] = 2] = "advisory";
    DisplayColour2[DisplayColour2["ok"] = 3] = "ok";
    DisplayColour2[DisplayColour2["none"] = 4] = "none";
    return DisplayColour2;
  })(DisplayColour || {});

  // src/compiler/compiler-interfaces/type-options.ts
  var noTypeOptions = {
    isImmutable: false,
    isAbstract: false,
    isIndexable: false,
    isDoubleIndexable: false,
    isIterable: false
  };
  var immutableTypeOptions = {
    isImmutable: true,
    isAbstract: false,
    isIndexable: false,
    isDoubleIndexable: false,
    isIterable: false
  };
  function getTypeOptions() {
    return {
      isImmutable: false,
      isAbstract: false,
      isIndexable: false,
      isDoubleIndexable: false,
      isIterable: false
    };
  }

  // src/compiler/symbols/elan-type-names.ts
  var BooleanName = "Boolean";
  var IntName = "Int";
  var FloatName = "Float";
  var StringName = "String";
  var RegExpName = "RegExp";
  var FuncName = "Func";
  var TupleName = "Tuple";
  var AnyExceptEnumName = "AnyExceptEnum";
  var AnyEnumName = "AnyEnum";

  // src/compiler/symbols/function-type.ts
  var FunctionType = class _FunctionType {
    constructor(parameterNames2, parameterTypes, returnType, isExtension, isPure, isAsync, deprecated) {
      this.parameterNames = parameterNames2;
      this.parameterTypes = parameterTypes;
      this.returnType = returnType;
      this.isExtension = isExtension;
      this.isPure = isPure;
      this.isAsync = isAsync;
      this.deprecated = deprecated;
    }
    languageSpecificName(language) {
      const ps = this.parameterTypes.length === 0 ? "no parameters" : this.parameterTypes.length === 1 ? "parameter - " : "parameters - ";
      return `lambda or function name that takes ${ps}${this.parameterTypes.map((p) => p.languageSpecificName(language)).join(", ")} - returning a ${this.returnType.languageSpecificName(language)}`;
    }
    get initialValue() {
      return `system.emptyFunc(${this.returnType.initialValue})`;
    }
    // so can have mutable type parameters
    typeOptions = noTypeOptions;
    get name() {
      return `Func<of ${this.parameterTypes.map((p) => p.name).join(", ")} => ${this.returnType.name}>`;
    }
    toString() {
      return FuncName;
    }
    isAssignableFrom(otherType) {
      if (otherType instanceof _FunctionType) {
        if (this.parameterTypes.length !== otherType.parameterTypes.length) {
          return false;
        }
        const rt = this.returnType.isAssignableFrom(otherType.returnType);
        return rt && this.parameterTypes.map((t, i) => t.isAssignableFrom(otherType.parameterTypes[i])).every((b) => b);
      }
      return false;
    }
  };

  // src/compiler/symbols/unknown-type.ts
  var UnknownType = class _UnknownType {
    constructor() {
    }
    languageSpecificName(_language) {
      return this.name;
    }
    initialValue = "";
    typeOptions = immutableTypeOptions;
    static Instance = new _UnknownType();
    name = "Unknown";
    toString() {
      return this.name;
    }
    isAssignableFrom(_otherType) {
      return true;
    }
  };

  // src/compiler/symbols/unknown-symbol.ts
  var UnknownSymbol = class {
    constructor(id) {
      this.symbolId = id ?? "";
    }
    symbolId = "";
    symbolType = () => UnknownType.Instance;
    symbolScope = 8 /* unknown */;
    symbolIsType = false;
    name = "Unknown Symbol";
  };

  // src/compiler/symbols/null-scope.ts
  var NullScope = class _NullScope {
    resolveSymbol(_id, _caseSensitive, _scope) {
      return new UnknownSymbol();
    }
    resolveOwnSymbol(_id) {
      return new UnknownSymbol();
    }
    getParentScope() {
      return _NullScope.Instance;
    }
    symbolMatches(_id, _all, _initialScope) {
      return [];
    }
    getChildren() {
      return [];
    }
    symbolId = "";
    symbolType = () => UnknownType.Instance;
    symbolScope = 8 /* unknown */;
    symbolIsType = false;
    static Instance = new _NullScope();
  };

  // src/compiler/symbols/procedure-type.ts
  var ProcedureType = class {
    constructor(parameterNames2, parameterTypes, isExtension, isAsync, deprecated) {
      this.parameterNames = parameterNames2;
      this.parameterTypes = parameterTypes;
      this.isExtension = isExtension;
      this.isAsync = isAsync;
      this.deprecated = deprecated;
    }
    languageSpecificName(language) {
      return `Procedure (${this.parameterTypes.map((p) => p.languageSpecificName(language)).join(", ")})`;
    }
    typeOptions = immutableTypeOptions;
    initialValue = "";
    get name() {
      return `Procedure (${this.parameterTypes.map((p) => p.name).join(", ")})`;
    }
    toString() {
      return `Procedure`;
    }
    isAssignableFrom(_otherType) {
      return true;
    }
  };

  // src/compiler/elan-compiler-error.ts
  var ElanCompilerError = class extends Error {
    constructor(err) {
      super(err instanceof Error ? err.message : err);
      this.err = err;
    }
  };

  // src/compiler/symbols/int-type.ts
  var IntType = class _IntType {
    constructor() {
    }
    languageSpecificName(language) {
      return language.INT_NAME;
    }
    initialValue = "0";
    typeOptions = immutableTypeOptions;
    static Instance = new _IntType();
    name = IntName;
    toString() {
      return this.name;
    }
    isAssignableFrom(otherType) {
      return otherType instanceof _IntType;
    }
  };

  // src/compiler/symbols/float-type.ts
  var FloatType = class _FloatType {
    constructor() {
    }
    languageSpecificName(language) {
      return language.FLOAT_NAME;
    }
    initialValue = "0";
    typeOptions = immutableTypeOptions;
    static Instance = new _FloatType();
    name = FloatName;
    toString() {
      return this.name;
    }
    isNumber(st) {
      return st instanceof IntType || st instanceof _FloatType;
    }
    isAssignableFrom(otherType) {
      return this.isNumber(otherType);
    }
  };

  // src/compiler/symbols/class-type.ts
  var ClassType = class _ClassType {
    constructor(className, subType, isNotInheritable, typeOptions, inheritsFrom, scope) {
      this.className = className;
      this.subType = subType;
      this.isNotInheritable = isNotInheritable;
      this.typeOptions = typeOptions;
      this.inheritsFrom = inheritsFrom;
      this.scope = scope;
    }
    languageSpecificName(language) {
      const className = this.className.trim().toUpperCase() === language.LIST_NAME.toUpperCase() ? language.LIST_NAME : this.className.trim();
      if (this.ofTypes.length === 1) {
        return `${className}${language.START_OF_GENERIC}${this.ofTypes[0].languageSpecificName(language)}${language.END_OF_GENERIC}`;
      }
      if (this.ofTypes.length === 2) {
        return `${className}${language.START_OF_GENERIC}${this.ofTypes[0].languageSpecificName(language)}, ${this.ofTypes[1].languageSpecificName(language)}${language.END_OF_GENERIC}`;
      }
      return className;
    }
    get ofTypes() {
      return isClass(this.scope) ? this.scope.ofTypes : [];
    }
    get deprecated() {
      return isClass(this.scope) ? this.scope.deprecated : void 0;
    }
    reify(gts) {
      if (isClass(this.scope)) {
        const cls = this.scope.updateOfTypes(gts);
        return new _ClassType(
          this.className,
          this.subType,
          this.isNotInheritable,
          this.typeOptions,
          this.inheritsFrom,
          cls
        );
      }
      return this;
    }
    updateFrom(other) {
      this.className = other.className;
      this.isNotInheritable = other.isNotInheritable;
      this.typeOptions = other.typeOptions;
      this.inheritsFrom = other.inheritsFrom;
      this.scope = other.scope;
      return this;
    }
    symbolMatches(id, all) {
      const symbols = this.scope.getChildren().filter((f) => isSymbol(f));
      return symbolMatches(id, all, symbols);
    }
    typeMatch(t1, t2) {
      if (t1 instanceof FloatType && t2 instanceof IntType) {
        return true;
      }
      return t1.name === t2.name;
    }
    isAssignableFrom(otherType) {
      if (otherType instanceof _ClassType) {
        if (otherType.className === this.className) {
          if (this.ofTypes.length === otherType.ofTypes.length) {
            return this.ofTypes.length === 0 ? true : this.ofTypes.every((t, i) => this.typeMatch(t, otherType.ofTypes[i]));
          }
          return false;
        }
        return otherType.inheritsFrom.some((c) => this.isAssignableFrom(c));
      }
      return false;
    }
    getParentScope() {
      return this.scope;
    }
    childSymbols() {
      return this.scope.getChildren().filter((c) => isSymbol(c));
    }
    resolveSymbol(id, caseSensitive, initialScope) {
      return this.scope.resolveSymbol(id, caseSensitive, initialScope);
    }
    get name() {
      if (this.ofTypes.length === 1) {
        return `${this.className.trim()}<of ${this.ofTypes[0].name}>`;
      }
      if (this.ofTypes.length === 2) {
        return `${this.className.trim()}<of ${this.ofTypes[0].name}, ${this.ofTypes[1].name}>`;
      }
      return `${this.className.trim()}`;
    }
    toString() {
      return `${this.className.trim()}`;
    }
    get initialValue() {
      const isStdLib = this.scope.symbolScope === 2 /* stdlib */;
      const prefix = isStdLib ? "system.initialise(_stdlib." : "";
      const postfix = isStdLib ? ")" : "";
      return `${prefix}${this.className}.emptyInstance()${postfix}`;
    }
  };

  // src/compiler/symbols/generic-parameter-type.ts
  var GenericParameterType = class _GenericParameterType {
    constructor(id, constraint) {
      this.id = id;
      this.constraint = constraint;
    }
    languageSpecificName(_language) {
      return this.name;
    }
    typeOptions = noTypeOptions;
    initialValue = "";
    get name() {
      return this.constraint ? `${this.constraint.name}` : `Generic Parameter ${this.id}`;
    }
    toString() {
      return this.name;
    }
    isAssignableFrom(otherType) {
      if (otherType instanceof _GenericParameterType) {
        return this.name === otherType.name;
      }
      return false;
    }
  };

  // src/compiler/symbols/string-type.ts
  var StringType = class _StringType {
    constructor() {
    }
    languageSpecificName(language) {
      return language.STRING_NAME;
    }
    get ofTypes() {
      return [_StringType.Instance];
    }
    initialValue = '""';
    get typeOptions() {
      return {
        isImmutable: true,
        isAbstract: false,
        isIndexable: true,
        isDoubleIndexable: false,
        isIterable: true
      };
    }
    static Instance = new _StringType();
    name = StringName;
    toString() {
      return this.name;
    }
    isAssignableFrom(otherType) {
      return otherType instanceof _StringType;
    }
  };

  // src/compiler/symbols/tuple-type.ts
  var TupleType = class _TupleType {
    constructor(ofTypes) {
      this.ofTypes = ofTypes;
    }
    languageSpecificName(language) {
      return `(${this.ofTypes.map((t) => t.languageSpecificName(language)).join(", ")})`;
    }
    typeOptions = noTypeOptions;
    get initialValue() {
      const init = this.ofTypes.map((t) => t.initialValue).join(", ");
      return `system.emptyTuple([${init}])`;
    }
    get name() {
      return `(${this.ofTypes.map((t) => t.name).join(", ")})`;
    }
    toString() {
      return `(${this.ofTypes.map((t) => t.name).join(", ")})`;
    }
    isAssignableFrom(otherType) {
      if (otherType instanceof _TupleType) {
        if (this.ofTypes.length !== otherType.ofTypes.length) {
          return false;
        }
        return this.ofTypes.map((t, i) => t.isAssignableFrom(otherType.ofTypes[i])).every((b) => b);
      }
      return false;
    }
  };

  // src/compiler/compiler-interfaces/elan-type-interfaces.ts
  var elanMetadataKey = Symbol("elan-metadata");

  // src/compiler/compile-error.ts
  var DisplayPriority = /* @__PURE__ */ ((DisplayPriority2) => {
    DisplayPriority2[DisplayPriority2["first"] = 0] = "first";
    DisplayPriority2[DisplayPriority2["second"] = 1] = "second";
    DisplayPriority2[DisplayPriority2["third"] = 2] = "third";
    DisplayPriority2[DisplayPriority2["fourth"] = 3] = "fourth";
    return DisplayPriority2;
  })(DisplayPriority || {});
  var Severity = /* @__PURE__ */ ((Severity2) => {
    Severity2[Severity2["error"] = 0] = "error";
    Severity2[Severity2["warning"] = 1] = "warning";
    Severity2[Severity2["advisory"] = 2] = "advisory";
    return Severity2;
  })(Severity || {});
  var CompileError = class {
    constructor(priority, severity, message, locationId, link) {
      this.priority = priority;
      this.severity = severity;
      this.message = message;
      this.locationId = locationId;
      this.link = link;
    }
    toString() {
      return `${this.constructor.name}: ${this.message} Priority: ${DisplayPriority[this.priority]} Severity: ${Severity[this.severity]} at: ${this.locationId}`;
    }
    sameError(other) {
      return this.toString() === other.toString();
    }
  };
  var TypesCompileError = class extends CompileError {
    constructor(type1, type2, addInfo, location) {
      super(
        3 /* fourth */,
        0 /* error */,
        `Incompatible types. Expected: ${type2}${addInfo}, Provided: ${type1}.`,
        location,
        "LangRef.html#TypesCompileError"
      );
    }
  };
  var SyntaxCompileError = class extends CompileError {
    constructor(message, location, link = "") {
      const linkToUse = link === "" ? "LangRef.html#compile_error" : link;
      super(1 /* second */, 0 /* error */, message, location, linkToUse);
    }
  };
  var UndefinedSymbolCompileError = class extends CompileError {
    constructor(id, type, location) {
      const postfix = type ? ` for type '${type}'` : "";
      super(
        2 /* third */,
        1 /* warning */,
        `'${id}' is not defined${postfix}.`,
        location,
        "LangRef.html#compile_error"
      );
    }
  };
  var CannotCallAFunction = class extends CompileError {
    constructor(location) {
      super(
        1 /* second */,
        0 /* error */,
        `Cannot call a function as a procedure.`,
        location,
        "LangRef.html#compile_error"
      );
    }
  };
  function reasonString(reason, isAdvisory) {
    const toAdvisory = (s) => isAdvisory ? "deprecated" : s;
    switch (reason) {
      case 3 /* classRemoved */:
        return `Class was ${toAdvisory("removed")}`;
      case 2 /* classRenamed */:
        return `Class was ${toAdvisory("renamed")}`;
      case 1 /* methodRemoved */:
        return `Method was ${toAdvisory("removed")}`;
      case 0 /* methodRenamed */:
        return `Method was ${toAdvisory("renamed")}`;
      case 5 /* classParametersChanged */:
        return `Parameters for class were ${toAdvisory("changed")}`;
      case 4 /* methodParametersChanged */:
        return `Parameters for method were ${toAdvisory("changed")}`;
      case 6 /* methodHidden */:
        return `Method was ${toAdvisory("hidden")}`;
    }
  }
  var IsDeprecated = class extends CompileError {
    constructor(reason, fromMajor, fromMinor, help, location, severity) {
      const isAdvisory = severity === 1 /* advisory */;
      const prefix = isAdvisory ? "Advisory: Code change suggested." : "Code change required.";
      super(
        isAdvisory ? 3 /* fourth */ : 0 /* first */,
        isAdvisory ? 2 /* advisory */ : 0 /* error */,
        `${prefix} ${reasonString(reason, isAdvisory)} in v${fromMajor}.${fromMinor}.`,
        location,
        help
      );
    }
  };
  var CannotCallAsAMethod = class extends CompileError {
    constructor(id, symbolType, location) {
      super(
        1 /* second */,
        0 /* error */,
        `Cannot invoke ${symbolType} '${id}' as a method.`,
        location,
        "LangRef.html#compile_error"
      );
    }
  };
  var MustBeAbstractCompileError = class extends CompileError {
    constructor(type, location) {
      super(
        1 /* second */,
        0 /* error */,
        `Superclass '${type}' must be inheritable class.`,
        location,
        "LangRef.html#compile_error"
      );
    }
  };
  var MustNotBeCircularDependencyCompileError = class extends CompileError {
    constructor(type, location) {
      super(
        1 /* second */,
        0 /* error */,
        `Class/interface '${type}' cannot inherit from itself.`,
        location,
        "LangRef.html#compile_error"
      );
    }
  };
  var MustBeSingleAbstractCompileError = class extends CompileError {
    constructor(types, location) {
      super(
        1 /* second */,
        0 /* error */,
        `There must be only one abstract superclass, ${types.join(", ")} are abstract classes.`,
        location,
        "LangRef.html#compile_error"
      );
    }
  };
  var PrivateMemberCompileError = class extends CompileError {
    constructor(id, location) {
      super(
        1 /* second */,
        0 /* error */,
        `Cannot reference private member '${id}'.`,
        location,
        "LangRef.html#compile_error"
      );
    }
  };
  var ExtensionCompileError = class extends CompileError {
    constructor(location) {
      super(
        1 /* second */,
        0 /* error */,
        `Cannot call extension method directly.`,
        location,
        "LangRef.html#compile_error"
      );
    }
  };
  var PropertyCompileError = class extends CompileError {
    constructor(location) {
      super(
        1 /* second */,
        0 /* error */,
        `Must prefix member with 'this'.`,
        location,
        "LangRef.html#compile_error"
      );
    }
  };
  var MissingParameterCompileError = class extends CompileError {
    constructor(description, location) {
      super(
        2 /* third */,
        1 /* warning */,
        `Missing argument(s). Expected: ${description}.`,
        location,
        "LangRef.html#compile_error"
      );
    }
  };
  var ExtraParameterCompileError = class extends CompileError {
    constructor(description, location) {
      description = description ? description : "none";
      super(
        1 /* second */,
        0 /* error */,
        `Too many argument(s). Expected: ${description}.`,
        location,
        "LangRef.html#compile_error"
      );
    }
  };
  var ParameterTypesCompileError = class extends CompileError {
    constructor(description, provided, location) {
      super(
        3 /* fourth */,
        0 /* error */,
        `Argument types. Expected: ${description}, Provided: ${provided}.`,
        location,
        "LangRef.html#compile_error"
      );
    }
  };
  var NotUniqueNameCompileError = class extends CompileError {
    constructor(name, postFix, location) {
      super(
        1 /* second */,
        0 /* error */,
        `Name '${name}' not unique in scope${postFix}.`,
        location,
        "LangRef.html#compile_error"
      );
    }
  };

  // src/compiler/symbols/boolean-type.ts
  var BooleanType = class _BooleanType {
    constructor() {
    }
    languageSpecificName(language) {
      return language.BOOL_NAME;
    }
    typeOptions = immutableTypeOptions;
    initialValue = "false";
    static Instance = new _BooleanType();
    name = BooleanName;
    toString() {
      return this.name;
    }
    isAssignableFrom(otherType) {
      return otherType instanceof _BooleanType;
    }
  };

  // src/compiler/symbols/duplicate-symbol.ts
  var DuplicateSymbol = class {
    constructor(duplicates) {
      this.duplicates = duplicates;
    }
    get symbolId() {
      return this.duplicates[0].symbolId;
    }
    symbolType() {
      return this.duplicates[0].symbolType();
    }
    get symbolScope() {
      return this.duplicates[0].symbolScope;
    }
    name = "Duplicate Symbol";
    get symbolIsType() {
      return this.duplicates[0].symbolIsType;
    }
  };

  // src/compiler/symbols/enum-type.ts
  var EnumType = class _EnumType {
    constructor(name) {
      this.name = name;
    }
    languageSpecificName(_language) {
      return this.name;
    }
    typeOptions = immutableTypeOptions;
    get initialValue() {
      return `${this.name}._default`;
    }
    toString() {
      return `Enum ${this.name}`;
    }
    isAssignableFrom(otherType) {
      if (otherType instanceof _EnumType) {
        return this.name === otherType.name;
      }
      return false;
    }
  };

  // src/compiler/syntax-nodes/abstract-ast-node.ts
  var AbstractAstNode = class {
    compileErrors = [];
    get symbolScope() {
      return 8 /* unknown */;
    }
    indent() {
      return "";
    }
    singleIndent() {
      return "  ";
    }
  };

  // src/compiler/syntax-nodes/breakpoint-asn.ts
  var BreakpointAsn = class extends AbstractAstNode {
    constructor(fieldId, scope) {
      super();
      this.fieldId = fieldId;
      this.scope = scope;
      getGlobalScope(scope).setScopeById(fieldId, this);
    }
    compile() {
      throw new Error("Method not implemented.");
    }
    breakpointStatus = 0 /* none */;
    setBreakPoint = () => {
      this.breakpointStatus = 2 /* active */;
    };
    clearBreakPoint = () => {
      this.breakpointStatus = 0 /* none */;
    };
    toggleBreakPoint = () => {
      if (this.hasBreakpoint()) {
        this.clearBreakPoint();
      } else {
        this.setBreakPoint();
      }
    };
    clearAllBreakPoints = () => {
      getGlobalScope(this.scope).updateBreakpoints(0 /* clear */);
    };
    hasBreakpoint() {
      return this.breakpointStatus === 2 /* active */ || this.breakpointStatus === 1 /* disabled */;
    }
    paused = false;
    symbolType() {
      return UnknownType.Instance;
    }
    compileScope;
    setCompileScope(s) {
      this.compileScope = s;
    }
    getParentScope() {
      return this.compileScope ?? this.scope;
    }
    getCurrentScope() {
      return this;
    }
    parentIndent() {
      return isAstNode(this.scope) ? this.scope.indent() : "";
    }
    indent() {
      return this.parentIndent() + this.singleIndent();
    }
    isNotGlobalOrLib(s) {
      const scope = s.symbolScope;
      return !(scope === 3 /* program */ || scope === 2 /* stdlib */);
    }
    bpIndent() {
      return this.indent() === "" ? "  " : this.indent();
    }
    getClassTypeMap(type, seenClasses) {
      seenClasses = seenClasses ?? [];
      if (type instanceof ClassType && (type.typeOptions.isIndexable || type.typeOptions.isDoubleIndexable)) {
        const ofTypes = type.ofTypes;
        const typeDict = { Type: type.name };
        if (ofTypes.length === 1) {
          typeDict["OfTypes"] = this.getClassTypeMap(ofTypes[0], [...seenClasses]);
        }
        if (ofTypes.length === 2) {
          typeDict["KeyType"] = this.getClassTypeMap(ofTypes[0], [...seenClasses]);
          typeDict["ValueType"] = this.getClassTypeMap(ofTypes[1], [...seenClasses]);
        }
        return typeDict;
      } else if (type instanceof ClassType && !type.typeOptions.isIndexable) {
        const childSymbols = type.childSymbols().filter((s) => s instanceof PropertyAsn);
        const className = type.name;
        const typeDict = { Type: className };
        if (seenClasses.includes(className)) {
          return typeDict;
        }
        typeDict["Properties"] = {};
        seenClasses.push(className);
        for (const s of childSymbols) {
          typeDict["Properties"][getId(s.name)] = this.getClassTypeMap(s.symbolType(), [
            ...seenClasses
          ]);
        }
        return typeDict;
      } else if (type instanceof TupleType) {
        const ofTypes = type.ofTypes;
        const typeDict = { Type: type.name };
        typeDict["OfTypes"] = [];
        for (const s of ofTypes) {
          typeDict["OfTypes"].push(this.getClassTypeMap(s, [...seenClasses]));
        }
        return typeDict;
      } else if (type instanceof EnumType) {
        const typeDict = { Type: "Enum" };
        typeDict["OfTypes"] = { Type: type.name };
        return typeDict;
      } else {
        return { Type: type.name };
      }
    }
    resolveVariables(scopedSymbols) {
      const resolveId = [];
      const symbols = scopedSymbols().filter(this.isNotGlobalOrLib).sort(orderSymbol);
      const indent = this.bpIndent();
      for (const symbol of symbols) {
        const idPrefix = symbol.symbolScope === 3 /* program */ ? "global." : symbol.symbolScope === 5 /* member */ ? "this." : "";
        const scopePrefix2 = symbol.symbolScope === 2 /* stdlib */ ? "_stdlib." : symbol.symbolScope === 3 /* program */ ? "global." : symbol.symbolScope === 5 /* member */ ? "this." : "";
        const id = `${idPrefix}${symbol.symbolId}`;
        const value = `${scopePrefix2}${symbol.symbolId}`;
        const type = symbol.symbolType();
        const typeMap = JSON.stringify(this.getClassTypeMap(type));
        resolveId.push(
          `${indent}_scopedIds${this.fieldId}.push(await system.debugSymbol("${id}", ${value}, '${typeMap}'));`
        );
      }
      return `${resolveId.join("\r\n")}`;
    }
    breakPoint(scopedSymbols) {
      if (this.breakpointStatus === 2 /* active */ || this.breakpointStatus === 3 /* singlestep */) {
        let resolve = this.resolveVariables(scopedSymbols);
        const type = this.breakpointStatus === 3 /* singlestep */ ? "true" : "false";
        const indent = this.bpIndent();
        if (this.breakpointStatus === 3 /* singlestep */) {
          resolve = `${indent}if (__pause) {
    ${resolve}
    ${indent}}`;
        }
        resolve = `${indent}const _scopedIds${this.fieldId} = [];
    ${resolve}`;
        return `${resolve}\r
${indent}__pause = await system.breakPoint(_scopedIds${this.fieldId}, "${this.fieldId}", ${type}, __pause);\r
`;
      }
      return "";
    }
    resolveSymbol(id, caseSensitive, _initialScope) {
      return this.getParentScope().resolveSymbol(id, caseSensitive, this);
    }
    symbolMatches(id, all, _initialScope) {
      return this.getParentScope().symbolMatches(id, all, this);
    }
    debugSymbols() {
      return () => allScopedSymbols(this.getParentScope(), this);
    }
    getNextState(currentState, event) {
      switch (currentState) {
        case 0 /* none */:
          switch (event) {
            case 0 /* clear */:
              return 0 /* none */;
            case 1 /* activate */:
              return 3 /* singlestep */;
            case 2 /* disable */:
              return 0 /* none */;
          }
        case 1 /* disabled */:
          switch (event) {
            case 0 /* clear */:
              return 0 /* none */;
            case 1 /* activate */:
              return 2 /* active */;
            case 2 /* disable */:
              return 1 /* disabled */;
          }
        case 2 /* active */:
          switch (event) {
            case 0 /* clear */:
              return 0 /* none */;
            case 1 /* activate */:
              return 2 /* active */;
            case 2 /* disable */:
              return 1 /* disabled */;
          }
        case 3 /* singlestep */:
          switch (event) {
            case 0 /* clear */:
              return 0 /* none */;
            case 1 /* activate */:
              return 3 /* singlestep */;
            case 2 /* disable */:
              return 0 /* none */;
          }
      }
    }
    updateBreakpoints(event) {
      this.breakpointStatus = this.getNextState(this.breakpointStatus, event);
    }
  };

  // src/compiler/syntax-nodes/empty-asn.ts
  var EmptyAsn = class _EmptyAsn {
    constructor(fieldId) {
      this.fieldId = fieldId;
    }
    indent() {
      return "";
    }
    items = [];
    id = "";
    symbolScope = 8 /* unknown */;
    compileErrors = [];
    compile() {
      return ``;
    }
    symbolType() {
      return UnknownType.Instance;
    }
    get value() {
      return _EmptyAsn.Instance;
    }
    toString() {
      return "";
    }
    static Instance = new _EmptyAsn("");
  };

  // src/compiler/syntax-nodes/class-members/property-asn.ts
  var PropertyAsn = class extends BreakpointAsn {
    constructor(fieldId, scope) {
      super(fieldId, scope);
    }
    isProperty = true;
    isMember = true;
    isAbstract = false;
    private = false;
    symbolIsType = false;
    name = EmptyAsn.Instance;
    type = EmptyAsn.Instance;
    getClass() {
      return this.getParentScope();
    }
    isGlobalClass(st) {
      return st instanceof ClassType && !st.typeOptions.isIndexable;
    }
    compile() {
      this.compileErrors = [];
      const pName = this.name.compile();
      const st = this.type.symbolType();
      mustBeUniqueNameInScope(pName, getClassScope(this), this.compileErrors, this.fieldId);
      mustBeKnownSymbolType(st, getId(this.type), this.compileErrors, this.fieldId);
      getGlobalScope(this.scope).addCompileErrors(this.compileErrors);
      if (this.isGlobalClass(st)) {
        return `${this.indent()}elan_${pName};\r
${this.indent()}get ${pName}() {\r
${this.indent()}${this.indent()}return this.elan_${pName} ??= ${this.type.compile()};\r
${this.indent()}}\r
${this.indent()}set ${pName}(${pName}) {\r
${this.indent()}${this.indent()}this.elan_${pName} = ${pName};\r
${this.indent()}}\r
`;
      }
      return `${this.indent()}${pName} = ${this.type.compile()};\r
`;
    }
    get symbolId() {
      return getId(this.name);
    }
    symbolType() {
      return this.type.symbolType();
    }
    get symbolScope() {
      return 5 /* member */;
    }
    initCode() {
      const tst = this.symbolType();
      if (!this.isGlobalClass(tst)) {
        return `["${getId(this.name)}", ${tst.initialValue}]`;
      }
      return "";
    }
  };

  // src/compiler/syntax-nodes/fixed-id-asn.ts
  var FixedIdAsn = class extends AbstractAstNode {
    constructor(id, fieldId) {
      super();
      this.id = id;
      this.fieldId = fieldId;
    }
    compile() {
      this.compileErrors = [];
      return this.id;
    }
    symbolType() {
      return UnknownType.Instance;
    }
    toString() {
      return this.id;
    }
  };

  // src/compiler/compile-rules.ts
  function mustBeKnownSymbol(symbol, scope, onSymbol, onType, compileErrors, location, forGlobal) {
    if (symbol instanceof UnknownSymbol && onType instanceof UnknownType) {
      const type = isClass(scope) ? scope.symbolId : "";
      const id = onSymbol || symbol.symbolId;
      compileErrors.push(new UndefinedSymbolCompileError(id, type, location));
    } else if (symbol instanceof UnknownSymbol) {
      const language = getGlobalScope(forGlobal).language;
      const type = isClass(scope) ? scope.symbolId : onType.languageSpecificName(language);
      compileErrors.push(new UndefinedSymbolCompileError(symbol.symbolId, type, location));
    }
  }
  function mustBeKnownExtension(id, type, compileErrors, location) {
    compileErrors.push(new UndefinedSymbolCompileError(id, type, location));
  }
  function mustBeKnownSymbolType(symbolType, originalName, compileErrors, location) {
    if (symbolType instanceof UnknownType) {
      compileErrors.push(new UndefinedSymbolCompileError(originalName, "", location));
    }
  }
  function mustNotBeKeyword(id, compileErrors, location) {
    if (ReservedWords.Instance.matchesIgnoringCase(id)) {
      compileErrors.push(new SyntaxCompileError(`'${id}' matches a reserved word.`, location));
    }
  }
  function mustBeProcedure(symbolId, symbolType, symbolScope, compileErrors, location) {
    if (symbolType instanceof FunctionType) {
      compileErrors.push(new CannotCallAFunction(location));
    } else if (isKnownType(symbolType) && !(symbolType instanceof ProcedureType)) {
      compileErrors.push(
        new CannotCallAsAMethod(symbolId, symbolScopeToFriendlyName(symbolScope), location)
      );
    }
  }
  function checkForDeprecation(symbolType, scope, compileErrors, location) {
    if (symbolType.deprecated) {
      const reason = symbolType.deprecated.reason;
      if (reason === 6 /* methodHidden */) {
        return;
      }
      if ((reason === 5 /* classParametersChanged */ || reason === 4 /* methodParametersChanged */) && compileErrors.length === 0) {
        return;
      }
      const file = getGlobalScope(scope);
      const version = file.getVersion();
      const fromMajor = symbolType.deprecated.fromMajor;
      const fromMinor = symbolType.deprecated.fromMinor;
      if (fromMajor < version.major || fromMajor === version.major && fromMinor <= version.minor) {
        compileErrors.push(
          new IsDeprecated(
            reason,
            fromMajor,
            fromMinor,
            symbolType.deprecated.message,
            location,
            symbolType.deprecated.Severity
          )
        );
      }
    }
  }
  function mustBeInheritableClassOrInterface(symbolType, name, compileErrors, location) {
    if (isKnownType(symbolType) && (!(symbolType instanceof ClassType) || symbolType.subType === 0 /* concrete */ || symbolType.isNotInheritable)) {
      compileErrors.push(new MustBeAbstractCompileError(name, location));
    }
  }
  function mustNotBeCircularDependency(name, compileErrors, location) {
    compileErrors.push(new MustNotBeCircularDependencyCompileError(name, location));
  }
  function mustBeSingleAbstractSuperClass(typeAndName, compileErrors, location) {
    const names = [];
    for (const [st, name] of typeAndName) {
      if (st instanceof ClassType) {
        if (st.subType === 1 /* abstract */) {
          names.push(name);
        }
      }
    }
    if (names.length > 1) {
      compileErrors.push(new MustBeSingleAbstractCompileError(names, location));
    }
  }
  function mustBePublicMember(member, compileErrors, location) {
    if (isMember(member) && member.private) {
      compileErrors.push(new PrivateMemberCompileError(member.symbolId, location));
    }
  }
  function mustCallExtensionViaQualifier(ft, qualifier, compileErrors, location) {
    if (ft.isExtension && isEmptyNode(qualifier)) {
      compileErrors.push(new ExtensionCompileError(location));
    }
  }
  function qualifierIsFixedIdOrEmpty(qualifier) {
    if (isEmptyNode(qualifier)) {
      return true;
    }
    return isAstQualifierNode(qualifier) ? qualifier.value instanceof FixedIdAsn : qualifier instanceof FixedIdAsn;
  }
  function mustNotCallNonExtensionViaQualifier(ft, name, qualifier, scope, compileErrors, location, forGlobal) {
    if (ft.isExtension || isClass(scope) || qualifierIsFixedIdOrEmpty(qualifier)) {
      return;
    }
    const language = getGlobalScope(forGlobal).language;
    compileErrors.push(
      new UndefinedSymbolCompileError(
        name,
        qualifier.symbolType().languageSpecificName(language),
        location
      )
    );
  }
  function mustbeValidQualifier(qualifier, compileErrors, location) {
    if (qualifier === EmptyAsn.Instance) {
      compileErrors.push(new PropertyCompileError(location));
    }
  }
  function mustCallMemberViaQualifier(id, ft, scope, compileErrors, location) {
    if (!ft.isExtension && isClass(scope)) {
      const t = scope.resolveOwnSymbol(id, true);
      if (t instanceof UnknownSymbol) {
        compileErrors.push(new UndefinedSymbolCompileError(id, scope.symbolId, location));
      }
    }
  }
  function mustMatchParameters(id, parms, ofType, description, isExtension, compileErrors, location, scope) {
    const extensionOfType = isExtension ? ofType[0] : void 0;
    const extensionParm = isExtension ? parms[0] : void 0;
    ofType = isExtension ? ofType.slice(1) : ofType;
    parms = isExtension ? parms.slice(1) : parms;
    const expected = ofType.length;
    const actual = parms.length;
    if (expected > actual) {
      compileErrors.push(new MissingParameterCompileError(description, location));
    }
    if (actual > expected) {
      compileErrors.push(new ExtraParameterCompileError(description, location));
    }
    if (extensionParm && extensionOfType) {
      const parmType = extensionParm.symbolType();
      if (!extensionOfType.isAssignableFrom(parmType)) {
        const language = getGlobalScope(scope).language;
        mustBeKnownExtension(id, parmType.languageSpecificName(language), compileErrors, location);
        return;
      }
    }
    const maxLen = parms.length > ofType.length ? parms.length : ofType.length;
    const tempErrors = [];
    const parmTypes = parms.map((p) => p.symbolType());
    for (let i = 0; i < maxLen; i++) {
      const p = parmTypes[i];
      const t = ofType[i];
      if (p && t) {
        mustBeAssignableType(t, p, tempErrors, location, scope);
      }
    }
    if (tempErrors.length > 0) {
      const language = getGlobalScope(scope).language;
      const provided = parmTypes.map((pt) => pt.languageSpecificName(language)).join(", ");
      compileErrors.push(new ParameterTypesCompileError(description, provided, location));
    }
  }
  function FailNotAssignable(lhs, rhs, compileErrors, location, language) {
    if (isKnownType(lhs) && isKnownType(rhs)) {
      compileErrors.push(
        new TypesCompileError(
          rhs.languageSpecificName(language),
          lhs.languageSpecificName(language),
          "",
          location
        )
      );
    }
  }
  function mustBeAssignableType(lhs, rhs, compileErrors, location, scope) {
    if (!lhs.isAssignableFrom(rhs)) {
      const language = getGlobalScope(scope).language;
      FailNotAssignable(lhs, rhs, compileErrors, location, language);
    }
  }
  function getId(astNode) {
    if (isAstIdNode(astNode)) {
      return astNode.id;
    }
    return "unknown";
  }
  function getQualifierId(astNode) {
    if (isAstQualifierNode(astNode)) {
      return getId(astNode.value);
    }
    return getId(astNode);
  }
  function mustBeUniqueNameInScope(name, scope, compileErrors, location) {
    const symbol = scope.resolveSymbol(name, true, scope);
    if (symbol instanceof DuplicateSymbol) {
      let postFix = "";
      if (symbol.duplicates.length === symbol.duplicates.filter((s) => isMember(s) && s.isAbstract).length) {
        postFix = ". Suggestion: factor out the common member(s) into a higher level interface";
      }
      compileErrors.push(new NotUniqueNameCompileError(name, postFix, location));
    }
  }
  function mustBeUniqueValueInScope(name, compileErrors, location) {
    compileErrors.push(new NotUniqueNameCompileError(name, "", location));
  }

  // src/compiler/syntax-nodes/class-members/abstract-property-asn.ts
  var AbstractPropertyAsn = class extends BreakpointAsn {
    isAbstract = true;
    isMember = true;
    private = false;
    constructor(fieldId, scope) {
      super(fieldId, scope);
    }
    symbolIsType = false;
    name = EmptyAsn.Instance;
    type = EmptyAsn.Instance;
    getClass() {
      return this.getParentScope();
    }
    compile() {
      this.compileErrors = [];
      const pName = this.name.compile();
      mustBeUniqueNameInScope(pName, getClassScope(this), this.compileErrors, this.fieldId);
      getGlobalScope(this.scope).addCompileErrors(this.compileErrors);
      return `${this.indent()}get ${pName}() {\r
${this.indent()}${this.indent()}return ${this.type.compile()};\r
${this.indent()}}\r
${this.indent()}set ${pName}(${pName}) {\r
${this.indent()}}\r
`;
    }
    initCode() {
      const tst = this.symbolType();
      if (!(tst instanceof ClassType)) {
        return `["${getId(this.name)}", ${tst.initialValue}]`;
      }
      return "";
    }
    get symbolId() {
      return getId(this.name);
    }
    symbolType() {
      return this.type.symbolType();
    }
    get symbolScope() {
      return 5 /* member */;
    }
  };

  // src/compiler/syntax-nodes/fields/inherits-from-asn.ts
  var InheritsFromAsn = class extends AbstractAstNode {
    constructor(fieldId) {
      super();
      this.fieldId = fieldId;
    }
    isParseByNodes = true;
    inheritance = EmptyAsn.Instance;
    symbolTypes() {
      if (isAstCollectionNode(this.inheritance)) {
        return this.inheritance.items.map((i) => i.symbolType());
      }
      return [];
    }
    symbolType() {
      return UnknownType.Instance;
    }
    compile() {
      this.compileErrors = [];
      return this.inheritance.compile();
    }
  };

  // src/compiler/syntax-nodes/globals/class-asn.ts
  var ClassAsn = class _ClassAsn extends BreakpointAsn {
    isParent = true;
    isClass = true;
    isAbstract = false;
    isConcrete = false;
    isRecord = false;
    isInterface = false;
    isNotInheritable = false;
    constructor(fieldId, scope) {
      super(fieldId, scope);
    }
    symbolIsType = true;
    name = EmptyAsn.Instance;
    inheritance = EmptyAsn.Instance;
    children = [];
    ofTypes = [];
    deprecated = void 0;
    updateOfTypes(_ofTypes) {
      return this;
    }
    get symbolScope() {
      return 3 /* program */;
    }
    inheritedSymbols(circular) {
      if (!circular && this.inheritance instanceof InheritsFromAsn) {
        return this.inheritance.symbolTypes();
      }
      return [];
    }
    getChildren() {
      return this.children.filter((c) => isSymbol(c));
    }
    indent() {
      return "";
    }
    properties() {
      return this.getChildren().filter(
        (c) => c instanceof PropertyAsn || c instanceof AbstractPropertyAsn
      );
    }
    propertiesToInit() {
      const pp = this.properties();
      const ps = pp.map((p) => p.initCode()).filter((s) => s).join(", ");
      return `[${ps}]`;
    }
    mapSymbol(c) {
      return [c.symbolType(), c.symbolId];
    }
    getInheritanceItems() {
      const superClasses = this.inheritance;
      if (superClasses instanceof InheritsFromAsn && isAstCollectionNode(superClasses.inheritance)) {
        return superClasses.inheritance.items;
      }
      return [];
    }
    getDirectSuperClassesTypeAndName() {
      const superClasses = getSuperClasses(this);
      const typeAndName = getSuperClassSymbols(superClasses, (_) => true, this).map(
        (c) => this.mapSymbol(c)
      );
      return typeAndName;
    }
    circularDependency(name) {
      mustNotBeCircularDependency(name, this.compileErrors, this.fieldId);
      getGlobalScope(this.scope).addCompileErrors(this.compileErrors);
      return `class ${name} { }\r
`;
    }
    lookForCircularDependencies(cf, seenNames) {
      const superClasses = getSuperClasses(cf);
      const symbols = getSuperClassSymbols(superClasses, (n) => n instanceof _ClassAsn, this);
      for (const s of symbols) {
        if (seenNames.includes(s.symbolId)) {
          return [true, s.symbolId];
        }
        const seenNamesThisPath = seenNames.concat([s.symbolId]);
        const [sd, name] = this.lookForCircularDependencies(s, seenNamesThisPath);
        if (sd) {
          return [sd, name];
        }
      }
      return [false, ""];
    }
    get symbolId() {
      return getId(this.name);
    }
    symbolMatches(id, all, _initialScope) {
      const otherMatches = this.getParentScope().symbolMatches(id, all, this);
      const symbols = this.getChildren().filter((f) => isSymbol(f));
      const types = this.getDirectSuperClassesTypeAndName().map((tn) => tn[0]).filter((t) => t instanceof ClassType);
      let inheritedMatches = [];
      for (const ct of types) {
        const s = ct.scope.symbolMatches(id, all, NullScope.Instance);
        inheritedMatches = inheritedMatches.concat(s);
      }
      const matches = symbolMatches(id, all, symbols);
      return matches.concat(inheritedMatches).concat(otherMatches);
    }
    resolveSymbol(id, caseSensitive, _initialScope) {
      const symbol = this.resolveOwnSymbol(id, caseSensitive);
      if (symbol instanceof UnknownSymbol) {
        return this.getParentScope().resolveSymbol(id, caseSensitive, this);
      }
      return symbol;
    }
    resolveOwnSymbol(id, caseSensitive) {
      if (id === thisKeyword) {
        return this;
      }
      let matches = this.getChildren().filter(
        (f) => isSymbol(f) && match(f.symbolId, id, caseSensitive)
      );
      const types = this.getDirectSuperClassesTypeAndName().map((tn) => tn[0]).filter((t) => t instanceof ClassType);
      for (const ct of types) {
        const s = ct.scope.resolveOwnSymbol(id, caseSensitive);
        if (isMember(s)) {
          matches.push(s);
        }
      }
      matches = Array.from(new Set(matches));
      if (matches.length === 2) {
        const concreteMatches = matches.filter((i) => isMember(i) && !i.isAbstract);
        if (concreteMatches.length === 1) {
          matches = concreteMatches;
        }
      }
      if (matches.length === 1) {
        return matches[0];
      }
      if (matches.length > 1) {
        return new DuplicateSymbol(matches);
      }
      return new UnknownSymbol(id);
    }
    getName() {
      const name = getId(this.name);
      mustBeUniqueNameInScope(name, getGlobalScope(this), this.compileErrors, this.fieldId);
      return name;
    }
    getExtends() {
      const typeAndName = this.getDirectSuperClassesTypeAndName();
      let implement = "";
      for (const [st, name] of typeAndName) {
        mustBeKnownSymbolType(st, name, this.compileErrors, this.fieldId);
        mustBeInheritableClassOrInterface(st, name, this.compileErrors, this.fieldId);
        if (st instanceof ClassType && st.subType === 1 /* abstract */) {
          implement = `extends ${name} `;
        }
      }
      mustBeSingleAbstractSuperClass(typeAndName, this.compileErrors, this.fieldId);
      return implement;
    }
    getClassIndex() {
      return getGlobalScope(this.scope).children.indexOf(this);
    }
    updateBreakpoints(event) {
      super.updateBreakpoints(event);
      for (const n of this.children) {
        n.updateBreakpoints(event);
      }
    }
  };

  // src/compiler/symbols/enum-value-type.ts
  var EnumValueType = class {
    constructor(owner, name) {
      this.owner = owner;
      this.name = name;
    }
    languageSpecificName(_language) {
      return this.name;
    }
    typeOptions = immutableTypeOptions;
    initialValue = "";
    toString() {
      return `${this.owner}.${this.name}`;
    }
    isAssignableFrom(_otherType) {
      return false;
    }
  };

  // src/compiler/syntax-nodes/fields/enum-values-asn.ts
  var EnumValuesAsn = class extends AbstractAstNode {
    constructor(fieldId, scope) {
      super();
      this.fieldId = fieldId;
      this.scope = scope;
    }
    values = EmptyAsn.Instance;
    get names() {
      if (isAstCollectionNode(this.values)) {
        const items = this.values.items;
        return items.map((i) => getId(i));
      }
      return [];
    }
    getSymbols(typeName) {
      return this.names.map((n) => ({
        symbolId: n,
        symbolType: () => new EnumValueType(typeName, n),
        symbolScope: 3 /* program */,
        symbolIsType: false
      }));
    }
    compile() {
      this.compileErrors = [];
      const ast = this.values;
      if (isAstCollectionNode(ast)) {
        const items = ast.items;
        if (items.length > 0) {
          const ids = items.map((i) => i.compile());
          for (const id of ids) {
            mustNotBeKeyword(id, this.compileErrors, this.fieldId);
            if (ids.indexOf(id) !== ids.lastIndexOf(id)) {
              mustBeUniqueValueInScope(id, this.compileErrors, this.fieldId);
            }
          }
          const def = `_default : "${ids[0]}", `;
          const itStr = ids.map((n) => `${n} : "${n}"`).join(", ");
          getGlobalScope(this.scope).addCompileErrors(this.compileErrors);
          return `${def}${itStr}`;
        }
        return `_default : ""`;
      }
      return "";
    }
    symbolType() {
      return UnknownType.Instance;
    }
  };

  // src/compiler/symbols/regexp-type.ts
  var RegExpType = class _RegExpType {
    constructor() {
    }
    languageSpecificName(_language) {
      return this.name;
    }
    initialValue = "system.emptyRegExp()";
    typeOptions = immutableTypeOptions;
    static Instance = new _RegExpType();
    name = RegExpName;
    toString() {
      return this.name;
    }
    isAssignableFrom(otherType) {
      return otherType instanceof _RegExpType;
    }
  };

  // src/compiler/symbols/elan-symbols.ts
  var intSymbol = {
    symbolId: IntType.Instance.name,
    symbolType: function() {
      return IntType.Instance;
    },
    symbolScope: 3 /* program */,
    symbolIsType: true,
    toLanguage: function(l) {
      return {
        symbolId: l.INT_NAME,
        symbolType: function() {
          return IntType.Instance;
        },
        symbolScope: 3 /* program */,
        symbolIsType: true
      };
    }
  };
  var floatSymbol = {
    symbolId: FloatType.Instance.name,
    symbolType: function() {
      return FloatType.Instance;
    },
    symbolScope: 3 /* program */,
    symbolIsType: true,
    toLanguage: function(l) {
      return {
        symbolId: l.FLOAT_NAME,
        symbolType: function() {
          return FloatType.Instance;
        },
        symbolScope: 3 /* program */,
        symbolIsType: true
      };
    }
  };
  var stringSymbol = {
    symbolId: StringType.Instance.name,
    symbolType: function() {
      return StringType.Instance;
    },
    symbolScope: 3 /* program */,
    symbolIsType: true,
    toLanguage: function(l) {
      return {
        symbolId: l.STRING_NAME,
        symbolType: function() {
          return StringType.Instance;
        },
        symbolScope: 3 /* program */,
        symbolIsType: true
      };
    }
  };
  var booleanSymbol = {
    symbolId: BooleanType.Instance.name,
    symbolType: function() {
      return BooleanType.Instance;
    },
    symbolScope: 3 /* program */,
    symbolIsType: true,
    toLanguage: function(l) {
      return {
        symbolId: l.BOOL_NAME,
        symbolType: function() {
          return BooleanType.Instance;
        },
        symbolScope: 3 /* program */,
        symbolIsType: true
      };
    }
  };
  var regExpSymbol = {
    symbolId: RegExpType.Instance.name,
    symbolType: function() {
      return RegExpType.Instance;
    },
    symbolScope: 3 /* program */,
    symbolIsType: true
  };
  var tupleSymbol = {
    symbolId: TupleName,
    symbolType: function() {
      return new TupleType([new GenericParameterType("T1"), new GenericParameterType("T2")]);
    },
    symbolScope: 3 /* program */,
    isClass: true,
    isAbstract: true,
    isNotInheritable: true,
    ofTypes: [new GenericParameterType("T1"), new GenericParameterType("T2")],
    symbolIsType: true
  };
  var funcSymbol = {
    symbolId: FuncName,
    symbolType: function() {
      return new FunctionType(
        ["T"],
        [new GenericParameterType("T")],
        new GenericParameterType("T1"),
        false,
        true,
        false
      );
    },
    symbolScope: 3 /* program */,
    isClass: true,
    isAbstract: true,
    isNotInheritable: true,
    ofTypes: [new GenericParameterType("T")],
    symbolIsType: true
  };

  // src/compiler/syntax-nodes/globals/enum-asn.ts
  var EnumAsn = class extends BreakpointAsn {
    constructor(fieldId, scope) {
      super(fieldId, scope);
    }
    symbolIsType = true;
    get symbolId() {
      return getId(this.name);
    }
    symbolType() {
      return new EnumType(this.symbolId);
    }
    name = EmptyAsn.Instance;
    values = EmptyAsn.Instance;
    compile() {
      this.compileErrors = [];
      const name = this.name.compile();
      mustBeUniqueNameInScope(name, getGlobalScope(this.scope), this.compileErrors, this.fieldId);
      getGlobalScope(this.scope).addCompileErrors(this.compileErrors);
      return `const ${name} = {\r
${this.singleIndent()}${this.values.compile()}\r
};\r
`;
    }
    enumValueSymbols() {
      return isEnumValuesAsn(this.values) ? this.values.getSymbols(getId(this.name)) : [];
    }
    resolveSymbol(id, caseSensitive, _initialScope) {
      for (const n of this.enumValueSymbols()) {
        if (match(n.symbolId, id, caseSensitive)) {
          return n;
        }
      }
      return this.getParentScope().resolveSymbol(id, caseSensitive, this);
    }
    symbolMatches(id, all, _initialScope) {
      const otherMatches = this.getParentScope().symbolMatches(id, all, this);
      const symbols = this.enumValueSymbols();
      const matches = symbolMatches(id, all, symbols);
      return matches.concat(otherMatches);
    }
  };

  // src/compiler/syntax-nodes/qualifier-asn.ts
  var QualifierAsn = class extends AbstractAstNode {
    constructor(value, fieldId, scope) {
      super();
      this.value = value;
      this.fieldId = fieldId;
      this.scope = scope;
    }
    compileErrors = [];
    compile() {
      const s = this.compileAsParameter();
      return s === "" ? "" : `${s}.`;
    }
    compileAsParameter() {
      this.compileErrors = [];
      return this.value.compile();
    }
    symbolType() {
      return this.value.symbolType();
    }
    toString() {
      return `${this.value}.`;
    }
  };

  // src/compiler/syntax-nodes/ast-helpers.ts
  function isAstNode(n) {
    return !!n && "compile" in n && "fieldId" in n && "indent" in n;
  }
  function isAstQualifiedNode(n) {
    return !!n && "qualifier" in n;
  }
  function isAstQualifierNode(n) {
    return n instanceof QualifierAsn;
  }
  function isAstCollectionNode(n) {
    return !!n && "items" in n;
  }
  function isAstIdNode(n) {
    return !!n && "id" in n;
  }
  function isRootNode(n) {
    return !!n && "isRoot" in n;
  }
  function isEmptyNode(n) {
    return n instanceof EmptyAsn;
  }
  function isEnumValuesAsn(n) {
    return n instanceof EnumValuesAsn;
  }
  var TypeHolder = class {
    constructor(symbolType, ofTypes) {
      this.symbolType = symbolType;
      this.ofTypes = ofTypes;
    }
    languageSpecificName(_language) {
      return this.name;
    }
    isAssignableFrom(otherType) {
      return this.symbolType.isAssignableFrom(otherType);
    }
    typeOptions = noTypeOptions;
    name = "TypeHolder";
    initialValue = "";
    toString() {
      return this.name;
    }
  };
  function flatten(p) {
    if (p instanceof ClassType && p.typeOptions.isIndexable && p.ofTypes.length === 1) {
      return new TypeHolder(p, [flatten(p.ofTypes[0])]);
    }
    if (p instanceof ClassType && p.typeOptions.isIndexable && p.ofTypes.length === 2) {
      return new TypeHolder(p, [flatten(p.ofTypes[0]), flatten(p.ofTypes[1])]);
    }
    if (p instanceof TupleType) {
      let flattened = [];
      for (const t of p.ofTypes) {
        flattened = flattened.concat(flatten(t));
      }
      return new TypeHolder(p, flattened);
    }
    if (p instanceof FunctionType) {
      let flattened = [];
      for (const t of p.parameterTypes) {
        flattened = flattened.concat(flatten(t));
      }
      flattened = flattened.concat(flatten(p.returnType));
      return new TypeHolder(p, flattened);
    }
    if (p instanceof StringType) {
      return new TypeHolder(p, [p]);
    }
    return p;
  }
  function containsGenericType(type) {
    if (type instanceof GenericParameterType) {
      return true;
    }
    if (type instanceof TupleType) {
      return type.ofTypes.some((t) => containsGenericType(t));
    }
    if (type instanceof ClassType) {
      if (isClass(type.scope)) {
        return type.scope.ofTypes.some((t) => containsGenericType(t));
      }
    }
    if (type instanceof FunctionType) {
      if (containsGenericType(type.returnType)) {
        return true;
      }
      return type.parameterTypes.some((t) => containsGenericType(t));
    }
    if (type instanceof ProcedureType) {
      return type.parameterTypes.some((t) => containsGenericType(t));
    }
    return false;
  }
  function generateType(type, matches, depth = 0) {
    depth++;
    if (depth > 20) {
      return type;
    }
    if (isReifyableSymbolType(type)) {
      return type.reify(type.ofTypes.map((t) => generateType(t, matches, depth)));
    }
    if (type instanceof GenericParameterType) {
      let match3 = matches.get(type.id);
      if (match3 instanceof TypeHolder) {
        match3 = generateType(match3.symbolType, matches, depth);
      }
      match3 = match3 ?? type;
      if (match3 instanceof GenericParameterType) {
        let newConstraint = void 0;
        if (match3.constraint) {
          newConstraint = generateType(match3.constraint, matches, depth);
        }
        if (newConstraint) {
          match3 = new GenericParameterType(match3.id, newConstraint);
        }
      }
      return match3;
    }
    if (type instanceof TupleType) {
      return new TupleType(type.ofTypes.map((t) => generateType(t, matches, depth)));
    }
    if (type instanceof FunctionType) {
      return new FunctionType(
        type.parameterNames,
        type.parameterTypes.map((t) => generateType(t, matches, depth)),
        generateType(type.returnType, matches),
        type.isExtension,
        type.isPure,
        type.isAsync,
        type.deprecated
      );
    }
    if (type instanceof ProcedureType) {
      return new ProcedureType(
        type.parameterNames,
        type.parameterTypes.map((t) => generateType(t, matches, depth)),
        type.isExtension,
        type.isAsync,
        type.deprecated
      );
    }
    return type;
  }
  function minOf(a1, a2) {
    return a1.length < a2.length ? a1.length : a2.length;
  }
  function match2(flattened, pTypes, matches) {
    const minLength = minOf(flattened, pTypes);
    for (let i = 0; i < minLength; i++) {
      const t = flattened[i];
      const st = pTypes[i];
      if (t instanceof GenericParameterType) {
        if (!matches.has(t.id)) {
          if (!t.constraint || t.constraint.isAssignableFrom(st)) {
            matches.set(t.id, st);
          }
        }
      }
      if (t instanceof TypeHolder && st instanceof TypeHolder) {
        match2(t.ofTypes, st.ofTypes, matches);
      }
    }
  }
  function matchGenericTypes(type, parameters) {
    const matches = /* @__PURE__ */ new Map();
    const flattened = type.parameterTypes.map((n) => flatten(n));
    const pTypes = parameters.map((p) => flatten(p.symbolType()));
    match2(flattened, pTypes, matches);
    return matches;
  }
  function matchParametersAndTypes(id, methodSymbolType, parameters, compileErrors, location, scope) {
    let parameterTypes = methodSymbolType.parameterTypes;
    if (parameterTypes.some((pt) => containsGenericType(pt))) {
      const matches = matchGenericTypes(methodSymbolType, parameters);
      parameterTypes = parameterTypes.map((pt) => generateType(pt, matches));
    }
    mustMatchParameters(
      id,
      parameters,
      parameterTypes,
      parameterNamesWithTypes(methodSymbolType, scope, parameterTypes).join(", "),
      methodSymbolType.isExtension,
      compileErrors,
      location,
      scope
    );
  }
  var opMap = /* @__PURE__ */ new Map([
    [0 /* Add */, "+"],
    [1 /* Minus */, "-"],
    [2 /* Not */, "not"],
    [3 /* Multiply */, "*"],
    [4 /* And */, "and"],
    [5 /* Equals */, "is"],
    [6 /* LT */, "<"],
    [7 /* GT */, ">"],
    [8 /* GTE */, ">="],
    [9 /* LTE */, "<="],
    [10 /* Div */, "div"],
    [11 /* Mod */, "mod"],
    [12 /* Divide */, "/"],
    [13 /* NotEquals */, "isnt"],
    [14 /* Or */, "or"]
  ]);
  function getSuperClasses(cf) {
    return cf.getInheritanceItems();
  }

  // src/compiler/syntax-nodes/globals/tuple-asn.ts
  var TupleAsn = class {
    constructor(type, scope) {
      this.type = type;
      this.scope = scope;
    }
    parseId(id) {
      if (id.startsWith("item_") && id.length >= 6) {
        const index = id.slice(5);
        const i = parseInt(index);
        if (!isNaN(i) && i < this.type.ofTypes.length) {
          return [true, i];
        }
      }
      return [false, 0];
    }
    typeToSymbol(id, t) {
      return {
        symbolId: id,
        symbolType: () => t,
        symbolScope: 5 /* member */,
        isProperty: true,
        symbolIsType: true
      };
    }
    resolveOwnSymbol(id) {
      const [ok, index] = this.parseId(id);
      if (ok) {
        return this.typeToSymbol(id, this.type.ofTypes[index]);
      }
      return new UnknownSymbol(id);
    }
    resolveSymbol(id, caseSensitive, _initialScope) {
      const symbol = this.resolveOwnSymbol(id);
      if (symbol instanceof UnknownSymbol) {
        return this.getParentScope().resolveSymbol(id, caseSensitive, this);
      }
      return symbol;
    }
    getParentScope() {
      return this.scope;
    }
    symbolMatches(id, all, _initialScope) {
      const symbols = this.type.ofTypes.map((t, i) => this.typeToSymbol(`item_${i}`, t));
      const matches = symbolMatches(id, all, symbols);
      return matches;
    }
  };

  // src/compiler/syntax-nodes/lambda-asn.ts
  var LambdaAsn = class extends AbstractAstNode {
    constructor(signature, body, fieldId) {
      super();
      this.signature = signature;
      this.body = body;
      this.fieldId = fieldId;
    }
    compile() {
      this.compileErrors = [];
      return `async (${this.signature.compile()}) => ${this.body.compile()}`;
    }
    symbolType() {
      const [pn, pt] = this.signature.parameterNamesAndTypes();
      return new FunctionType(pn, pt, this.body.symbolType(), false, true, true);
    }
    toString() {
      return `lambda ${this.signature} => ${this.body}`;
    }
  };

  // src/compiler/syntax-nodes/statements/call-asn.ts
  var CallAsn = class extends BreakpointAsn {
    constructor(fieldId, scope) {
      super(fieldId, scope);
    }
    proc = EmptyAsn.Instance;
    args = EmptyAsn.Instance;
    wrapParameters(callParameters) {
      const wrappedInParameters = [];
      const passedParameters = [];
      for (let i = 0; i < callParameters.length; i++) {
        const p = callParameters[i];
        const pName = p.compile();
        passedParameters.push(pName);
      }
      return [wrappedInParameters, passedParameters];
    }
    compile() {
      this.compileErrors = [];
      const astNode = this.proc;
      const id = isAstIdNode(astNode) ? astNode.id : "";
      const [updatedQualifier, currentScope] = updateScopeAndQualifier(astNode, this);
      let qualifier = updatedQualifier;
      const procSymbol = currentScope.resolveSymbol(id, true, this);
      mustBeKnownSymbol(
        procSymbol,
        currentScope,
        getQualifierId(qualifier),
        qualifier.symbolType(),
        this.compileErrors,
        this.fieldId,
        this.scope
      );
      mustBeProcedure(
        procSymbol.symbolId,
        procSymbol.symbolType(),
        procSymbol.symbolScope,
        this.compileErrors,
        this.fieldId
      );
      if (isMemberOnFieldsClass(procSymbol, this)) {
        mustbeValidQualifier(qualifier, this.compileErrors, this.fieldId);
      } else {
        mustBePublicMember(procSymbol, this.compileErrors, this.fieldId);
      }
      const procSymbolType = procSymbol.symbolType();
      const parameterList = this.args;
      if (isAstCollectionNode(parameterList)) {
        let callParameters = parameterList.items;
        let isAsync = false;
        if (procSymbolType instanceof ProcedureType) {
          mustCallExtensionViaQualifier(procSymbolType, qualifier, this.compileErrors, this.fieldId);
          mustNotCallNonExtensionViaQualifier(
            procSymbolType,
            procSymbol.symbolId,
            qualifier,
            currentScope,
            this.compileErrors,
            this.fieldId,
            this.scope
          );
          mustCallMemberViaQualifier(
            id,
            procSymbolType,
            currentScope,
            this.compileErrors,
            this.fieldId
          );
          if (procSymbolType.isExtension && qualifier instanceof QualifierAsn) {
            callParameters = [qualifier.value].concat(callParameters);
            qualifier = EmptyAsn.Instance;
          }
          matchParametersAndTypes(
            id,
            procSymbolType,
            callParameters,
            this.compileErrors,
            this.fieldId,
            this.scope
          );
          checkForDeprecation(procSymbolType, this, this.compileErrors, this.fieldId);
          isAsync = procSymbolType.isAsync;
        }
        const [wrappedInParameters, passedParameters] = this.wrapParameters(callParameters);
        const parms = passedParameters.join(", ");
        const prefix = !isEmptyNode(qualifier) ? `${qualifier.compile()}` : scopePrefix(procSymbol, void 0, this.compileErrors, this, this.fieldId);
        const async = isAsync ? "await " : "";
        let wrappedInParms = "";
        if (wrappedInParameters.length > 0) {
          wrappedInParms = `${this.indent()}${wrappedInParameters.join("; ")};
`;
        }
        const dot = prefix.endsWith(".") || prefix === "" ? "" : ".";
        getGlobalScope(this.scope).addCompileErrors(this.compileErrors);
        return `${wrappedInParms}${this.indent()}${this.breakPoint(this.debugSymbols())}${async}${prefix}${dot}${id}(${parms});`;
      }
      return "";
    }
    resolveSymbol(id, caseSensitive, initialScope) {
      if (isAstCollectionNode(this.args)) {
        const items = this.args.items;
        const last = items.length > 0 ? items[items.length - 1] : new UnknownSymbol();
        if (last instanceof LambdaAsn) {
          const ss = last.signature.resolveSymbol(id, caseSensitive, initialScope);
          if (!(ss instanceof UnknownSymbol)) {
            return ss;
          }
        }
      }
      return super.resolveSymbol(id, caseSensitive, this);
    }
    symbolMatches(id, all, initialScope) {
      const matches = super.symbolMatches(id, all, this);
      let localMatches = [];
      if (isAstCollectionNode(this.args)) {
        const items = this.args.items;
        const last = items.length > 0 ? items[items.length - 1] : new UnknownSymbol();
        if (last instanceof LambdaAsn) {
          localMatches = last.signature.symbolMatches(id, all, initialScope);
        }
      }
      return localMatches.concat(matches);
    }
  };

  // src/compiler/symbols/symbol-helpers.ts
  function isClass(s) {
    return !!s && "isClass" in s;
  }
  function isGenericClass(s) {
    return isClass(s) && s.ofTypes?.length > 0;
  }
  function isScope(s) {
    return !!s && "resolveSymbol" in s && "getParentScope" in s;
  }
  function isSymbol(s) {
    return !!s && "symbolId" in s && "symbolType" in s;
  }
  function isReifyableSymbolType(s) {
    return !!s && "reify" in s;
  }
  function isDefinition(s) {
    return !!s && "isLocalConstant" in s && "isVariable" in s;
  }
  function isGlobalConstant(s) {
    return !!s && "isGlobalConstant" in s;
  }
  function isProperty(s) {
    return !!s && "isProperty" in s;
  }
  function isMember(s) {
    return !!s && "isMember" in s;
  }
  function isEnum(s) {
    return s instanceof EnumAsn;
  }
  function isCall(s) {
    return s instanceof CallAsn;
  }
  function isFunctionType(s) {
    return s instanceof FunctionType;
  }
  function isInsideClass(scope) {
    return getClassScope(scope) !== NullScope.Instance;
  }
  function isPublicMember(s) {
    return isMember(s) && !s.private;
  }
  function isEnumValue(s) {
    return s?.symbolType() instanceof EnumValueType;
  }
  function isParameter(s) {
    return s?.symbolScope === 4 /* parameter */;
  }
  function isVariable(s) {
    return isDefinition(s) && s.isVariable();
  }
  function isLocalConstant(s) {
    return isDefinition(s) && s.isLocalConstant();
  }
  function isKnownType(s) {
    return !(s instanceof UnknownType);
  }
  function isProcedure(s) {
    return s.symbolType() instanceof ProcedureType;
  }
  function isFunction(s) {
    return isSymbol(s) && s.symbolType() instanceof FunctionType;
  }
  function isPureFunction(s) {
    if (isFunction(s)) {
      const ft = s.symbolType();
      return ft instanceof FunctionType && ft.isPure;
    }
    return false;
  }
  function isSystemFunction(s) {
    if (isFunction(s)) {
      const ft = s.symbolType();
      return ft instanceof FunctionType && !ft.isPure;
    }
    return false;
  }
  function isTypeSymbol(s) {
    return s?.symbolIsType || false;
  }
  function isAbstractClass(s) {
    return isClass(s) && s.isAbstract;
  }
  function isNotInheritableClass(s) {
    return isClass(s) && s.isNotInheritable;
  }
  function isConcreteTypeName(s) {
    return isTypeSymbol(s) && !isAbstractClass(s);
  }
  function isAbstractTypeName(s) {
    return isTypeSymbol(s) && isAbstractClass(s) && !isNotInheritableClass(s);
  }
  function isNotInheritableTypeName(s) {
    return isTypeSymbol(s) && isAbstractClass(s) && isNotInheritableClass(s);
  }
  function isId(f) {
    return isGlobalConstant(f) || isLocalConstant(f) || isVariable(f) || isParameter(f) || isProperty(f) || isEnumValue(f);
  }
  function isNotFuncOrProcOrType(s) {
    const st = s.symbolType();
    return !(st instanceof FunctionType || st instanceof ProcedureType || firstCharIsUpper(s.symbolId));
  }
  function isPossibleExtensionForType(actualType, procType) {
    if (procType.parameterTypes.length > 0) {
      const firstParmType = procType.parameterTypes[0];
      return matchType(actualType, firstParmType);
    }
    return false;
  }
  function isMemberOnFieldsClass(s, scope) {
    const currentClass = getClassScope(scope);
    const matchingMember = currentClass.resolveSymbol(s.symbolId, true, scope);
    return isMember(s) && isMember(matchingMember) && s.getClass() === matchingMember.getClass();
  }
  function scopePrefix(symbol, qualifier, _compileErors, scope, _location) {
    if (symbol.symbolScope === 2 /* stdlib */) {
      return `_stdlib.`;
    }
    if (isGlobalConstant(symbol) && symbol.symbolScope === 3 /* program */) {
      return isGlobalConstant(scope) ? "this." : "global.";
    }
    if (symbol.symbolScope === 5 /* member */) {
      return isAstIdNode(qualifier) ? `${qualifier.id}.` : `this.`;
    }
    if (isFunction(symbol) && symbol.symbolScope === 3 /* program */) {
      return "global.";
    }
    return "";
  }
  function internalUpdateScopeAndQualifier(qualifierScope, currentScope, _value, qualifier) {
    if (qualifierScope instanceof ClassType) {
      const classSymbol = currentScope.resolveSymbol(qualifierScope.className, true, currentScope);
      currentScope = isScope(classSymbol) ? classSymbol : currentScope;
      if (isClass(currentScope)) {
        if (isClass(qualifierScope.scope)) {
          currentScope = currentScope.updateOfTypes(qualifierScope.scope.ofTypes);
        }
      }
    } else if (qualifierScope instanceof TupleType) {
      currentScope = new TupleAsn(qualifierScope, currentScope);
    } else if (!isEmptyNode(qualifier)) {
      currentScope = getGlobalScope(currentScope).libraryScope;
    } else {
      currentScope = currentScope.getParentScope();
    }
    return [qualifier, currentScope];
  }
  function updateScopeAndQualifier(rootNode, currentScope) {
    const qualifier = isAstQualifiedNode(rootNode) ? rootNode.qualifier : EmptyAsn.Instance;
    const qualifierScope = qualifier.symbolType();
    const value = qualifier.value;
    return internalUpdateScopeAndQualifier(qualifierScope, currentScope, value, qualifier);
  }
  function getGlobalScope(start) {
    if (start instanceof NullScope) {
      throw new ElanCompilerError("Global scope not found");
    }
    if (isRootNode(start)) {
      return start;
    }
    return getGlobalScope(start.getParentScope());
  }
  function getClassScope(start) {
    if (start instanceof NullScope) {
      return start;
    }
    if (isClass(start)) {
      return start;
    }
    return getClassScope(start.getParentScope());
  }
  function matchType(actualType, paramType) {
    if (paramType.name === actualType.name) {
      return true;
    }
    if (paramType instanceof GenericParameterType) {
      return true;
    }
    if (paramType instanceof ClassType) {
      return paramType.isAssignableFrom(actualType);
    }
    return false;
  }
  function firstCharIsUpper(s) {
    const firstChar = s[0] ?? "";
    return firstChar.toUpperCase() === firstChar;
  }
  function matchingSymbolsWithQualifier(propId, qualId, scope) {
    const qual = scope.resolveSymbol(qualId, true, scope);
    if (qual instanceof UnknownSymbol) {
      return [];
    }
    let qualSt = qual.symbolType();
    if (isFunctionType(qualSt)) {
      qualSt = qualSt.returnType;
    }
    let qualifiedSymbols = [];
    if (qualSt instanceof ClassType) {
      const cls = getGlobalScope(scope).resolveSymbol(qualSt.className, true, scope);
      if (isClass(cls)) {
        qualifiedSymbols = cls.symbolMatches(propId, !propId, NullScope.Instance).filter((s) => isPublicMember(s));
      }
    }
    if (qualSt instanceof EnumType) {
      const en = getGlobalScope(scope).resolveSymbol(qualSt.name, true, scope);
      if (isEnum(en)) {
        qualifiedSymbols = en.symbolMatches(propId, !propId, NullScope.Instance);
      }
    }
    if (qualSt instanceof TupleType) {
      qualifiedSymbols = new TupleAsn(qualSt, scope).symbolMatches(
        propId,
        !propId,
        NullScope.Instance
      );
    }
    const allExtensions = getGlobalScope(scope).libraryScope.symbolMatches(propId, !propId, NullScope.Instance).filter((s) => {
      const st = s.symbolType();
      return (st instanceof ProcedureType || st instanceof FunctionType) && st.isExtension && isPossibleExtensionForType(qualSt, st);
    });
    return qualifiedSymbols.concat(allExtensions);
  }
  function orderSymbol(s1, s2) {
    return s1.symbolId.localeCompare(s2.symbolId);
  }
  function fixCase(id, s) {
    let sid = s.symbolId;
    if (!hasAnyUpperCase(id)) {
      id = id.toUpperCase();
      sid = sid.toUpperCase();
    }
    return [id, sid];
  }
  function matchStart(i, s) {
    const [id, sid] = fixCase(i, s);
    return sid.startsWith(id);
  }
  function hasAnyUpperCase(id) {
    return Array.from(id).filter((c) => c.toUpperCase() === c).length > 0;
  }
  function matchIncludes(i, s) {
    const [id, sid] = fixCase(i, s);
    return sid.includes(id);
  }
  function symbolMatches(id, all, symbols) {
    if (all) {
      return symbols;
    }
    const sw = symbols.filter((s) => matchStart(id, s));
    let inc = [];
    const limit = 1;
    if (id.length >= limit) {
      inc = symbols.filter((s) => !sw.includes(s)).filter((s) => matchIncludes(id, s));
    }
    return sw.concat(inc);
  }
  function symbolScopeToFriendlyName(ss) {
    switch (ss) {
      case 5 /* member */:
        return "property";
      case 4 /* parameter */:
        return "parameter";
      default:
        return "identifier";
    }
  }
  function parameterNamesWithTypes(st, scope, actualTypes) {
    if (st instanceof ProcedureType || st instanceof FunctionType) {
      const parameterNames2 = st.isExtension ? st.parameterNames.slice(1) : st.parameterNames;
      let parameterTypes = actualTypes ? actualTypes : st.parameterTypes;
      parameterTypes = st.isExtension ? parameterTypes.slice(1) : parameterTypes;
      const language = getGlobalScope(scope).language;
      const descriptions = parameterNames2.map(
        (n, i) => `${n} (${parameterTypes[i].languageSpecificName(language)})`
      );
      return descriptions;
    }
    return [];
  }
  function parameterNames(st) {
    if (st instanceof ProcedureType || st instanceof FunctionType) {
      const parameterNames2 = st.isExtension ? st.parameterNames.slice(1) : st.parameterNames;
      const descriptions = parameterNames2.map((n) => `${n}`);
      return descriptions;
    }
    return [];
  }
  function allScopedSymbols(scope, initialScope) {
    return scope.symbolMatches("", true, initialScope).filter((s) => isNotFuncOrProcOrType(s));
  }
  function allPropertiesInScope(scope) {
    const all = scope.symbolMatches("", true, scope);
    return all.filter((s) => isProperty(s));
  }
  function match(id1, id2, caseSensitive) {
    return caseSensitive ? id1 === id2 : id1.toUpperCase() === id2.toUpperCase();
  }
  function getClassType(className, rootNode) {
    const cls = rootNode.resolveSymbol(className, false, rootNode);
    if (isClass(cls)) {
      const st = cls.symbolType();
      return st.subType;
    }
    return void 0;
  }
  function implementsAbstractMethodOnClassOrInterface(nameField, classFrame) {
    const methodName = nameField.renderAsElanSource();
    const className = classFrame.name.renderAsElanSource();
    const rootNode = classFrame.getFile().getAst(true);
    const cls = rootNode.resolveSymbol(className, false, rootNode);
    let superCls = "";
    if (isClass(cls)) {
      const method = cls.resolveSymbol(methodName, false, cls);
      if (!(method instanceof UnknownSymbol) && cls instanceof ClassAsn) {
        const abstractClasses = getAllAbstractClasses(cls, [], cls);
        const interfaces = getAllInterfaces(cls, [], cls);
        const all = abstractClasses.concat(interfaces);
        for (const a of all) {
          if (!(a.resolveOwnSymbol(methodName, true) instanceof UnknownSymbol)) {
            superCls = a.getName();
          }
        }
      }
    }
    const abstractClass = getClassType(superCls, rootNode) === 1 /* abstract */;
    return [superCls, abstractClass];
  }
  function getSuperClassSymbols(superClasses, filter, scope) {
    const nodes = superClasses.filter((i) => isAstIdNode(i));
    const symbols = nodes.map((n) => getGlobalScope(scope).resolveSymbol(n.id, true, scope)).filter(filter);
    return symbols;
  }
  function seenTwice(name, seenNames) {
    return seenNames.filter((s) => s === name).length > 1;
  }
  function getAllClasses(cf, seenNames, filter, scope) {
    const superClasses = getSuperClasses(cf);
    const symbols = getSuperClassSymbols(
      superClasses,
      (n) => n instanceof ClassAsn && !seenTwice(n.symbolId, seenNames),
      scope
    );
    let allSymbols = symbols;
    seenNames.push(cf.symbolId);
    for (const s of symbols) {
      allSymbols = allSymbols.concat(getAllClasses(s, seenNames, filter, scope));
    }
    return allSymbols.filter(filter);
  }
  function getAllInterfaces(cf, seenNames, scope) {
    return getAllClasses(cf, seenNames, (s) => s.isInterface, scope);
  }
  function getAllAbstractClasses(cf, seenNames, scope) {
    return getAllClasses(cf, seenNames, (s) => s.isAbstract && !s.isInterface, scope);
  }

  // src/ide/frames/symbol-completion-helpers.ts
  var KeywordCompletion = class _KeywordCompletion {
    constructor(keyword, spaceAfter, dotAfter, openBracketAfter) {
      this.keyword = keyword;
      this.spaceAfter = spaceAfter;
      this.dotAfter = dotAfter;
      this.openBracketAfter = openBracketAfter;
    }
    static map = /* @__PURE__ */ new Map();
    static create(keyword, spaceAfter = true, dotAfter = false, openBracketAfter = false) {
      if (!this.map.has(keyword)) {
        this.map.set(keyword, new _KeywordCompletion(keyword, spaceAfter, dotAfter, openBracketAfter));
      }
      return this.map.get(keyword);
    }
    static reset() {
      this.map.clear();
    }
  };
  var SymbolCompletionSpec = class {
    constructor(toMatch, tokenTypes, keywords, context) {
      this.toMatch = toMatch;
      this.tokenTypes = tokenTypes;
      this.keywords = keywords;
      this.context = context;
    }
  };
  function matchingSymbols(spec, scope) {
    if (spec.context) {
      return matchingSymbolsWithQualifier(spec.toMatch, spec.context, scope);
    }
    const allNotExtensions = scope.symbolMatches(spec.toMatch, !spec.toMatch, scope).filter((s) => {
      const st = s.symbolType();
      let isCall2 = false;
      let isExtension = false;
      if (st instanceof ProcedureType || st instanceof FunctionType) {
        isCall2 = true;
        isExtension = st.isExtension;
      }
      return !isCall2 || isCall2 && !isExtension;
    });
    return allNotExtensions;
  }
  function filteredSymbols(spec, scope) {
    const matches = matchingSymbols(spec, scope);
    const filters = filtersForTokenType(spec.tokenTypes);
    const filtered = ensureUnique(filterSymbols(matches, filters));
    const startsWith = filtered.filter((s) => s.symbolId.toUpperCase().startsWith(spec.toMatch.toUpperCase())).sort(orderSymbol);
    const includes = filtered.filter((s) => !startsWith.includes(s)).sort(orderSymbol);
    return startsWith.concat(includes);
  }
  function filterSymbols(matches, filters) {
    let filtered = [];
    for (const f of filters) {
      filtered = filtered.concat(matches.filter(f));
    }
    return filtered.filter((e) => !e.symbolId.startsWith("_"));
  }
  function ensureUnique(symbols) {
    const uniqueNames = Array.from(new Set(symbols.map((s) => s.symbolId)));
    return uniqueNames.map((n) => symbols.find((s) => s.symbolId === n));
  }
  function filterForTokenType(tt) {
    switch (tt) {
      case 11 /* method_function */:
        return (s) => isPureFunction(s);
      case 10 /* method_procedure */:
        return (s) => isProcedure(s);
      case 12 /* method_system */:
        return (s) => isSystemFunction(s);
      case 6 /* type_concrete */:
        return isConcreteTypeName;
      case 7 /* type_abstract */:
        return isAbstractTypeName;
      case 8 /* type_enum */:
        return isEnum;
      case 9 /* type_notInheritable */:
        return isNotInheritableTypeName;
      case 4 /* id_constant */:
        return isGlobalConstant;
      case 0 /* id_let */:
        return isLocalConstant;
      case 1 /* id_variable */:
        return isVariable;
      case 3 /* id_parameter_regular */:
        return isParameter;
      case 2 /* id_property */:
        return isProperty;
      case 5 /* id_enumValue */:
        return isEnumValue;
    }
  }
  function filtersForTokenType(tokenTypes) {
    const filters = [];
    for (const f of tokenTypes) {
      filters.push(filterForTokenType(f));
    }
    return filters;
  }
  function getFilteredSymbols(spec, ast, htmlId) {
    const scope = ast?.getScopeById(htmlId) ?? NullScope.Instance;
    let symbols = filteredSymbols(spec, scope);
    if (isInsideClass(scope)) {
      if (thisKeyword.startsWith(spec.toMatch)) {
        const allProperties = allPropertiesInScope(getClassScope(scope)).sort(orderSymbol);
        symbols = symbols.filter((s) => !allProperties.includes(s)).concat(allProperties);
      } else if (spec.context === thisKeyword) {
        const newSpec = new SymbolCompletionSpec(
          spec.toMatch,
          /* @__PURE__ */ new Set([2 /* id_property */]),
          /* @__PURE__ */ new Set(),
          ""
        );
        symbols = filteredSymbols(newSpec, scope);
      }
    }
    return symbols;
  }
  function removeIfSingleFullMatch(symbols, id) {
    if (symbols.length === 1 && symbols[0].symbolId === id) {
      return [];
    } else {
      return symbols;
    }
  }

  // src/ide/frames/frame-helpers.ts
  function isCollapsible(f) {
    return !!f && "isCollapsible" in f;
  }
  function isFrame(f) {
    return !!f && "isFrame" in f;
  }
  function isFrameWithStatements(f) {
    return !!f && "isFrameWithStatements" in f;
  }
  function isParent(f) {
    return !!f && "isParent" in f;
  }
  function isConstructor(f) {
    return !!f && "isConstructor" in f;
  }
  function isSelector(f) {
    return !!f && "isSelector" in f;
  }
  function isGlobal(f) {
    return !!f && "isGlobal" in f;
  }
  function singleIndent() {
    return "  ";
  }
  function expandCollapseAll(file) {
    const map = file.getMap();
    const collapsible = [...map.values()].filter((s) => isCollapsible(s)).map((s) => s);
    const firstCollapsibleGlobal = collapsible.filter((s) => isGlobal(s))[0];
    let collapse = true;
    if (firstCollapsibleGlobal && firstCollapsibleGlobal.isCollapsed()) {
      collapse = false;
    }
    for (const c of collapsible) {
      if (collapse) {
        c.collapse();
      } else {
        c.expand();
      }
    }
    const globals = [...map.values()].filter((s) => isGlobal(s));
    const selectedGlobals = globals.filter((s) => s.isSelected());
    if (selectedGlobals.length === 0) {
      file.getFirstChild().select(true, false);
    }
  }
  function escapeHtmlChars(str) {
    return str.replaceAll(/</g, "&lt;").replaceAll(/>/g, "&gt;");
  }
  function helper_pastePopUp(loc) {
    let popup = "";
    if (isFrame(loc) && loc.pasteError) {
      popup = `<div class="context-menu"><div>${loc.pasteError}</div></div>`;
      loc.pasteError = "";
    }
    return popup;
  }
  function helper_compileMsgAsHtmlNew(file, loc) {
    let msg = "";
    let link = "";
    let help = "";
    let compileErrors = [];
    if (loc.readParseStatus() === 3 /* valid */) {
      compileErrors = file.getAst(false)?.getCompileErrorsFor(loc.getHtmlId()) ?? [];
    }
    const n = compileErrors.length;
    if (n > 0) {
      const first = compileErrors[0];
      const highest = compileErrors.reduce(
        (prev, curr) => curr.priority < prev.priority ? curr : prev,
        first
      );
      msg = highest.message;
      link = highest.link ?? "";
    }
    let cls = "";
    const compile = helper_compileStatusAsDisplayStatus(loc.readCompileStatus());
    if (compile === 0 /* error */ || compile === 1 /* warning */ || compile === 2 /* advisory */) {
      cls = DisplayColour[compile];
    }
    if (link) {
      const active = loc.helpActive ? ` class="active"` : "";
      loc.helpActive = false;
      help = `<el-help title="Click to open Help for this error"><a href="documentation/${link}" target="help-iframe" tabindex="-1"${active}>?</a></el-help>`;
    }
    const popUp = helper_pastePopUp(loc);
    const toDisplay = escapeHtmlChars(msg);
    return cls === "" ? `<el-msg></el-msg>${popUp}` : ` <el-msg class="${cls}">${toDisplay}${help}</el-msg>${popUp}`;
  }
  function helper_deriveCompileStatusFromErrors(errors) {
    let result = 0 /* error */;
    if (errors.length === 0) {
      result = 3 /* ok */;
    } else {
      const hasErrors = errors.some((e) => e.severity === 0 /* error */);
      const hasWarnings = errors.some((e) => e.severity === 1 /* warning */);
      if (hasErrors) {
        return 0 /* error */;
      }
      if (hasWarnings) {
        return 1 /* unknown_symbol */;
      }
      return 2 /* advisory */;
    }
    return result;
  }
  function helper_CompileOrParseAsDisplayStatus(loc) {
    let status = helper_parseStatusAsDisplayColour(loc.readParseStatus());
    if (status === 3 /* ok */) {
      const compile = helper_compileStatusAsDisplayStatus(loc.readCompileStatus());
      if (compile !== 4 /* none */) {
        status = compile;
      }
    }
    return status;
  }
  function helper_parseStatusAsDisplayColour(ps) {
    let overall = 4 /* none */;
    if (ps === 3 /* valid */) {
      overall = 3 /* ok */;
    } else if (ps === 2 /* incomplete */) {
      overall = 1 /* warning */;
    } else if (ps === 0 /* invalid */) {
      overall = 1 /* warning */;
    }
    return overall;
  }
  function helper_compileStatusAsDisplayStatus(cs) {
    switch (cs) {
      case 3 /* ok */:
        return 3 /* ok */;
      case 2 /* advisory */:
        return 2 /* advisory */;
      case 1 /* unknown_symbol */:
        return 1 /* warning */;
      case 0 /* error */:
        return 0 /* error */;
      default:
        return 4 /* none */;
    }
  }
  function helper_testStatusAsDisplayStatus(ts) {
    let overall = 4 /* none */;
    if (ts === 4 /* pass */) {
      overall = 3 /* ok */;
    } else if (ts === 3 /* running */ || ts === 2 /* ignored */) {
      overall = 1 /* warning */;
    } else if (ts === 1 /* fail */ || ts === 0 /* error */) {
      overall = 0 /* error */;
    }
    return overall;
  }
  function currentParameterIndex(text) {
    if (text) {
      if (text.includes(",")) {
        const parameters = text.split(",");
        const count = parameters.length - 1;
        const startedInput = !!parameters[count].trim();
        return startedInput ? count + 1 : count;
      }
      return 1;
    }
    return 0;
  }
  function addPrivateToggleToContextMenu(member, menu) {
    if (member.isPrivate) {
      menu.set("makePublic", [
        "make public &nbsp;&nbsp; <span class='kb'>Ctrl+p</span>",
        member.makePublic
      ]);
    } else {
      menu.set("makePrivate", ["make private <span class='kb'>Ctrl+p</span>", member.makePrivate]);
    }
  }
  function addDeleteToContextMenu(member, menu) {
    menu.set("delete", ["delete <span class='kb'>Ctrl+Backspace</span>", member.deleteSelected]);
  }
  function togglePrivatePublic(member) {
    if (member.isPrivate) {
      return member.makePublic();
    } else {
      return member.makePrivate();
    }
  }
  function selfTypeAsHtml(member) {
    const typeNode = member.getParent().name.getRootNode();
    return typeNode.renderAsHtml();
  }
  function modifierAsElanSource(member) {
    return member.isPrivate ? `${privateKeyword} ` : "";
  }
  function removeHtmlTagsAndEscChars(html) {
    let result = html;
    result = result.replace(/<script.*?<\/el-place>/gm, "");
    result = result.replace(/<el-place.*?<\/el-place>/gm, "");
    result = result.replace(/<el-compl.*?<\/el-compl>/gm, "");
    result = result.replace(/<el-msg.*?<\/el-msg>/gm, "");
    result = result.replace(/<el-help.*?<\/el-help>/gm, "");
    result = result.replace(/<el-fr>.*?<\/el-fr>/gm, "");
    result = result.replace(/<el-expand>.*?<\/el-expand>/gm, "");
    result = result.replace(/<br>/gm, "\n");
    while (result.match(/<[[a-z\/][^>]*>/gm)) {
      result = result.replace(/<[^>]*>/gm, "");
    }
    result = result.replace(/&nbsp;/gm, " ");
    result = result.replace(/&gt;/gm, ">");
    result = result.replace(/&lt;/gm, "<");
    return result;
  }

  // src/ide/frames/parse-nodes/abstract-parse-node.ts
  var AbstractParseNode = class {
    constructor(file) {
      this.file = file;
    }
    status = 1 /* empty */;
    matchedText = "";
    completionWhenEmpty = "";
    remainingText = "";
    message = "";
    activeNodeForSymbolCompl = this;
    //'done' means that parseNode is valid and that no more text may be taken
    //Most parse nodes are never 'done'. Only ones that can return true are:
    //SpaceNode and sub-classes of FixedTextNode or of AbstractSequence
    _done = false;
    setSyntaxCompletionWhenEmpty(ph) {
      this.completionWhenEmpty = ph;
    }
    getSyntaxCompletionAsHtml() {
      return this.matchedText === "" ? `${this.completionWhenEmpty}` : "";
    }
    renderAsElanSource() {
      return this.matchedText.trim();
    }
    renderAsExport() {
      return this.isValid() ? removeHtmlTagsAndEscChars(this.renderAsHtml()) : this.matchedText;
    }
    renderAsHtml() {
      return this.renderAsElanSource();
    }
    set(status, matched, remaining) {
      this.status = status;
      this.matchedText = matched;
      this.remainingText = remaining;
    }
    numLeadingSpaces(text) {
      return text.length - text.trimStart().length;
    }
    updateFrom(other) {
      this.status = other.status;
      this.matchedText = other.matchedText;
      this.remainingText = other.remainingText;
    }
    symbolCompletion_getSpec() {
      const active = this.getActiveNode();
      const isThis = active === this;
      const toMatch = isThis ? this.symbolCompletion_toMatch() : active.symbolCompletion_toMatch();
      const tokens = isThis ? this.symbolCompletion_tokenTypes() : active.symbolCompletion_tokenTypes();
      const keywords = isThis ? this.symbolCompletion_keywords() : active.symbolCompletion_keywords();
      const context = isThis ? this.symbolCompletion_context() : active.symbolCompletion_context();
      const spec = new SymbolCompletionSpec(toMatch, tokens, keywords, context);
      return spec;
    }
    symbolCompletion_toMatch() {
      const active = this.getActiveNode();
      return active === this ? this.matchedText : active.symbolCompletion_toMatch();
    }
    symbolCompletion_tokenTypes() {
      const active = this.getActiveNode();
      return active === this ? /* @__PURE__ */ new Set() : active.symbolCompletion_tokenTypes();
    }
    symbolCompletion_keywords() {
      const active = this.getActiveNode();
      return active === this ? /* @__PURE__ */ new Set() : active.symbolCompletion_keywords();
    }
    symbolCompletion_context() {
      const active = this.getActiveNode();
      return active === this ? "" : active.symbolCompletion_context();
    }
    getActiveNode() {
      const active = this.activeNodeForSymbolCompl;
      return active === this ? active : active.getActiveNode();
    }
    isDone() {
      return this._done;
    }
    isValid() {
      return this.status === 3 /* valid */;
    }
    isIncomplete() {
      return this.status === 2 /* incomplete */;
    }
    isEmpty() {
      return this.status === 1 /* empty */;
    }
    isInvalid() {
      return this.status === 0 /* invalid */;
    }
  };

  // src/ide/frames/parse-nodes/space-node.ts
  var SpaceNode = class extends AbstractParseNode {
    type;
    constructor(file, type) {
      super(file);
      this.type = type;
    }
    parseText(text) {
      if (text.length === 0) {
        if (this.type === 2 /* required */) {
          this.status = 1 /* empty */;
        } else {
          this.status = 3 /* valid */;
        }
      } else {
        this.remainingText = text;
        const matches = text.match(Regexes.leadingSpaceNotNL);
        if (matches !== null && matches.length > 0) {
          this.remainingText = text.replace(matches[0], "");
          this.status = 3 /* valid */;
          this._done = true;
        } else if (this.type === 2 /* required */) {
          this.status = 0 /* invalid */;
        } else {
          this.status = 3 /* valid */;
          this._done = true;
        }
      }
    }
    renderAsHtml() {
      return this.renderAsElanSource();
    }
    renderAsElanSource() {
      return this.type === 0 /* ignored */ || this.status === 1 /* empty */ ? "" : " ";
    }
    getSyntaxCompletionAsHtml() {
      return this.status === 1 /* empty */ && this.type === 2 /* required */ ? " " : "";
    }
    compile() {
      return this.type === 0 /* ignored */ ? "" : " ";
    }
  };

  // src/ide/frames/parse-nodes/parse-node-helpers.ts
  function matchRegEx(text, regx) {
    let status = 0 /* invalid */;
    let match3 = "";
    let remaining = text;
    const matches = text.match(regx);
    if (matches !== null && matches.length > 0) {
      match3 = matches[0];
      status = 3 /* valid */;
      remaining = text.replace(match3, "");
    }
    return [status, match3, remaining];
  }
  var allIds = [
    4 /* id_constant */,
    0 /* id_let */,
    3 /* id_parameter_regular */,
    2 /* id_property */,
    1 /* id_variable */,
    5 /* id_enumValue */
  ];
  var allMethods = [
    11 /* method_function */,
    11 /* method_function */,
    12 /* method_system */
  ];
  var allIdsAndMethods = [
    4 /* id_constant */,
    0 /* id_let */,
    3 /* id_parameter_regular */,
    2 /* id_property */,
    1 /* id_variable */,
    5 /* id_enumValue */,
    11 /* method_function */,
    11 /* method_function */,
    12 /* method_system */
  ];
  var assignableIds = [1 /* id_variable */, 2 /* id_property */];
  var concreteAndAbstractTypes = [
    7 /* type_abstract */,
    9 /* type_notInheritable */,
    6 /* type_concrete */,
    8 /* type_enum */
  ];
  var allKeywordsThatCanStartAnExpression = new Set(
    [newKeyword, ifKeyword, lambdaKeyword].map((kw) => KeywordCompletion.create(kw))
  );
  function removeUnmatchedClosingBracket(text) {
    if (text.endsWith(")") && text.split("(").length - text.split(")").length !== 0) {
      text = text.slice(0, text.length - 1);
    }
    return text;
  }

  // src/ide/frames/parse-nodes/identifier-def.ts
  var IdentifierDef = class extends IdentifierUse {
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        [this.status, this.matchedText, this.remainingText] = matchRegEx(
          text.trimStart(),
          Regexes.identifier
        );
      }
      if (this.isValid()) {
        if (ReservedWords.Instance.matchesIgnoringCase(this.matchedText)) {
          this.status = 0 /* invalid */;
          this.message = `matches a reserved word.`;
        } else {
          this._done = true;
        }
      }
    }
  };

  // src/ide/frames/parse-nodes/method-name-def.ts
  var MethodNameDef = class extends IdentifierDef {
    renderAsHtml() {
      return `<el-method>${this.matchedText.trim()}</el-method>`;
    }
  };

  // src/ide/frames/overtyper.ts
  var Overtyper = class {
    hasNotConsumed = (_s) => true;
    toConsume = "";
    timer;
    timeOut;
    consuming(k) {
      if (k) {
        if (this.toConsume.length > 0 && k.toUpperCase() === this.toConsume[0].toUpperCase()) {
          this.toConsume = this.toConsume.slice(1);
          clearTimeout(this.timer);
          this.timer = setTimeout(
            () => this.hasNotConsumed = (_s) => true,
            this.timeOut
          );
          return false;
        }
        this.toConsume = "";
        this.hasNotConsumed = (_s) => true;
        clearTimeout(this.timer);
      }
      return true;
    }
    consumeChars(toConsume, timeOut) {
      if (toConsume.length > 0) {
        this.timeOut = timeOut;
        this.toConsume = toConsume;
        this.hasNotConsumed = this.consuming;
        this.timer = setTimeout(
          () => this.hasNotConsumed = (_s) => true,
          timeOut
        );
      }
    }
  };

  // src/ide/frames/symbol-wrapper.ts
  var SymbolWrapper = class {
    constructor(wrapped, scope, file) {
      this.wrapped = wrapped;
      this.scope = scope;
      this.file = file;
      if (wrapped instanceof KeywordCompletion) {
        this.name = wrapped.keyword;
        this.isKeyword = true;
      } else {
        this.name = wrapped.symbolId;
        this.isKeyword = false;
      }
    }
    isKeyword;
    name;
    get displayName() {
      if (this.name === "") {
        return this.name;
      }
      if (this.isKeyword) {
        return this.name;
      }
      const symbol = this.wrapped;
      if (isProperty(symbol) && isMemberOnFieldsClass(symbol, this.scope)) {
        const thisInstance = this.file.language().THIS_INSTANCE;
        return `${thisInstance}.${symbol.symbolId}`;
      }
      if (isTypeSymbol(symbol)) {
        return this.langSpecificTypeName(this.name);
      }
      return this.name;
    }
    langSpecificTypeName(elanName) {
      const lang = this.file.language();
      let name = elanName;
      if (name === "Int") {
        name = lang.INT_NAME;
      } else if (name === "Float") {
        name = lang.FLOAT_NAME;
      } else if (name === "Boolean") {
        name = lang.BOOL_NAME;
      } else if (name === "String") {
        name = lang.STRING_NAME;
      } else if (name === "List") {
        name = lang.LIST_NAME;
      }
      return name;
    }
    get class() {
      if (this.isKeyword) {
        return " keyword";
      }
      const symbol = this.wrapped;
      if (isConcreteTypeName(symbol) || isAbstractTypeName(symbol) || isNotInheritableClass(symbol)) {
        return " type";
      }
      if (isFunction(symbol) || isProcedure(symbol)) {
        return " method";
      }
      if (isId(symbol)) {
        return " id";
      }
      return "";
    }
    get insertedText() {
      if (this.wrapped instanceof KeywordCompletion) {
        const postfix = this.wrapped.dotAfter ? "." : this.wrapped.spaceAfter ? " " : this.wrapped.openBracketAfter ? "(" : "";
        return `${this.name}${postfix}`;
      }
      const symbol = this.wrapped;
      if (isTypeSymbol(symbol)) {
        let toInsert = this.langSpecificTypeName(this.name);
        if (isGenericClass(symbol)) {
          const lang = this.file.language();
          toInsert += lang.START_OF_GENERIC;
        }
        return toInsert;
      }
      if (isFunction(symbol)) {
        return `${this.name}(`;
      }
      if (isProcedure(symbol)) {
        return `${this.name}`;
      }
      if (isConcreteTypeName(symbol) || isAbstractTypeName(symbol)) {
        return `${this.name}`;
      }
      if (isMemberOnFieldsClass(symbol, this.scope)) {
        const thisInstance = this.file.language().THIS_INSTANCE;
        return `${thisInstance}.${symbol.symbolId}`;
      }
      if (isCall(this.scope) && this.scope.args instanceof EmptyAsn) {
        return `${this.name}.`;
      }
      return this.name;
    }
    matches(other) {
      if (!other) {
        return false;
      }
      if (this.isKeyword && other.isKeyword) {
        return this.name === other.name;
      }
      if (!this.isKeyword && !other.isKeyword) {
        return this.name === other.name && this.wrapped.symbolScope === other.wrapped.symbolScope;
      }
      return false;
    }
  };

  // src/ide/frames/fields/abstract-field.ts
  var AbstractField = class {
    isField = true;
    text = "";
    _placeholder = "";
    placeholderIsCode = false;
    useHtmlTags = false;
    id = "";
    selected = false;
    focused = false;
    _classes = new Array();
    holder;
    _optional = false;
    map;
    _parseStatus;
    cursorPos = 0;
    //Relative to LH end of text
    selectionEnd = 0;
    //Relative to LH end of text
    rootNode;
    completion = "";
    overtyper = new Overtyper();
    codeHasChanged = false;
    allPossibleSymbolCompletions = [];
    symbolToMatch = "";
    selectedSymbolCompletion;
    showingSymbolCompletion = false;
    helpActive = false;
    constructor(holder) {
      this.holder = holder;
      const map = holder.getMap();
      this.id = `${this.getFile().getNextId()}`;
      map.set(this.htmlId, this);
      this.map = map;
      this._parseStatus = 2 /* incomplete */;
    }
    get htmlId() {
      return `${this.getIdPrefix()}${this.id}`;
    }
    getRootNode() {
      return this.rootNode;
    }
    getFile() {
      return this.holder.getFile();
    }
    getHtmlId() {
      return this.htmlId;
    }
    showHelp() {
      this.helpActive = true;
    }
    alertHolderToUpdate() {
      this.getHolder().fieldUpdated(this);
    }
    parseCurrentText() {
      const root = this.initialiseRoot();
      this.parseCompleteTextUsingNode(this.text, root);
    }
    parseFrom(source) {
      this.holder.hasBeenAddedTo();
      const text = this.readToDelimiter(source);
      const root = this.initialiseRoot();
      this.parseCompleteTextUsingNode(text, root);
      if (this.isOptional() && this._parseStatus === 1 /* empty */) {
        this._parseStatus = 3 /* valid */;
      } else if (this._parseStatus === 0 /* invalid */) {
        throw new Error(`Parse error at ${source.getRemainingCode()}`);
      }
    }
    parseCompleteTextUsingNode(text, root) {
      if (text.length === 0) {
        this.setParseStatus(this.isOptional() ? 3 /* valid */ : 2 /* incomplete */);
      } else {
        root.parseText(text.trimStart());
        if (root.remainingText.trim().length > 0 || root.status === 0 /* invalid */) {
          this.setParseStatus(0 /* invalid */);
          this.text = text.trimStart();
        } else {
          this.setParseStatus(root.status);
          this.text = root.renderAsExport();
        }
      }
    }
    getCompletion() {
      return this.rootNode ? this.rootNode.getSyntaxCompletionAsHtml() : "";
    }
    getPlainTextCompletion() {
      const comps = this.getCompletion();
      const i = comps.indexOf("<i>");
      return i === -1 ? comps : comps.substring(0, i);
    }
    setOptional(optional) {
      this._optional = optional;
      if (this.text === "" && optional) {
        this._parseStatus = 3 /* valid */;
      } else if (this.text === "" && !optional) {
        this._parseStatus = 2 /* incomplete */;
      }
    }
    getOptional() {
      return this._optional;
    }
    isOptional() {
      return this._optional;
    }
    processAutocompleteText(txt) {
      if (txt) {
        this.selectedSymbolCompletion = this.allPossibleSymbolCompletions.find(
          (s) => s.displayName === txt
        );
      }
    }
    setSelection(start, end) {
      this.cursorPos = start;
      this.selectionEnd = end ?? start;
    }
    deleteSelection(selection) {
      const [start, end] = selection;
      const textLen = this.text.length;
      if (start !== textLen) {
        const endMod = start === end ? start + 1 : end;
        this.text = this.text.slice(0, start) + this.text.slice(endMod);
        this.setSelection(start);
      }
    }
    deleteNewSelection(e) {
      if (e.selection) {
        this.deleteSelection(e.selection);
      }
    }
    hasSelection() {
      return this.cursorPos !== this.selectionEnd;
    }
    deleteExistingSelection() {
      if (this.hasSelection()) {
        this.deleteSelection([this.cursorPos, this.selectionEnd]);
      }
    }
    controlKeys = ["o", "O", "ArrowLeft", "ArrowRight", "a", "v", "?"];
    processKey(e) {
      this.codeHasChanged = false;
      const key = e.key;
      if (e.modKey.control && !this.controlKeys.includes(key ?? "")) {
        return false;
      }
      const textLen = this.text.length;
      this.processAutocompleteText(e.optionalData);
      switch (key) {
        case "Home": {
          this.setSelection(0);
          break;
        }
        case "End": {
          this.setSelection(textLen);
          break;
        }
        case "Tab": {
          this.tab(e.modKey.shift);
          this.noLongerEditingField();
          break;
        }
        case "Enter": {
          this.enter();
          break;
        }
        case "ArrowLeft": {
          if (e.modKey.control) {
            this.cursorWordLeft(e.modKey.shift);
          } else {
            this.cursorLeft(e.modKey.shift);
          }
          break;
        }
        case "ArrowRight": {
          if (e.modKey.control) {
            this.cursorWordRight(e.modKey.shift);
          } else {
            this.cursorRight(e.modKey.shift);
          }
          break;
        }
        case "ArrowUp": {
          if (this.showingSymbolCompletion) {
            this.selectFromAutoCompleteItems(true);
          }
          break;
        }
        case "ArrowDown": {
          if (this.showingSymbolCompletion) {
            this.selectFromAutoCompleteItems(false);
          }
          break;
        }
        case "ContextMenu": {
          if (this.getHolder().isSelected()) {
            return this.getHolder().processKey(e);
          }
        }
        case "Backspace": {
          if (this.holder.isNew) {
            this.holder.deleteIfPermissible();
            this.codeHasChanged = true;
          } else if (this.hasSelection()) {
            this.deleteExistingSelection();
            this.parseCurrentText();
          } else if (this.cursorPos > 0) {
            const reduced = this.text.slice(0, this.cursorPos - 1) + this.text.slice(this.cursorPos);
            this.text = reduced;
            this.setSelection(this.cursorPos - 1);
            const cursorBeforeParse = this.cursorPos;
            this.parseCurrentText();
            if (this.text.length > reduced.length) {
              this.text = reduced;
              this.setSelection(cursorBeforeParse);
            }
            this.codeHasChanged = true;
            this.editingField();
          }
          break;
        }
        case "Delete": {
          this.deleteNewSelection(e);
          this.parseCurrentText();
          this.codeHasChanged = true;
          this.editingField();
          break;
        }
        case "t": {
          if (e.modKey.alt) {
            this.getFile().removeAllSelectorsThatCanBe();
            break;
          }
        }
        case "a": {
          if (e.modKey.control) {
            this.setSelection(0, this.text.length);
            break;
          }
        }
        case "?": {
          if (e.modKey.control) {
            this.showHelp();
            break;
          }
        }
        case "v": {
          if (e.modKey.control) {
            const toPaste = e.optionalData ?? "";
            this.deleteExistingSelection();
            for (const c of toPaste) {
              this.processInput(c);
            }
            this.codeHasChanged = true;
            this.holder.hasBeenAddedTo();
            this.editingField();
            this.getFile().removeAllSelectorsThatCanBe();
            break;
          }
        }
        default: {
          if (key === "o" && e.modKey.control && isCollapsible(this.holder)) {
            this.holder.expandCollapse();
            this.noLongerEditingField();
          } else if (key === "O" && e.modKey.control) {
            this.holder.expandCollapseAll();
            this.noLongerEditingField();
          } else if (key?.length === 1) {
            this.deleteExistingSelection();
            this.processInput(key);
            this.codeHasChanged = true;
            this.holder.hasBeenAddedTo();
            this.editingField();
          }
        }
      }
      if (this.codeHasChanged) {
        this.selectedSymbolCompletion = void 0;
      }
      return this.codeHasChanged;
    }
    editingField() {
      this.getFile().setFieldBeingEdited(true);
    }
    noLongerEditingField() {
      this.getFile().setFieldBeingEdited(false);
      this.codeHasChanged = true;
    }
    isEndMarker(_key) {
      return false;
    }
    processInput(key) {
      if (this.overtyper.hasNotConsumed(key)) {
        if (this.isEndMarker(key)) {
          this.enter();
        } else {
          this.text = this.text.slice(0, this.cursorPos) + key + this.text.slice(this.cursorPos);
          const preParse = this.text.length;
          this.parseCurrentText();
          const afterParse = this.text.length;
          this.setSelection(this.cursorPos + 1 + afterParse - preParse);
        }
      }
    }
    cursorSelectRight() {
      const textLen = this.text.length;
      if (this.selectionEnd < textLen) {
        this.setSelection(this.cursorPos, this.selectionEnd + 1);
      }
    }
    cursorSelectLeft() {
      if (this.cursorPos > 0) {
        this.setSelection(this.cursorPos - 1, this.selectionEnd);
      }
    }
    cursorMoveRight() {
      const textLen = this.text.length;
      if (this.cursorPos < textLen) {
        this.setSelection(this.cursorPos + 1);
      } else {
        const completions = this.getPlainTextCompletion();
        if (completions.length > 0) {
          this.text = this.text + completions;
          this.parseCurrentText();
          this.setSelection(this.text.length);
          this.codeHasChanged = true;
        }
      }
    }
    cursorMoveLeft() {
      if (this.cursorPos > 0) {
        this.setSelection(this.cursorPos - 1);
      }
    }
    cursorRight(shift) {
      if (shift) {
        this.cursorSelectRight();
      } else {
        this.cursorMoveRight();
      }
    }
    cursorLeft(shift) {
      if (shift) {
        this.cursorSelectLeft();
      } else {
        this.cursorMoveLeft();
      }
    }
    isWordBreakCharRight(c) {
      return c === " " || c === "." || c === "(";
    }
    isWordBreakCharLeft(c) {
      return c === " " || c === "." || c === ")";
    }
    cursorSelectWordRight() {
      const textLen = this.text.length;
      if (this.selectionEnd < textLen) {
        for (let i = this.selectionEnd + 1; i < textLen; i++) {
          const nextChar = this.text[i];
          if (this.isWordBreakCharRight(nextChar)) {
            this.setSelection(this.cursorPos, i);
            return;
          }
        }
        this.setSelection(this.cursorPos, textLen);
      }
    }
    cursorMoveWordRight() {
      const textLen = this.text.length;
      if (this.cursorPos < textLen) {
        for (let i = this.cursorPos + 1; i < textLen; i++) {
          const nextChar = this.text[i];
          if (this.isWordBreakCharRight(nextChar)) {
            this.setSelection(i);
            return;
          }
        }
        this.setSelection(textLen);
      }
    }
    cursorWordRight(shift) {
      if (shift) {
        this.cursorSelectWordRight();
      } else {
        this.cursorMoveWordRight();
      }
    }
    cursorSelectWordLeft() {
      if (this.cursorPos > 0) {
        const startIndex = this.isWordBreakCharLeft(this.text[this.cursorPos - 1]) ? this.cursorPos - 1 : this.cursorPos;
        for (let i = startIndex; i > 0; i--) {
          const nextChar = this.text[i - 1];
          if (this.isWordBreakCharLeft(nextChar)) {
            this.setSelection(i, this.selectionEnd);
            return;
          }
        }
        this.setSelection(0, this.selectionEnd);
      }
    }
    cursorMoveWordLeft() {
      if (this.cursorPos > 0) {
        const startIndex = this.isWordBreakCharLeft(this.text[this.cursorPos - 1]) ? this.cursorPos - 1 : this.cursorPos;
        for (let i = startIndex; i > 0; i--) {
          const nextChar = this.text[i - 1];
          if (this.isWordBreakCharLeft(nextChar)) {
            this.setSelection(i);
            return;
          }
        }
        this.setSelection(0);
      }
    }
    cursorWordLeft(shift) {
      if (shift) {
        this.cursorSelectWordLeft();
      } else {
        this.cursorMoveWordLeft();
      }
    }
    language() {
      return this.getFile().language();
    }
    replaceAutocompletedText() {
      if (this.symbolToMatch !== "") {
        const li = this.text.lastIndexOf(this.symbolToMatch);
        this.text = this.text.slice(0, li);
      }
      const thisInstance = this.language().THIS_INSTANCE;
      const propertyPrefix = `${thisInstance}.`;
      const appendText = this.selectedSymbolCompletion?.insertedText ?? "";
      if (this.text === propertyPrefix && appendText.startsWith(propertyPrefix)) {
        this.text = "";
      }
      const optSpace = this.text && this.selectedSymbolCompletion?.isKeyword ? " " : "";
      this.text = `${this.text}${optSpace}${appendText}`;
      this.selectedSymbolCompletion = void 0;
      this.parseCurrentText();
      this.setSelection(this.text.length);
      this.codeHasChanged = true;
      this.holder.hasBeenAddedTo();
    }
    tab(back) {
      if (back) {
        this.holder.selectFieldBefore(this);
      } else if (this.selectedSymbolCompletion) {
        this.replaceAutocompletedText();
      } else {
        const completions = this.getPlainTextCompletion();
        if (completions.length > 0) {
          this.cursorRight(false);
        } else {
          this.holder.selectFieldAfter(this);
        }
      }
    }
    enter() {
      if (this.selectedSymbolCompletion) {
        this.replaceAutocompletedText();
      } else {
        const completions = this.getPlainTextCompletion();
        if (completions.length > 0) {
          this.cursorRight(false);
        } else {
          const peerFields = this.holder.getFields();
          const last = peerFields.length - 1;
          const thisField = peerFields.indexOf(this);
          if (thisField === last) {
            this.holder.selectNextFrame();
          } else {
            this.tab(false);
          }
          this.noLongerEditingField();
        }
      }
    }
    isFocused() {
      return this.focused;
    }
    getHolder() {
      return this.holder;
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_text`;
    }
    focus() {
      this.focused = true;
    }
    defocus() {
      this.focused = false;
    }
    deselectAll() {
      for (const f of this.map.values()) {
        if (f.isSelected()) {
          f.deselect();
        }
      }
      this.noLongerEditingField();
    }
    setParseStatus(newStatus) {
      this._parseStatus = newStatus;
    }
    readParseStatus() {
      return this._parseStatus;
    }
    readCompileStatus() {
      return helper_deriveCompileStatusFromErrors(
        this.getFile().getAst(false)?.getCompileErrorsFor(this.htmlId) ?? []
      );
    }
    onClick(withFocus, multiSelect, selection) {
      if (!this.isWithinAGhostedFrame()) {
        const parentSelected = this.getHolder().isSelected();
        if (this.selected || parentSelected || selection && selection[0] !== selection[1]) {
          this.select(withFocus, multiSelect, selection);
        } else {
          this.getHolder().select(true);
        }
      }
    }
    select(_withFocus, _multiSelect, selection) {
      if (!this.isWithinAGhostedFrame()) {
        this.deselectAll();
        this.selected = true;
        this.focus();
        if (selection) {
          let [start, end] = selection;
          if (start === this.cursorPos && end === this.selectionEnd) {
            start = end = this.cursorPos;
          }
          this.setSelection(start, end);
        } else {
          this.setSelection(this.text.length);
        }
      }
    }
    isSelected() {
      return this.selected === true;
    }
    deselect() {
      this.selected = false;
      this.defocus();
      this.noLongerEditingField();
    }
    setPlaceholder(placeholder) {
      this._placeholder = placeholder;
    }
    textAsHtml() {
      let html = "";
      if (this.selected) {
        html = this.fieldAsInput() + this.symbolCompletion();
      } else {
        if (this.rootNode && this._parseStatus === 3 /* valid */) {
          html = this.rootNode.renderAsHtml();
        } else {
          html = escapeHtmlChars(this.text);
        }
      }
      return html;
    }
    textAsExport() {
      return this.rootNode && this._parseStatus === 3 /* valid */ ? this.rootNode.renderAsExport() : "";
    }
    fieldAsInput() {
      return `<input spellcheck="false" data-cursorstart="${this.cursorPos}" data-cursorend="${this.selectionEnd}" size="${this.charCount()}" style="width: ${this.fieldWidth()}" value="${this.escapeDoubleQuotesAndEscapes(this.text)}" tabindex="-1">`;
    }
    charCount() {
      return this.text ? this.text.length > 1 ? this.text.length - 1 : 1 : 1;
    }
    fieldWidth() {
      return this.text.length === 0 ? "2px" : `${this.text.length}ch`;
    }
    escapeDoubleQuotesAndEscapes(str) {
      return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
    }
    textAsSource() {
      return this.text;
    }
    setClasses() {
      this._classes = new Array();
      this.pushClass(this.selected, "selected");
      this.pushClass(this.focused, "focused");
      this.pushClass(!this.text, "empty");
      this.pushClass(this.isOptional(), "optional");
      this._classes.push(DisplayColour[this.readDisplayStatus()]);
    }
    readDisplayStatus() {
      return helper_CompileOrParseAsDisplayStatus(this);
    }
    pushClass(flag, cls) {
      if (flag) {
        this._classes.push(cls);
      }
    }
    cls() {
      this.setClasses();
      return this._classes.join(" ");
    }
    getMessage() {
      let message = ``;
      if (this._parseStatus === 0 /* invalid */) {
        const cls = this.isSelected() ? DisplayColour[1 /* warning */] : DisplayColour[0 /* error */];
        const msg = this.rootNode.message;
        message = `<el-msg class="${cls}">${msg}${this.helpAsHtml()}</el-msg>`;
      } else {
        message = helper_compileMsgAsHtmlNew(this.getFile(), this);
      }
      return message;
    }
    helpAsHtml() {
      const active = this.helpActive ? ` class="active"` : "";
      this.helpActive = false;
      return `<el-help title="Click to open Help for this field"><a href="documentation/LangRef.html#${this.helpId()}" target="help-iframe" tabindex="-1"${active}>?</a></el-help>`;
    }
    renderAsHtml() {
      let completion = "";
      if (this.cursorPos === this.text.length) {
        const content = this.getCompletion().replace("<of", "&lt;of");
        completion = `<el-compl>${content}</el-compl>`;
      }
      return `<el-field id="${this.htmlId}" class="${this.cls()}" tabindex="-1"><el-txt>${this.textAsHtml()}</el-txt><el-place>${this._placeholder}</el-place>${completion}${this.getMessage()}${this.helpAsHtml()}</el-field>`;
    }
    renderAsExport() {
      return this.readParseStatus() === 3 /* valid */ ? removeHtmlTagsAndEscChars(this.textAsHtml()) : this.rootNode.matchedText;
    }
    indent() {
      return "";
    }
    renderAsElanSource() {
      return this.rootNode ? this.rootNode.renderAsElanSource() : this.textAsSource();
    }
    setFieldToKnownValidText(text) {
      this.text = text;
      const root = this.initialiseRoot();
      this.parseCompleteTextUsingNode(this.text, root);
      this._parseStatus = 3 /* valid */;
    }
    matchingSymbolsForId(spec) {
      const ast = this.getFile().getAst(false);
      const symbols = getFilteredSymbols(spec, ast, this.getHolder().getHtmlId());
      return removeIfSingleFullMatch(symbols, spec.toMatch);
    }
    popupAsHtml() {
      const symbols = this.allPossibleSymbolCompletions;
      const symbolAsHtml = [];
      const count = this.allPossibleSymbolCompletions.length;
      this.selectedSymbolCompletion = this.selectedSymbolCompletion ? symbols.filter((s) => s.matches(this.selectedSymbolCompletion))[0] : void 0;
      const selectedIndex = this.selectedSymbolCompletion ? symbols.indexOf(this.selectedSymbolCompletion) : 0;
      let popupAsHtml = "";
      let startIndex = 0;
      let lastIndex = count > 10 ? 10 : count;
      let lastName = "";
      if (count > 10 && selectedIndex > 5) {
        startIndex = selectedIndex - 5;
        lastIndex = selectedIndex + 5;
        lastIndex = lastIndex > count ? count : lastIndex;
      }
      if (count === 0) {
        this.selectedSymbolCompletion = void 0;
      }
      for (let i = startIndex; i < lastIndex; i++) {
        const symbol = symbols[i];
        const name = symbol.displayName;
        const cls = symbol.class;
        const selected = this.markIfSelected(symbol) ? " selected" : "";
        lastName = name;
        symbolAsHtml.push(
          `<div class="autocomplete-item${selected}${cls}" data-id="${this.htmlId}">${name}</div>`
        );
      }
      if (count > 10 && selectedIndex + 5 < count) {
        symbolAsHtml.push(
          `<div class="autocomplete-ellipsis" data-id="${this.htmlId}" data-selected="${lastName}" >...</div>`
        );
      }
      if (symbolAsHtml.length > 0) {
        popupAsHtml = `<div class="autocomplete-popup">${symbolAsHtml.join("")}</div>`;
      }
      return popupAsHtml;
    }
    markIfSelected(symbol) {
      return symbol === this.selectedSymbolCompletion;
    }
    selectFromAutoCompleteItems(up) {
      const options = this.allPossibleSymbolCompletions;
      let matched = false;
      for (let i = 0; i < options.length; i++) {
        if (!matched && options[i] === this.selectedSymbolCompletion) {
          if (i > 0 && up) {
            this.selectedSymbolCompletion = options[i - 1];
            matched = true;
          } else if (i < options.length - 1 && !up) {
            this.selectedSymbolCompletion = options[i + 1];
            matched = true;
          }
        }
      }
      if (!matched && options.length > 0) {
        this.selectedSymbolCompletion = options[0];
      }
    }
    showAutoComplete(spec) {
      return (spec.tokenTypes.size > 0 || spec.keywords.size > 0) && this.selected && this.cursorPos === this.text.length && this.readParseStatus() !== 0 /* invalid */;
    }
    getSymbolCompletionSpec() {
      KeywordCompletion.reset();
      const rn = this.rootNode ?? this.initialiseRoot();
      const spec = rn.symbolCompletion_getSpec();
      if (spec.context === "") {
        spec.context = this.extractContextFromText();
      } else if (spec.context === "none") {
        spec.context = "";
      }
      return spec;
    }
    orderSymbol(s1, s2) {
      return s1.name.localeCompare(s2.name);
    }
    extractContextFromText() {
      const rgx = /([[A-Za-z][A-Za-z0-9_]*)(\(.*\))?\.([[A-Za-z][A-Za-z0-9_]*)?$/;
      return rgx.test(this.text) ? this.text.match(rgx)[1] : "";
    }
    symbolCompletionAsHtml() {
      let popupAsHtml = "";
      const spec = this.getSymbolCompletionSpec();
      if (this.showAutoComplete(spec)) {
        this.symbolToMatch = spec.toMatch;
        const scope = this.getFile().getAst(false)?.getScopeById(this.getHolder().getHtmlId());
        const keywords = Array.from(spec.keywords).map((k) => new SymbolWrapper(k, scope, this.getFile())).sort(this.orderSymbol);
        const symbols = this.matchingSymbolsForId(spec).map(
          (s) => new SymbolWrapper(s, scope, this.getFile())
        );
        this.allPossibleSymbolCompletions = keywords.concat(symbols);
        popupAsHtml = this.popupAsHtml();
      }
      this.showingSymbolCompletion = !!popupAsHtml;
      return popupAsHtml;
    }
    isWithinAGhostedFrame() {
      return this.getHolder().isGhostedOrWithinAGhostedFrame();
    }
    resetText() {
      if (!!this.rootNode && this._parseStatus === 3 /* valid */) {
        const text = removeHtmlTagsAndEscChars(this.rootNode.renderAsHtml());
        if (text !== this.text) {
          this.setFieldToKnownValidText(text);
        }
      }
    }
  };

  // src/ide/frames/fields/method-name-field.ts
  var MethodNameField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this.setPlaceholder("<i>name</i>");
    }
    helpId() {
      return "MethodNameField";
    }
    initialiseRoot() {
      this.rootNode = new MethodNameDef(this.getFile());
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readUntil(/[^a-zA-Z0-9_]/);
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_ident`;
    }
    isEndMarker(key) {
      return key === " " || key === "(";
    }
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
  };

  // src/ide/frames/parse-nodes/abstract-sequence.ts
  var AbstractSequence = class extends AbstractParseNode {
    elements = [];
    constructor(file) {
      super(file);
    }
    addElement(node) {
      this.elements.push(node);
    }
    getElements() {
      return this.elements;
    }
    parseText(text) {
      let i = -1;
      this.remainingText = text;
      let continueLoop = true;
      while (this.elements.length > 0 && continueLoop) {
        i++;
        const node = this.elements[i];
        const firstNode = i === 0;
        const lastNode = i === this.elements.length - 1;
        const nextNode = lastNode ? void 0 : this.elements[i + 1];
        node.parseText(this.remainingText);
        this.remainingText = node.remainingText;
        const moreText = this.remainingText.length > 0;
        if (node.isDone()) {
          if (lastNode) {
            this.status = 3 /* valid */;
            this._done = true;
            continueLoop = false;
          } else {
            this.status = 2 /* incomplete */;
            this.activeNodeForSymbolCompl = nextNode.getActiveNode();
            continueLoop = true;
          }
        } else if (node.isValid()) {
          if (moreText) {
            if (lastNode) {
              this.status = 3 /* valid */;
              this._done = true;
              continueLoop = false;
            } else {
              this.activeNodeForSymbolCompl = nextNode.getActiveNode();
              continueLoop = true;
            }
          } else {
            if (node.matchedText.length > 0 || firstNode) {
              this.activeNodeForSymbolCompl = node.getActiveNode();
            }
            this.status = 3 /* valid */;
            continueLoop = !lastNode;
          }
        } else if (node.isIncomplete()) {
          continueLoop = false;
          if (moreText) {
            this.status = 0 /* invalid */;
          } else {
            this.status = 2 /* incomplete */;
            this.activeNodeForSymbolCompl = node.getActiveNode();
          }
        } else if (node.isEmpty()) {
          if (firstNode) {
            this.status = 1 /* empty */;
            this.activeNodeForSymbolCompl = node.getActiveNode();
          } else {
            this.status = 2 /* incomplete */;
          }
          continueLoop = false;
        } else if (node.isInvalid()) {
          this.status = 0 /* invalid */;
          continueLoop = false;
        }
      }
      if (this.isInvalid() || this.isEmpty()) {
        this.remainingText = text;
        this.elements = [];
      } else {
        this.matchedText = text.substring(0, text.length - this.remainingText.length);
      }
    }
    renderAsHtml() {
      return this.elements.reduce((result, current) => result + current.renderAsHtml(), "");
    }
    renderAsElanSource() {
      return this.elements.reduce((result, current) => result + current.renderAsElanSource(), "");
    }
    renderAsExport() {
      return this.elements.reduce((result, current) => result + current.renderAsExport(), "");
    }
    getSyntaxCompletionAsHtml() {
      const c = this.elements.length > 0 ? this.elements.reduce(
        (result, current) => `${result}${current.getSyntaxCompletionAsHtml()}`,
        ""
      ) : super.getSyntaxCompletionAsHtml();
      return c;
    }
  };

  // src/ide/frames/symbols.ts
  var ARROW = "=>";
  var OPEN_BRACE = "{";
  var CLOSE_BRACE = "}";
  var OPEN_SQ_BRACKET = "[";
  var CLOSE_SQ_BRACKET = "]";
  var OPEN_BRACKET = "(";
  var CLOSE_BRACKET = ")";
  var DOT = ".";
  var COMMA = ",";
  var COLON = ":";
  var PLUS = "+";
  var MINUS = "-";
  var MULT = "*";
  var DIVIDE = "/";
  var LT = "<";
  var GT = ">";
  var LE = "<=";
  var GE = ">=";
  var DOUBLE_QUOTES = `"`;

  // src/ide/frames/parse-nodes/comma-node.ts
  var CommaNode = class extends AbstractParseNode {
    parseText(text) {
      const trim = text.trimStart();
      if (trim.length > 0) {
        if (trim.startsWith(COMMA)) {
          this.status = 3 /* valid */;
          this._done = true;
          this.matchedText = COMMA;
          text = trim.slice(1);
        } else {
          this.status = 0 /* invalid */;
          this.remainingText = text;
        }
        text = text.trimStart();
        this.remainingText = text;
      }
    }
    renderAsElanSource() {
      return this.matchedText + " ";
    }
  };

  // src/ide/frames/parse-nodes/multiple.ts
  var Multiple = class extends AbstractParseNode {
    elementConstructor;
    minimum;
    elements = [];
    constructor(file, elementConstructor, minimum) {
      super(file);
      this.elementConstructor = elementConstructor;
      this.minimum = minimum;
    }
    getElements() {
      return this.elements;
    }
    parseText(text) {
      this.remainingText = text;
      if (text.length === 0) {
        this.status = this.minimum === 0 ? 3 /* valid */ : 1 /* empty */;
      } else {
        let toParse = text;
        let cont = true;
        while (cont && toParse.length > 0) {
          const node = this.elementConstructor();
          node.parseText(toParse);
          if (node.status === 3 /* valid */) {
            this.elements.push(node);
            toParse = node.remainingText;
            this.activeNodeForSymbolCompl = node.getActiveNode();
          } else if (node.status === 2 /* incomplete */ && node.remainingText.trim() === "") {
            this.elements.push(node);
            toParse = node.remainingText;
            this.activeNodeForSymbolCompl = node.getActiveNode();
          } else {
            cont = false;
          }
          if (this.elements.length === 0 && this.minimum === 0) {
            this.status = 3 /* valid */;
            this.remainingText = toParse;
          } else if (this.elements.length >= this.minimum) {
            const last = this.elements[this.elements.length - 1];
            this.status = last.status;
            const matchedLength = text.length - toParse.length;
            this.matchedText = text.substring(0, matchedLength);
            this.remainingText = toParse;
          } else {
            this.status = 0 /* invalid */;
            this.remainingText = text;
          }
        }
      }
    }
    renderAsHtml() {
      return this.elements.reduce((result, current) => result + current.renderAsHtml(), "");
    }
    renderAsElanSource() {
      return this.elements.reduce((result, current) => result + current.renderAsElanSource(), "");
    }
    getSyntaxCompletionAsHtml() {
      return this.elements.reduce(
        (result, current) => `${result}${current.getSyntaxCompletionAsHtml()}`,
        ""
      );
    }
    getActiveNode() {
      const n = this.elements.length;
      return n > 0 ? this.elements[n - 1].getActiveNode() : this;
    }
  };

  // src/ide/frames/parse-nodes/optional-node.ts
  var OptionalNode = class extends AbstractParseNode {
    option;
    matchedNode;
    constructor(file, option) {
      super(file);
      this.option = option;
    }
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        const option = this.option;
        option.parseText(text);
        if (option.status === 3 /* valid */ || option.status === 2 /* incomplete */ && option.remainingText.trim() === "") {
          this._done = option.isDone();
          this.updateFrom(option);
          this.matchedNode = option;
        } else {
          this.status = 3 /* valid */;
          this.remainingText = text;
          this._done = true;
        }
      } else {
        this.status = 3 /* valid */;
      }
    }
    renderAsHtml() {
      return this.matchedNode ? this.matchedNode.renderAsHtml() : "";
    }
    renderAsElanSource() {
      return this.matchedNode ? this.matchedNode.renderAsElanSource() : "";
    }
    renderAsExport() {
      return this.matchedNode ? this.matchedNode.renderAsExport() : "";
    }
    getSyntaxCompletionAsHtml() {
      const c = this.matchedNode ? this.matchedNode.getSyntaxCompletionAsHtml() : super.getSyntaxCompletionAsHtml();
      return c;
    }
    getActiveNode() {
      return this.matchedNode ? this.matchedNode.getActiveNode() : this;
    }
    symbolCompletion_tokenTypes() {
      return this.option.symbolCompletion_tokenTypes();
    }
    symbolCompletion_keywords() {
      return this.option.symbolCompletion_keywords();
    }
  };

  // src/ide/frames/parse-nodes/sequence.ts
  var Sequence = class extends AbstractSequence {
    elementConstructors;
    constructor(file, elementConstructors) {
      super(file);
      this.elementConstructors = elementConstructors;
    }
    parseText(text) {
      if (text.length > 0) {
        this.elementConstructors.forEach((ec) => {
          this.addElement(ec());
        });
      }
      super.parseText(text);
    }
  };

  // src/ide/frames/parse-nodes/csv.ts
  var CSV = class extends AbstractSequence {
    elementConstructor;
    minimum;
    constructor(file, elementConstructor, minimum) {
      super(file);
      this.elementConstructor = elementConstructor;
      this.minimum = minimum;
    }
    parseText(text) {
      this.remainingText = text;
      let commaNodesMin = 0;
      const commaNode = () => new Sequence(this.file, [() => new CommaNode(this.file), this.elementConstructor]);
      if (this.minimum === 0) {
        this.addElement(new OptionalNode(this.file, this.elementConstructor()));
      } else {
        this.addElement(this.elementConstructor());
        commaNodesMin = this.minimum - 1;
      }
      this.addElement(new Multiple(this.file, commaNode, commaNodesMin));
      super.parseText(text);
    }
    getSyntaxCompletionAsHtml() {
      let comp = super.getSyntaxCompletionAsHtml();
      if (this.minimum > 0 && this.matchedText.length === 0) {
        const el = this.elementConstructor();
        comp = el.getSyntaxCompletionAsHtml();
      }
      return comp;
    }
  };

  // src/ide/frames/parse-nodes/param-def-node.ts
  var ParamDefNode = class extends AbstractSequence {
    name;
    type;
    constructor(file) {
      super(file);
      this.completionWhenEmpty = "<i>name</i> as <i>Type</i>";
    }
    parseText(text) {
      if (text.trim().length > 0) {
        this.file.language().addNodesForParamDef(this);
        super.parseText(text);
      }
    }
    symbolCompletion_keywords() {
      return this.getElements().length === 0 ? /* @__PURE__ */ new Set([]) : super.symbolCompletion_keywords();
    }
    renderAsHtml() {
      return this.isValid() || this.isIncomplete() ? this.file.language().paramDefAsHtml(this) : this.matchedText;
    }
    renderAsElanSource() {
      return this.isValid() ? `${this.name?.renderAsElanSource()} ${asKeyword} ${this.type?.renderAsElanSource()}` : this.matchedText;
    }
    renderAsExport() {
      const lang = this.file.language();
      return this.isValid() ? removeHtmlTagsAndEscChars(lang.paramDefAsHtml(this)) : this.matchedText;
    }
  };

  // src/ide/frames/parse-nodes/param-list-node.ts
  var ParamListNode = class extends CSV {
    constructor(file) {
      super(file, () => new ParamDefNode(file), 0);
      this.setSyntaxCompletionWhenEmpty("<i>parameter definitions</i>");
    }
    parseText(text) {
      text = removeUnmatchedClosingBracket(text);
      super.parseText(text);
    }
    renderAsHtml() {
      return this.isValid() ? super.renderAsHtml() : this.matchedText;
    }
    renderAsExport() {
      return this.isValid() ? removeHtmlTagsAndEscChars(this.renderAsHtml()) : this.matchedText;
    }
    renderAsElanSource() {
      return super.renderAsElanSource();
    }
  };

  // src/ide/frames/fields/param-list-field.ts
  var ParamListField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this.setPlaceholder("<i>parameter definitions</i>");
      this.useHtmlTags = true;
      this.setOptional(true);
    }
    helpId() {
      return "ParamListField";
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_params`;
    }
    contentAsSource() {
      if (this.text) {
        return this.text;
      } else {
        return "";
      }
    }
    initialiseRoot() {
      this.rootNode = new ParamListNode(this.getFile());
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readToNonMatchingCloseBracket();
    isEndMarker(key) {
      return this.text === "" && key === ")";
    }
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
  };

  // src/ide/frames/parse-nodes/abstract-alternatives.ts
  var AbstractAlternatives = class extends AbstractParseNode {
    alternatives = [];
    bestMatch;
    parseText(text) {
      this.remainingText = text;
      if (this.remainingText.length > 0) {
        let open = true;
        let i = 0;
        while (i < this.alternatives.length) {
          const alt = this.alternatives[i];
          alt.parseText(text);
          if (open) {
            if (alt.isValid() && alt.remainingText.length === 0) {
              this.bestMatch = alt;
              open = false;
              this._done = alt.isDone();
            } else if (!this.bestMatch || alt.remainingText.length < this.bestMatch.remainingText.length || alt.remainingText.length === this.bestMatch.remainingText.length && alt.status > this.bestMatch.status) {
              this.bestMatch = alt;
            }
          }
          i++;
        }
        if (this.bestMatch.status > 0 /* invalid */) {
          this.status = this.bestMatch.status;
          this.matchedText = this.bestMatch.matchedText;
          this.remainingText = this.bestMatch.remainingText;
          this.alternatives = this.alternatives.filter((alt) => alt.status > 0 /* invalid */);
        } else {
          this.bestMatch = void 0;
          this.status = 0 /* invalid */;
          this.alternatives = [];
        }
      }
      if (this.isDone()) {
        this.alternatives = [];
      }
    }
    renderAsHtml() {
      return this.bestMatch ? this.bestMatch.renderAsHtml() : "";
    }
    renderAsElanSource() {
      return this.bestMatch ? this.bestMatch.renderAsElanSource() : "";
    }
    renderAsExport() {
      return this.bestMatch ? this.bestMatch.renderAsExport() : "";
    }
    getSyntaxCompletionAsHtml() {
      const c = this.bestMatch ? this.bestMatch.getSyntaxCompletionAsHtml() : super.getSyntaxCompletionAsHtml();
      return c;
    }
    getActiveNode() {
      if (this.bestMatchIsOnlyMatch()) {
        return this.bestMatch?.getActiveNode() ?? this;
      } else {
        return this;
      }
    }
    bestMatchIsOnlyMatch() {
      return this.potentialMatches().length === 1;
    }
    potentialMatches() {
      const best = this.bestMatch;
      const bestMatchLength = best ? best.matchedText.length : 0;
      return this.alternatives.filter(
        (alt) => alt.status !== 0 /* invalid */ && alt.matchedText.length === bestMatchLength
      );
    }
    symbolCompletion_tokenTypes() {
      return this.potentialMatches().reduce(
        (prev, m) => prev.union(m.symbolCompletion_tokenTypes()),
        /* @__PURE__ */ new Set()
      );
    }
    symbolCompletion_keywords() {
      return this.potentialMatches().reduce(
        (prev, m) => prev.union(m.symbolCompletion_keywords()),
        /* @__PURE__ */ new Set()
      );
    }
  };

  // src/ide/frames/parse-nodes/fixed-text-node.ts
  var FixedTextNode = class extends AbstractParseNode {
    fixedText;
    constructor(file, fixedText) {
      super(file);
      this.fixedText = fixedText;
      this.completionWhenEmpty = fixedText;
    }
    getErrorMessage() {
      return `must match ${this.fixedText}`;
    }
    getSyntaxCompletionAsHtml() {
      return this.status === 1 /* empty */ ? `${this.fixedText}` : "";
    }
  };

  // src/ide/frames/parse-nodes/keyword-node.ts
  var KeywordNode = class extends FixedTextNode {
    spaceAfter;
    dotAfter;
    constructor(file, keyword, spaceAfter = false, dotAfter = false) {
      super(file, keyword);
      this.spaceAfter = spaceAfter;
      this.dotAfter = dotAfter;
      this.completionWhenEmpty = keyword;
    }
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        const target = this.fixedText;
        const trimmed = text.trimStart();
        const lcLetters = trimmed.match(/^[A-Z]?[a-z]*/);
        if (lcLetters && lcLetters.length === 1) {
          if (lcLetters[0] === target) {
            const n = this.numLeadingSpaces(text) + this.fixedText.length;
            this.set(3 /* valid */, text.substring(0, n), text.substring(n));
            this._done = true;
          } else if (target.startsWith(trimmed)) {
            this.set(2 /* incomplete */, text, "");
          } else {
            this.set(0 /* invalid */, "", text);
          }
        }
      }
    }
    getSyntaxCompletionAsHtml() {
      let comp = ``;
      const matched = this.matchedText.length;
      const kw = this.fixedText.length;
      if (matched === 0) {
        comp = `${this.fixedText}`;
      } else if (matched === kw && this.remainingText === "") {
        comp = ``;
      } else if (matched < kw) {
        comp = `${this.fixedText.substring(this.matchedText.length)}`;
      }
      return comp;
    }
    renderAsHtml() {
      return `<el-kw>${this.matchedText.trim()}</el-kw>`;
    }
    renderAsElanSource() {
      return this.matchedText.trim();
    }
    compile() {
      switch (this.fixedText) {
        case isKeyword:
          return "===";
        case `${isKeyword} ${notKeyword}`:
          return "!==";
        case notKeyword:
          return "!";
        case andKeyword:
          return "&&";
        case orKeyword:
          return "||";
        default:
          return this.matchedText;
      }
    }
    symbolCompletion_keywords() {
      return /* @__PURE__ */ new Set([
        KeywordCompletion.create(this.fixedText, this.spaceAfter, this.dotAfter)
      ]);
    }
  };

  // src/ide/frames/parse-nodes/punctuation-node.ts
  var PunctuationNode = class extends FixedTextNode {
    constructor(file, symbol) {
      super(file, symbol);
    }
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        const target = this.fixedText;
        if (text.startsWith(target)) {
          const n = this.numLeadingSpaces(text) + this.fixedText.length;
          this.set(3 /* valid */, text.substring(0, n), text.substring(n));
          this._done = true;
        } else if (target.startsWith(text)) {
          this.set(2 /* incomplete */, text, "");
        } else {
          this.set(0 /* invalid */, "", text);
        }
      }
    }
    renderAsHtml() {
      return escapeHtmlChars(this.matchedText.trim());
    }
    getSyntaxCompletionAsHtml() {
      let comp = ``;
      const matched = this.matchedText.length;
      const kw = this.fixedText.length;
      if (matched === 0) {
        comp = `${this.fixedText}`;
      } else if (matched === kw && this.remainingText === "") {
        comp = ``;
      } else if (matched < kw) {
        comp = `${this.fixedText.substring(this.matchedText.length)}`;
      }
      return comp;
    }
  };

  // src/ide/frames/parse-nodes/regex-match-node.ts
  var RegExMatchNode = class extends AbstractParseNode {
    regx;
    constructor(file, regx) {
      super(file);
      this.regx = regx;
    }
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        [this.status, this.matchedText, this.remainingText] = matchRegEx(text, this.regx);
      }
    }
    renderAsElanSource() {
      return this.matchedText;
    }
  };

  // src/ide/frames/parse-nodes/type-specific-func-node.ts
  var TypeSpecificFuncNode = class extends RegExMatchNode {
    constructor(file) {
      super(file, /^\s*Func/);
      this.completionWhenEmpty = "<i>Func</i>";
    }
    renderAsHtml() {
      return `<el-type>${this.renderAsElanSource()}</el-type>`;
    }
    symbolCompletion_tokenTypes() {
      return /* @__PURE__ */ new Set();
    }
  };

  // src/ide/frames/parse-nodes/type-func-node.ts
  var TypeFuncNode = class extends AbstractSequence {
    inputTypes;
    returnType;
    tokenTypes = /* @__PURE__ */ new Set([
      6 /* type_concrete */,
      7 /* type_abstract */,
      9 /* type_notInheritable */
    ]);
    constructor(file) {
      super(file);
    }
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        this.addElement(new TypeSpecificFuncNode(this.file));
        this.addElement(new PunctuationNode(this.file, "<"));
        this.addElement(new KeywordNode(this.file, ofKeyword));
        this.addElement(new SpaceNode(this.file, 2 /* required */));
        const inputTypes = () => new CSV(this.file, () => new TypeNode(this.file, this.tokenTypes), 1);
        const sp = () => new SpaceNode(this.file, 2 /* required */);
        const inputTypesSp = new Sequence(this.file, [inputTypes, sp]);
        this.inputTypes = new OptionalNode(this.file, inputTypesSp);
        this.inputTypes.setSyntaxCompletionWhenEmpty("<i>InputType(s) </i>");
        this.addElement(this.inputTypes);
        this.addElement(new PunctuationNode(this.file, ARROW));
        this.addElement(new SpaceNode(this.file, 2 /* required */));
        this.returnType = new TypeNode(this.file, this.tokenTypes);
        this.returnType.setSyntaxCompletionWhenEmpty("<i>ReturnType</i>");
        this.addElement(this.returnType);
        this.addElement(new PunctuationNode(this.file, GT));
        super.parseText(text.trimStart());
      }
    }
    getSyntaxCompletionAsHtml() {
      return super.getSyntaxCompletionAsHtml();
    }
  };

  // src/ide/frames/parse-nodes/type-generic-node.ts
  var TypeGenericNode = class extends AbstractSequence {
    qualifiedName;
    genericTypes;
    tokenTypes = /* @__PURE__ */ new Set();
    concreteAndAbstract = new Set(concreteAndAbstractTypes);
    constructor(file, tokenTypes) {
      super(file);
      this.tokenTypes = tokenTypes;
    }
    parseText(text) {
      if (text.trim().length > 0) {
        this.file.language().addNodesForTypeGeneric(this);
        super.parseText(text);
      }
    }
    symbolCompletion_tokenTypes() {
      if (this.getElements().length === 0) {
        return this.concreteAndAbstract;
      } else {
        return super.symbolCompletion_tokenTypes();
      }
    }
    renderAsHtml() {
      return this.isValid() ? this.file.language().typeGenericAsHtml(this) : this.matchedText;
    }
    renderAsElanSource() {
      return this.isValid() ? `${this.qualifiedName?.renderAsElanSource()}<${ofKeyword} ${this.genericTypes?.renderAsElanSource()}>` : this.matchedText;
    }
    renderAsExport() {
      return this.isValid() ? `${removeHtmlTagsAndEscChars(this.renderAsHtml())}` : this.matchedText;
    }
  };

  // src/ide/frames/parse-nodes/type-name-use.ts
  var TypeNameUse = class extends AbstractParseNode {
    tokenTypes = /* @__PURE__ */ new Set();
    elanTypeName = "";
    constructor(file, tokenTypes = /* @__PURE__ */ new Set([
      7 /* type_abstract */,
      6 /* type_concrete */,
      9 /* type_notInheritable */,
      8 /* type_enum */
    ])) {
      super(file);
      this.completionWhenEmpty = "<i>Type</i>";
      this.tokenTypes = tokenTypes;
    }
    attemptToMatchStandardType(text, langName, elanName) {
      if (text.startsWith(langName)) {
        this.status = 3 /* valid */;
        this.matchedText = langName;
        this.remainingText = text.substring(langName.length);
        this.elanTypeName = elanName;
      } else if (text.length === 0 || langName.startsWith(text)) {
        this.status = 2 /* incomplete */;
        this.matchedText = text;
        this.remainingText = "";
        this.elanTypeName = text;
      } else {
        this.status = 0 /* invalid */;
      }
    }
    parseText(text) {
      this.remainingText = text;
      const lang = this.file.language();
      if (text.length > 0) {
        this.attemptToMatchStandardType(text, lang.INT_NAME, "Int");
        if (this.status === 0 /* invalid */) {
          this.attemptToMatchStandardType(text, lang.FLOAT_NAME, "Float");
        }
        if (this.status === 0 /* invalid */) {
          this.attemptToMatchStandardType(text, lang.BOOL_NAME, "Boolean");
        }
        if (this.status === 0 /* invalid */) {
          this.attemptToMatchStandardType(text, lang.STRING_NAME, "String");
        }
        if (this.status === 0 /* invalid */) {
          this.attemptToMatchStandardType(text, lang.LIST_NAME, "List");
        }
        if (this.status === 0 /* invalid */) {
          [this.status, this.matchedText, this.remainingText] = matchRegEx(
            text,
            Regexes.typeSimpleName
          );
          this.elanTypeName = this.matchedText;
          if (ReservedWords.Instance.matchesIgnoringCase(this.matchedText)) {
            this.status = 0 /* invalid */;
            this.matchedText = "";
            this.message = `matches a reserved word.`;
          }
        }
      }
    }
    renderAsHtml() {
      return `<el-type>${this.renderAsExport()}</el-type>`;
    }
    renderAsElanSource() {
      return this.elanTypeName;
    }
    symbolCompletion_tokenTypes() {
      return this.tokenTypes;
    }
    renderAsExport() {
      const lang = this.file.language();
      const elan = this.elanTypeName;
      let target = elan;
      if (elan === "Int") {
        target = lang.INT_NAME;
      } else if (elan === "Float") {
        target = lang.FLOAT_NAME;
      } else if (elan === "Boolean") {
        target = lang.BOOL_NAME;
      } else if (elan === "String") {
        target = lang.STRING_NAME;
      } else if (elan === "List") {
        target = lang.LIST_NAME;
      }
      return target;
    }
  };

  // src/ide/frames/parse-nodes/type-tuple-node.ts
  var TypeTupleNode = class extends AbstractSequence {
    types;
    tupleTypeName = "";
    parseText(text) {
      if (text.trim().length > 0) {
        this.file.language().addNodesForTypeTuple(this);
        super.parseText(text);
      }
    }
    renderAsHtml() {
      return this.isValid() ? this.file.language().typeTupleAsHtml(this) : this.matchedText;
    }
    renderAsExport() {
      return this.isValid() ? super.renderAsExport() : this.matchedText;
    }
    renderAsElanSource() {
      return `(${this.types?.renderAsElanSource()})`;
    }
  };

  // src/ide/frames/parse-nodes/type-node.ts
  var TypeNode = class extends AbstractAlternatives {
    tokenTypes = /* @__PURE__ */ new Set();
    constructor(file, tokenTypes = /* @__PURE__ */ new Set()) {
      super(file);
      this.completionWhenEmpty = "<i>Type</i>";
      this.tokenTypes = tokenTypes;
    }
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        if (text.trimStart().startsWith("Func")) {
          this.alternatives.push(new TypeFuncNode(this.file));
        } else if (text.trimStart().startsWith(OPEN_BRACKET) || text.trimStart().startsWith("tuple")) {
          this.alternatives.push(new TypeTupleNode(this.file));
        } else {
          this.alternatives.push(new TypeNameUse(this.file, this.tokenTypes));
          this.alternatives.push(new TypeGenericNode(this.file, this.tokenTypes));
        }
        super.parseText(text.trimStart());
      }
    }
    symbolCompletion_tokenTypes() {
      return this.matchedText.length === 0 ? this.tokenTypes : super.symbolCompletion_tokenTypes();
    }
  };

  // src/ide/frames/fields/type-field.ts
  var TypeField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this.useHtmlTags = true;
      this.setPlaceholder("<i>Type</i>");
    }
    helpId() {
      return "TypeField";
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_type`;
    }
    initialiseRoot() {
      this.rootNode = new TypeNode(
        this.getFile(),
        /* @__PURE__ */ new Set([
          6 /* type_concrete */,
          7 /* type_abstract */,
          9 /* type_notInheritable */
        ])
      );
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readToEndOfLine();
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
  };

  // src/ide/frames/parent-helpers.ts
  function worstParseStatus(prev, cur) {
    return cur < prev ? cur : prev;
  }
  function parentHelper_readWorstParseStatusOfChildren(parent) {
    return parent.getChildren().map((s) => s.readParseStatus()).reduce(worstParseStatus, 4 /* default */);
  }
  function parentHelper_readWorstCompileStatusOfChildren(parent) {
    return parent.getChildren().map((s) => s.readCompileStatus()).reduce((prev, cur) => cur < prev ? cur : prev, 4 /* default */);
  }
  function parentHelper_removeChild(parent, child) {
    const i = parent.getChildren().indexOf(child);
    if (i >= 0) {
      parent.getChildren().splice(i, 1);
    } else {
      parent.getFile().getMap().delete(child.getHtmlId());
    }
    child.deselect();
  }
  function parentHelper_removeAllSelectedChildren(parent) {
    const selected = parentHelper_getAllSelectedChildren(parent);
    const nonSelectors = selected.filter((s) => !(s.initialKeywords() === "selector"));
    for (const child of nonSelectors) {
      parentHelper_removeChild(parent, child);
    }
    return selected;
  }
  function parentHelper_getFirstChild(parent) {
    return parent.getChildren()[0];
  }
  function parentHelper_getLastChild(parent) {
    return parent.getChildren()[parent.getChildren().length - 1];
  }
  function parentHelper_getChildAfter(parent, child) {
    const index = parent.getChildren().indexOf(child);
    return index < parent.getChildren().length - 1 ? parent.getChildren()[index + 1] : child;
  }
  function parentHelper_getChildBefore(parent, child) {
    const index = parent.getChildren().indexOf(child);
    return index > 0 ? parent.getChildren()[index - 1] : child;
  }
  function parentHelper_getChildRange(parent, first, last) {
    const fst = parent.getChildren().indexOf(first);
    const lst = parent.getChildren().indexOf(last);
    return fst < lst ? parent.getChildren().slice(fst, lst + 1) : parent.getChildren().slice(lst, fst + 1);
  }
  function parentHelper_getFirstSelectorAsDirectChild(parent) {
    return parent.getChildren().filter((g) => isSelector(g))[0];
  }
  function parentHelper_selectFirstChild(parent, multiSelect) {
    if (parent.getChildren().length > 0) {
      parent.getChildren()[0].select(true, multiSelect);
      return true;
    }
    return false;
  }
  function parentHelper_addChildBefore(parent, child, before) {
    const i = parent.getChildren().indexOf(before);
    child.setParent(parent);
    parent.getChildren().splice(i, 0, child);
  }
  function parentHelper_addChildAfter(parent, child, after) {
    const i = parent.getChildren().indexOf(after) + 1;
    parent.getChildren().splice(i, 0, child);
  }
  function parentHelper_renderChildrenAsHtml(parent) {
    const ss = [];
    for (const m of parent.getChildren()) {
      ss.push(m.renderAsHtml());
    }
    return ss.join("\n");
  }
  function isNotSelectorFrame(f) {
    return !!f && !("isSelector" in f);
  }
  function parentHelper_renderChildrenAsElanSource(parent) {
    let result = "";
    if (parent.getChildren().length > 0) {
      const ss = [];
      for (const frame of parent.getChildren().filter(isNotSelectorFrame)) {
        ss.push(frame.renderAsElanSource());
      }
      result = ss.join("\r\n");
    }
    return result;
  }
  function parentHelper_renderChildrenAsExport(parent) {
    let result = "";
    if (parent.getChildren().length > 0) {
      const ss = [];
      for (const frame of parent.getChildren().filter(isNotSelectorFrame)) {
        ss.push(frame.renderAsExport());
      }
      const joiner = parent.hasParent() ? "\r\n" : "\r\n\r\n";
      result = ss.join(joiner);
    }
    return result;
  }
  function parentHelper_insertOrGotoChildSelector(parent, after, child) {
    if (after) {
      return insertOrGotoChildSelectorAfter(parent, child);
    } else {
      return insertOrGotoChildSelectorBefore(parent, child);
    }
  }
  function insertOrGotoChildSelectorBefore(parent, child) {
    const prev = parent.getChildBefore(child);
    if (isSelector(prev)) {
      prev.select(true, false);
      return prev;
    } else {
      const selector = parent.newChildSelector();
      parent.addChildBefore(selector, child);
      selector.select(true, false);
      return selector;
    }
  }
  function insertOrGotoChildSelectorAfter(parent, child) {
    const follow = parent.getChildAfter(child);
    if (isSelector(follow)) {
      follow.select(true, false);
      return follow;
    } else {
      const selector = parent.newChildSelector();
      parent.addChildAfter(selector, child);
      selector.select(true, false);
      return selector;
    }
  }
  function parentHelper_getAllSelectedChildren(parent) {
    return parent.getChildren().filter((g) => g.isSelected());
  }
  function parentHelper_deleteSelectedChildren(parent) {
    const toDelete = parentHelper_getAllSelectedChildren(parent);
    for (let i = toDelete.length - 1; i >= 0; i--) {
      toDelete[i].deleteIfPermissible();
    }
  }
  function isValidOrIncomplete(f) {
    const status = f.readParseStatus();
    return status === 3 /* valid */ || status === 2 /* incomplete */;
  }
  function parentHelper_copySelectedChildren(parent, encode) {
    const toCopy = parentHelper_getAllSelectedChildren(parent);
    if (toCopy.some((tc) => !isValidOrIncomplete(tc))) {
      return false;
    }
    for (const tc of toCopy) {
      tc.copy(encode);
    }
    return true;
  }
  function parentHelper_exportSelectedChildren(parent) {
    const toExport = parentHelper_getAllSelectedChildren(parent);
    if (toExport.some((tc) => !isValidOrIncomplete(tc))) {
      return false;
    }
    for (const tc of toExport) {
      tc.export();
    }
    return true;
  }
  function parentHelper_moveSelectedChildrenUpOne(parent) {
    const toMove = parentHelper_getAllSelectedChildren(parent);
    let cont = true;
    let i = 0;
    while (cont && i < toMove.length) {
      cont = moveUpOne(parent, toMove[i]);
      i++;
    }
  }
  function parentHelper_moveSelectedChildrenDownOne(parent) {
    const toMove = parentHelper_getAllSelectedChildren(parent);
    let cont = true;
    let i = toMove.length - 1;
    while (cont && i >= 0) {
      cont = moveDownOne(parent, toMove[i]);
      i--;
    }
  }
  function moveDownOne(parent, child) {
    let result = false;
    const i = parent.getChildren().indexOf(child);
    if (i < parent.getChildren().length - 1 && parent.getChildren()[i + 1].canInsertAfter()) {
      parent.getChildren().splice(i, 1);
      parent.getChildren().splice(i + 1, 0, child);
      result = true;
    }
    return result;
  }
  function moveUpOne(parent, child) {
    let result = false;
    const i = parent.getChildren().indexOf(child);
    if (i > 0 && parent.getChildren()[i - 1].canInsertBefore()) {
      parent.getChildren().splice(i, 1);
      parent.getChildren().splice(i - 1, 0, child);
      result = true;
    }
    return result;
  }
  function parentHelper_updateBreakpoints(parent, event) {
    for (const frame of parent.getChildren()) {
      frame.updateBreakpoints(event);
    }
  }
  function setGhostOnSelectedChildren(parent, ghost) {
    const toGhost = parentHelper_getAllSelectedChildren(parent);
    for (const child of toGhost) {
      if (child.isGhostable()) {
        child.setGhosted(ghost);
      }
    }
  }
  function parentHelper_resetFieldTextOnChildren(parent) {
    for (const frame of parent.getChildren()) {
      frame.resetFieldText();
    }
  }

  // src/ide/frames/abstract-frame.ts
  var AbstractFrame = class {
    isFrame = true;
    isNew = true;
    breakpointStatus = 0 /* none */;
    pasteError = "";
    helpActive = false;
    id = "";
    ghostable = true;
    canHaveBreakPoint = true;
    showContextMenu = false;
    paused = false;
    _parent;
    _selected = false;
    _focused = false;
    _collapsed = false;
    _classes = new Array();
    _movable = true;
    _parseStatus = 4 /* default */;
    _ghosted = false;
    constructor(parent) {
      this._parent = parent;
      const file = this.getFile();
      this.id = `${file.getNextId()}`;
      file.getMap().set(this.htmlId, this);
    }
    get htmlId() {
      return `${this.getIdPrefix()}${this.id}`;
    }
    helpId() {
      return this.initialKeywords().replace(/\s/g, "");
    }
    helpAsHtml() {
      const active = this.helpActive ? ` class="active"` : "";
      this.helpActive = false;
      return this._selected ? `<el-help title="Click to open Help for this instruction"> <a href="documentation/LangRef.html#${this.helpId()}" target="help-iframe" tabindex="-1"${active}>?</a></el-help>` : ``;
    }
    showHelp() {
      this.helpActive = true;
    }
    hasBeenAddedTo() {
      this.isNew = false;
    }
    isMovable() {
      return this._movable;
    }
    isDeletable() {
      return true;
    }
    getFile() {
      return this.getParent().getFile();
    }
    getHtmlId() {
      return this.htmlId;
    }
    getFrNo() {
      return this.isGhostedOrWithinAGhostedFrame() ? "" : this.getFile().getFrNo();
    }
    fieldUpdated(_field) {
    }
    getFirstPeerFrame() {
      return this.getParent().getFirstChild();
    }
    getLastPeerFrame() {
      return this.getParent().getLastChild();
    }
    getPreviousPeerFrame() {
      return this.getParent().getChildBefore(this);
    }
    getNextPeerFrame() {
      return this.getParent().getChildAfter(this);
    }
    selectFieldBefore(current) {
      const fields = this.getFields();
      const i = fields.indexOf(current);
      if (i > 0) {
        this.getFields()[i - 1].select(true, false);
      } else {
        this.select(true, false);
      }
    }
    selectFieldAfter(current) {
      const fields = this.getFields();
      const i = fields.indexOf(current);
      if (i < fields.length - 1) {
        fields[i + 1].select(true, false);
      } else {
        this.select(true, false);
      }
    }
    getNextFrameInTabOrder() {
      let result = this;
      if (this.getNextPeerFrame() !== this) {
        result = this.getNextPeerFrame();
      } else {
        const parent = this.getParent();
        if (isFrame(parent)) {
          const parentNextPeer = parent.getNextFrameInTabOrder();
          if (parentNextPeer !== parent) {
            result = parentNextPeer;
          }
        }
      }
      return result;
    }
    getPreviousFrameInTabOrder() {
      let result = this;
      if (this.getPreviousPeerFrame() !== this) {
        result = this.getPreviousPeerFrame();
      } else {
        const parent = this.getParent();
        if (isFrame(parent)) {
          result = parent.getPreviousFrameInTabOrder();
        }
      }
      return result;
    }
    //Overridden by any frames that have children
    selectFirstField() {
      let result = false;
      if (this.getFields().length > 0) {
        this.getFields()[0].select(true, false);
        result = true;
      }
      return result;
    }
    selectLastField() {
      let result = false;
      const length = this.getFields().length;
      if (length > 0) {
        this.getFields()[length - 1].select(true, false);
        result = true;
      }
      return result;
    }
    controlKeys = [
      "o",
      "O",
      "ArrowUp",
      "ArrowDown",
      "Backspace",
      "Delete",
      "x",
      "m",
      "c",
      "?"
    ];
    processKey(e) {
      let codeHasChanged = false;
      const key = e.key;
      if (e.modKey.control && !this.controlKeys.includes(key ?? "")) {
        return false;
      }
      switch (key) {
        case "Home": {
          this.getFirstPeerFrame().select(true, false);
          break;
        }
        case "End": {
          this.getLastPeerFrame().select(true, false);
          break;
        }
        case "o": {
          if (e.modKey.control && isCollapsible(this)) {
            this.expandCollapse();
          }
          break;
        }
        case "O": {
          if (e.modKey.control) {
            this.expandCollapseAll();
          }
          break;
        }
        case "t": {
          if (e.modKey.alt) {
            this.getFile().removeAllSelectorsThatCanBe();
          }
          break;
        }
        case "ArrowUp": {
          if (e.modKey.control) {
            this.up();
          } else {
            this.selectSingleOrMulti(this.getPreviousPeerFrame(), e.modKey.shift);
          }
          break;
        }
        case "ArrowDown": {
          if (e.modKey.control) {
            this.down();
          } else {
            this.selectSingleOrMulti(this.getNextPeerFrame(), e.modKey.shift);
          }
          break;
        }
        case "ArrowLeft": {
          const pt = this.getParent();
          if (isFrame(pt)) {
            pt.select(true, false);
          }
          break;
        }
        case "ArrowRight": {
          if (isParent(this)) {
            this.getFirstChild().select(true, false);
          }
          break;
        }
        case "Enter": {
          this.insertPeerSelector(e.modKey.shift);
          break;
        }
        case "Tab": {
          if (e.modKey.shift) {
            this.selectLastField();
          } else {
            this.selectFirstField();
          }
          break;
        }
        case "Delete": {
          if (e.modKey.control) {
            this.deleteSelected();
            codeHasChanged = true;
          }
          break;
        }
        case "Backspace": {
          if (e.modKey.control || this.isNew) {
            this.deleteSelected();
            codeHasChanged = true;
          }
          break;
        }
        case "Escape": {
          this.showContextMenu = false;
          break;
        }
        case "c": {
          if (e.modKey.control) {
            this.copySelected(e.modKey.alt);
            codeHasChanged = true;
          }
          break;
        }
        case "x": {
          if (e.modKey.control) {
            this.cutSelected();
            codeHasChanged = true;
          }
          break;
        }
        case "?": {
          if (e.modKey.control) {
            this.showHelp();
          }
          break;
        }
        case "m": {
          if (!e.modKey.control) {
            break;
          }
        }
        case "ContextMenu": {
          if (e.command) {
            const map = this.getContextMenuItems();
            codeHasChanged = map.get(e.command)[1]?.(e.optionalData);
          } else {
            if (!this.isSelected()) {
              this.select(true, false);
            }
            this.showContextMenu = true;
          }
          break;
        }
      }
      return codeHasChanged;
    }
    up = () => {
      if (this.isMovable()) {
        this.getParent().moveSelectedChildrenUpOne();
        return true;
      }
      return false;
    };
    down = () => {
      if (this.isMovable()) {
        this.getParent().moveSelectedChildrenDownOne();
        return true;
      }
      return false;
    };
    deleteSelected = () => {
      this.getParent().deleteSelectedChildren();
      return true;
    };
    copySelected = (encode) => {
      if (!this.getParent().copySelectedChildren(encode)) {
        this.pasteError = "Copy Failed: At least one selected frame does not parse";
        return true;
      }
      return false;
    };
    exportSelected = () => {
      if (!this.getParent().exportSelectedChildren()) {
        this.pasteError = "Copy Failed: At least one selected frame does not parse";
        return true;
      }
      return false;
    };
    cutSelected = () => {
      const selected = parentHelper_getAllSelectedChildren(this.getParent());
      const nonSelectors = selected.filter((s) => !(s.initialKeywords() === "selector"));
      if (nonSelectors.length === 0) {
        this.pasteError = "Cut Failed: No code to cut";
        return true;
      }
      const movable = nonSelectors.filter((s) => s.isMovable());
      if (movable.length !== nonSelectors.length) {
        this.pasteError = "Cut Failed: At least one selected frame is not moveable";
        return true;
      }
      if (!parentHelper_copySelectedChildren(this.getParent(), false)) {
        this.pasteError = "Cut Failed: At least one selected frame does not parse";
        return true;
      }
      parentHelper_removeAllSelectedChildren(this.getParent());
      const last = selected[selected.length - 1];
      const newFocus = parentHelper_getChildAfter(this.getParent(), last);
      newFocus.select(true, false);
      if (!isSelector(newFocus) && !newFocus.getParent().minimumNumberOfChildrenExceeded()) {
        newFocus.insertPeerSelector(false);
      }
      return true;
    };
    deleteIfPermissible() {
      if (this.isDeletable()) {
        this.insertNewSelectorIfNecessary();
        this.delete();
      }
    }
    delete() {
      const parent = this.getParent();
      const newFocus = this.getAdjacentPeer();
      parent.removeChild(this);
      this.getMap().delete(this.htmlId);
      newFocus.select(true, false);
    }
    insertNewSelectorIfNecessary() {
      if (!this.getParent().minimumNumberOfChildrenExceeded()) {
        this.insertPeerSelector(true);
      }
    }
    getAdjacentPeer() {
      const parent = this.getParent();
      let adjacent = parent.getChildAfter(this);
      if (adjacent === this) {
        adjacent = parent.getChildBefore(this);
      }
      return adjacent;
    }
    insertSelectorAfterLastField() {
      this.insertPeerSelector(false);
    }
    selectNextFrame() {
      const parent = this.getParent();
      let next = parent.getChildAfter(this);
      if (next === this) {
        if (isFrame(parent)) {
          next = parent;
        }
      }
      next.select(true, false);
    }
    above = () => {
      this.insertPeerSelector(true);
      return false;
    };
    below = () => {
      this.insertPeerSelector(false);
      return false;
    };
    insertPeerSelector(before) {
      const parent = this.getParent();
      if (before && this.canInsertBefore()) {
        parent.insertOrGotoChildSelector(false, this);
      } else if (!before && this.canInsertAfter()) {
        parent.insertOrGotoChildSelector(true, this);
      }
    }
    canInsertBefore() {
      return true;
    }
    canInsertAfter() {
      return true;
    }
    selectSingleOrMulti(other, multiSelect) {
      if (multiSelect && other.isSelected()) {
        this.deselect();
        other.select(true, true);
      } else if (multiSelect) {
        this.select(false, true);
        other.select(true, true);
      } else {
        other.select(true, false);
      }
    }
    getMap() {
      return this.getFile().getMap();
    }
    pushClass(flag, cls) {
      if (flag) {
        this._classes.push(cls);
      }
    }
    setClasses() {
      this._classes = new Array();
      this.pushClass(this._collapsed, "collapsed");
      this.pushClass(this._selected, "selected");
      this.pushClass(this._focused, "focused");
      this.pushClass(this.breakpointStatus !== 0 /* none */, "breakpoint");
      this.pushClass(this.paused, "paused");
      this.pushClass(this.isGhosted(), ghostedAnnotation);
      this._classes.push(DisplayColour[this.readDisplayStatus()]);
    }
    readDisplayStatus() {
      return helper_CompileOrParseAsDisplayStatus(this);
    }
    cls() {
      this.setClasses();
      return this._classes.join(" ");
    }
    indent() {
      if (this.hasParent()) {
        return this.getParent().indent() + singleIndent();
      } else {
        return singleIndent();
      }
    }
    isSelected() {
      return this._selected;
    }
    onClick(withFocus, multiSelect) {
      this.select(withFocus, multiSelect);
    }
    select(withFocus, multiSelect) {
      if (!multiSelect) {
        this.deselectAll();
      }
      this._selected = true;
      this._focused = withFocus;
    }
    deselect() {
      this._selected = false;
      this._focused = false;
    }
    deselectAll() {
      for (const f of this.getMap().values()) {
        if (f.isSelected()) {
          f.deselect();
        }
      }
    }
    getAllSelected() {
      const selected = [];
      for (const f of this.getMap().values()) {
        if (f.isSelected()) {
          selected.push(f);
        }
      }
      return selected;
    }
    hasParent() {
      return !!this._parent;
    }
    setParent(parent) {
      this._parent = parent;
    }
    getParent() {
      if (this._parent) {
        return this._parent;
      }
      throw new Error(`Frame : ${this.htmlId} has no Parent`);
    }
    expandCollapse() {
      if (this.isCollapsed()) {
        this.expand();
      } else {
        this.collapse();
      }
    }
    expandCollapseAll() {
      expandCollapseAll(this.getFile());
    }
    isCollapsed() {
      return this._collapsed;
    }
    collapse() {
      if (isCollapsible(this)) {
        this._collapsed = true;
      }
    }
    expand() {
      if (isCollapsible(this)) {
        this._collapsed = false;
      }
    }
    isFocused() {
      return this._focused;
    }
    focus() {
      this._focused = true;
    }
    defocus() {
      this._focused = false;
    }
    isComplete() {
      return true;
    }
    updateParseStatus() {
      this._parseStatus = this.worstParseStatusOfFields();
    }
    updateDirectives() {
    }
    worstParseStatusOfFields() {
      return this.getFields().map((g) => g.readParseStatus()).reduce((prev, cur) => cur < prev ? cur : prev, 3 /* valid */);
    }
    readParseStatus() {
      return this._parseStatus;
    }
    setParseStatus(newStatus) {
      this._parseStatus = newStatus;
    }
    worstCompileStatusOfFields() {
      return this.getFields().map((g) => g.readCompileStatus()).reduce((prev, cur) => cur < prev ? cur : prev, 4 /* default */);
    }
    readCompileStatus() {
      const own = helper_deriveCompileStatusFromErrors(
        this.getFile().getAst(false)?.getCompileErrorsFor(this.htmlId) ?? []
      );
      const worstField = this.worstCompileStatusOfFields();
      return Math.min(own, worstField);
    }
    compileMsgAsHtml() {
      return helper_compileMsgAsHtmlNew(this.getFile(), this);
    }
    copy = (encode) => {
      const source = this.renderAsElanSource();
      this.getFile().addCopiedSource(encode ? escapeHtmlChars(source) : source);
      return false;
    };
    export = () => {
      const source = this.renderAsExport();
      this.getFile().addCopiedSource(source);
      return false;
    };
    getNextState(currentState, event) {
      switch (currentState) {
        case 0 /* none */:
          switch (event) {
            case 0 /* clear */:
              return 0 /* none */;
            case 1 /* activate */:
              return 3 /* singlestep */;
            case 2 /* disable */:
              return 0 /* none */;
          }
        case 1 /* disabled */:
          switch (event) {
            case 0 /* clear */:
              return 0 /* none */;
            case 1 /* activate */:
              return 2 /* active */;
            case 2 /* disable */:
              return 1 /* disabled */;
          }
        case 2 /* active */:
          switch (event) {
            case 0 /* clear */:
              return 0 /* none */;
            case 1 /* activate */:
              return 2 /* active */;
            case 2 /* disable */:
              return 1 /* disabled */;
          }
        case 3 /* singlestep */:
          switch (event) {
            case 0 /* clear */:
              return 0 /* none */;
            case 1 /* activate */:
              return 3 /* singlestep */;
            case 2 /* disable */:
              return 0 /* none */;
          }
      }
    }
    updateBreakpoints(event) {
      this.breakpointStatus = this.getNextState(this.breakpointStatus, event);
    }
    setBreakPoint = () => {
      this.breakpointStatus = 2 /* active */;
      return false;
    };
    clearBreakPoint = () => {
      this.breakpointStatus = 0 /* none */;
      return false;
    };
    toggleBreakPoint = () => {
      if (this.hasBreakpoint()) {
        this.clearBreakPoint();
      } else {
        this.setBreakPoint();
      }
    };
    clearAllBreakPoints = () => {
      this.getFile().updateBreakpoints(0 /* clear */);
      return false;
    };
    hasBreakpoint() {
      return this.breakpointStatus === 2 /* active */ || this.breakpointStatus === 1 /* disabled */;
    }
    isGhostable() {
      return this.ghostable;
    }
    setGhosted(flag) {
      this._ghosted = flag;
    }
    ghost = () => {
      this.getParent().ghostSelectedChildren();
      return true;
    };
    unGhost = () => {
      this.getParent().unghostSelectedChildren();
      return true;
    };
    isGhosted() {
      return this._ghosted;
    }
    isGhostedOrWithinAGhostedFrame() {
      return this.isGhosted() || this.getParent().isGhostedOrWithinAGhostedFrame();
    }
    deleteAllGhostedInFile = () => {
      this.getFile().deleteAllGhosted();
      return true;
    };
    sourceAnnotations() {
      return this.isGhosted() ? `[${ghostedAnnotation}] ` : "";
    }
    getContextMenuItems() {
      const map = /* @__PURE__ */ new Map();
      if (this.isGhosted()) {
        map.set("unghost", ["unghost", this.unGhost]);
      }
      if (this.canInsertAfter()) {
        map.set("below", ["insert new code below <span class='kb'>Enter</span>", this.below]);
      }
      if (this.canInsertBefore()) {
        map.set("above", ["insert new code above <span class='kb'>Shift+Enter</span>", this.above]);
      }
      if (this.isDeletable()) {
        addDeleteToContextMenu(this, map);
      }
      if (this.isGhosted()) {
        map.set("deleteGhosted", ["delete ALL ghosted code", this.deleteAllGhostedInFile]);
      }
      if (this.isMovable()) {
        map.set("up", ["move up <span class='kb'>Ctrl+\u2191</span>", this.up]);
        map.set("down", ["move down <span class='kb'>Ctrl+\u2193</span>", this.down]);
      }
      if (this.isDeletable()) {
        map.set("cut", ["cut for internal use <span class='kb'>Ctrl+x</span>", this.cutSelected]);
      }
      map.set("copyInternal", [
        "copy for internal use <span class='kb'>Ctrl+c</span>",
        () => this.copySelected(false)
      ]);
      if (!(this.language().languageHtmlClass === "elan")) {
        map.set("copyExport", ["copy for export", this.exportSelected]);
      }
      if (!this.isGhosted() && this.isGhostable()) {
        map.set("ghost", ["ghost", this.ghost]);
      }
      if (this.canHaveBreakPoint && !this.isGhosted()) {
        if (this.hasBreakpoint()) {
          map.set("clearBP", ["clear breakpoint", this.clearBreakPoint]);
          map.set("clearAllBP", ["clear all breakpoints", this.clearAllBreakPoints]);
        } else {
          map.set("setBP", ["set breakpoint", this.setBreakPoint]);
        }
      }
      return map;
    }
    contextMenu() {
      if (this.showContextMenu) {
        this.showContextMenu = false;
        const items = [];
        const map = this.getContextMenuItems();
        for (const k of map.keys()) {
          let val = map.get(k)[0];
          let cls = "context-menu-item";
          if (val.startsWith("separator ")) {
            val = val.substring(10);
            cls += " separator";
          }
          items.push(
            `<div class='${cls}' data-id='${this.htmlId}' data-func="${k}" title="" tabindex="-1">${val}</div>`
          );
        }
        return `<div class='context-menu'>${items.join("")}</div>`;
      }
      return "";
    }
    bpAsHtml() {
      return this.hasBreakpoint() ? `<el-bp>&#x1f5f2;</el-bp>` : "";
    }
    toolTip() {
      return ``;
    }
    deleteAllGhosted() {
      if (this.isGhosted()) {
        this.insertNewSelectorIfNecessary();
        this.delete();
      }
    }
    annotationAsHtml() {
      const source = this.annotationAsSource();
      return source.length > 0 ? `<el-comment>${source}</el-comment>` : ``;
    }
    annotationAsSource() {
      const annotation = this.language().annotation(this).trim();
      return annotation.length > 0 ? ` ${this.language().COMMENT_MARKER} ${annotation}` : ``;
    }
    language() {
      return this._parent.language();
    }
    resetFieldText() {
      for (const field of this.getFields()) {
        field.resetText();
      }
    }
  };

  // src/ide/frames/single-line-frame.ts
  var SingleLineFrame = class extends AbstractFrame {
    outerHtmlTag = "el-statement";
    // Overridden by non-statement single line frames
    renderAsHtml() {
      return `<${this.outerHtmlTag} class="${this.cls()}" id='${this.htmlId}' tabindex="-1" ${this.toolTip()}>${this.contextMenu()}<el-top>${this.bpAsHtml()}${this.language().renderSingleLineAsHtml(this)}</el-top>${this.helpAsHtml()}${this.compileMsgAsHtml()}${this.annotationAsHtml()}${this.getFrNo()}</${this.outerHtmlTag}>`;
    }
    renderAsExport() {
      return `${this.indent()}${removeHtmlTagsAndEscChars(this.renderAsHtml())}`;
    }
  };

  // src/ide/frames/class-members/abstract-function.ts
  var AbstractFunction = class extends SingleLineFrame {
    isAbstract = true;
    isMember = true;
    private = false;
    name;
    params;
    returnType;
    hrefForFrameHelp = "LangRef.html#Abstract_function";
    constructor(parent) {
      super(parent);
      this.name = new MethodNameField(this);
      this.params = new ParamListField(this);
      this.returnType = new TypeField(this);
      this.canHaveBreakPoint = false;
    }
    initialKeywords() {
      return abstractFunctionKeywords;
    }
    getFields() {
      return [this.name, this.params, this.returnType];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_func`;
    }
    frameSpecificAnnotation() {
      return "abstract function";
    }
    indent() {
      return singleIndent();
    }
    outerHtmlTag = "el-func";
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}${abstractKeyword} ${functionKeyword} ${this.name.renderAsElanSource()}(${this.params.renderAsElanSource()}) ${returnsKeyword} ${this.returnType.renderAsElanSource()}\r
`;
    }
    parseFrom(source) {
      source.remove(`${abstractKeyword} ${functionKeyword} `);
      this.name.parseFrom(source);
      source.remove("(");
      this.params.parseFrom(source);
      source.remove(`) ${returnsKeyword} `);
      this.returnType.parseFrom(source);
    }
    renderAsExport() {
      return `${super.renderAsExport()}\r
`;
    }
  };

  // src/ide/frames/class-members/abstract-procedure.ts
  var AbstractProcedure = class extends SingleLineFrame {
    isAbstract = true;
    isMember = true;
    private = false;
    name;
    params;
    constructor(parent) {
      super(parent);
      this.name = new MethodNameField(this);
      this.params = new ParamListField(this);
      this.canHaveBreakPoint = false;
    }
    initialKeywords() {
      return abstractProcedureKeywords;
    }
    getFields() {
      return [this.name, this.params];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_proc`;
    }
    frameSpecificAnnotation() {
      return "abstract procedure";
    }
    indent() {
      return singleIndent();
    }
    outerHtmlTag = "el-proc";
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}abstract procedure ${this.name.renderAsElanSource()}(${this.params.renderAsElanSource()})\r
`;
    }
    parseFrom(source) {
      source.remove("abstract procedure ");
      this.name.parseFrom(source);
      source.remove("(");
      this.params.parseFrom(source);
      source.remove(")");
    }
    renderAsExport() {
      return `${super.renderAsExport()}\r
`;
    }
  };

  // src/ide/frames/parse-nodes/operator.ts
  var Operator = class extends AbstractParseNode {
    elanOp;
    langOp;
    constructor(file, elanOp, langOp) {
      super(file);
      this.elanOp = elanOp;
      this.langOp = langOp ? langOp : (lang) => lang ? elanOp : elanOp;
      this.completionWhenEmpty = "";
    }
    parseText(text) {
      if (text.length > 0) {
        const langOp = this.langOp(this.file.language());
        const trimmed = text.trimStart();
        if (trimmed.startsWith(langOp)) {
          const n = this.numLeadingSpaces(text) + langOp.length;
          this.set(3 /* valid */, text.substring(0, n), text.substring(n));
          this._done = true;
        } else if (langOp.startsWith(trimmed)) {
          this.set(2 /* incomplete */, text, "");
        } else {
          this.set(0 /* invalid */, "", text);
        }
      }
    }
    renderAsElanSource() {
      const closePacked = this.elanOp === MULT || this.elanOp === DIVIDE;
      const space = closePacked ? "" : " ";
      return `${space}${this.elanOp}${space}`;
    }
    renderAsHtml() {
      const langOp = this.langOp(this.file.language());
      let text = langOp;
      if (text.includes(`<`) || text.includes(`>`)) {
        text = escapeHtmlChars(langOp);
      }
      const alpha = /^[a-zA-Z]/;
      const kw = alpha.test(text);
      const closePacked = langOp === MULT || langOp === DIVIDE;
      const open = kw ? "<el-kw>" : "";
      const close = kw ? "</el-kw>" : "";
      const space = closePacked ? "" : " ";
      return this.isValid() ? `${open}${space}${text}${space}${close}` : this.matchedText;
    }
    renderAsExport() {
      return this.isValid() ? `${removeHtmlTagsAndEscChars(this.renderAsHtml())}` : this.matchedText;
    }
  };

  // src/ide/frames/parse-nodes/binary-operation.ts
  var BinaryOperation = class extends AbstractAlternatives {
    constructor(file) {
      super(file);
      this.completionWhenEmpty = "<i>operator </i>";
    }
    keywords = [];
    elanEQUAL = "is";
    elanNOT_EQUAL = "isnt";
    elanAND = "and";
    elanOR = "or";
    elanMOD = "mod";
    parseText(text) {
      if (text.length > 0) {
        this.remainingText = text;
        this.alternatives.push(new Operator(this.file, this.elanEQUAL, (lang) => lang.EQUAL));
        this.alternatives.push(new Operator(this.file, this.elanNOT_EQUAL, (lang) => lang.NOT_EQUAL));
        this.alternatives.push(new Operator(this.file, GT));
        this.alternatives.push(new Operator(this.file, LT));
        this.alternatives.push(new Operator(this.file, GE));
        this.alternatives.push(new Operator(this.file, LE));
        this.alternatives.push(new Operator(this.file, MULT));
        this.alternatives.push(new Operator(this.file, DIVIDE));
        this.alternatives.push(new Operator(this.file, PLUS));
        this.alternatives.push(new Operator(this.file, MINUS));
        this.alternatives.push(new Operator(this.file, this.elanAND, (lang) => lang.AND));
        this.alternatives.push(new Operator(this.file, this.elanOR, (lang) => lang.OR));
        this.alternatives.push(new Operator(this.file, this.elanMOD, (lang) => lang.MOD));
        while (this.nextChar() === " ") {
          this.moveCharsToMatched(1, 2 /* incomplete */);
        }
        super.parseText(text);
        while (this.status === 3 /* valid */ && this.nextChar() === " ") {
          this.moveCharsToMatched(1, 3 /* valid */);
        }
      }
    }
    nextChar() {
      return this.remainingText.length > 0 ? this.remainingText[0] : "";
    }
    moveCharsToMatched(n, st) {
      this.matchedText = this.matchedText + this.remainingText.slice(0, n);
      this.remainingText = this.remainingText.slice(n);
      this.status = st;
    }
    getSyntaxCompletionAsHtml() {
      let completion = "";
      if (this.matchedText === "" || this.matchedText === " ") {
        completion = "<i>operator </i>";
      }
      return completion;
    }
    symbolCompletion_keywords() {
      let kws = this.keywords.map((kw) => KeywordCompletion.create(kw));
      const trim = this.matchedText.trim();
      if (trim.length > 0) {
        kws = kws.filter((kw) => kw.keyword.startsWith(trim));
      }
      return new Set(kws);
    }
    renderAsElanSource() {
      let elan = "";
      if (this.status === 3 /* valid */) {
        const op = this.bestMatch;
        elan = op.renderAsElanSource();
      } else if (this.status === 2 /* incomplete */) {
        elan = this.matchedText;
      }
      return elan;
    }
    renderAsHtml() {
      let html = "";
      if (this.status === 3 /* valid */) {
        const op = this.bestMatch;
        html = op.renderAsHtml();
      } else if (this.status === 2 /* incomplete */) {
        html = this.matchedText;
      }
      return html;
    }
  };

  // src/ide/frames/parse-nodes/if-expr.ts
  var IfExpr = class extends AbstractSequence {
    condition;
    whenTrue;
    whenFalse;
    parseText(text) {
      if (text.trim().length > 0) {
        this.addElement(new KeywordNode(this.file, ifKeyword));
        this.addElement(new PunctuationNode(this.file, OPEN_BRACKET));
        this.condition = new ExprNode(this.file);
        this.condition.setSyntaxCompletionWhenEmpty("<i>condition </i>");
        this.addElement(this.condition);
        this.addElement(new CommaNode(this.file));
        this.whenTrue = new ExprNode(this.file);
        this.addElement(this.whenTrue);
        this.addElement(new CommaNode(this.file));
        this.whenFalse = new ExprNode(this.file);
        this.addElement(this.whenFalse);
        this.addElement(new PunctuationNode(this.file, CLOSE_BRACKET));
        super.parseText(text);
      }
    }
    symbolCompletion_keywords() {
      return this.getElements().length === 0 ? /* @__PURE__ */ new Set([KeywordCompletion.create(ifKeyword)]) : super.symbolCompletion_keywords();
    }
    renderAsHtml() {
      return this.isValid() ? `<el-method>${ifKeyword}</el-method>(${this.condition?.renderAsHtml()}, ${this.whenTrue?.renderAsHtml()}, ${this.whenFalse?.renderAsHtml()})` : this.matchedText;
    }
  };

  // src/ide/frames/parse-nodes/index-double.ts
  var IndexDouble = class extends AbstractSequence {
    index1;
    index2;
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        this.index1 = new ExprNode(this.file);
        this.index2 = new ExprNode(this.file);
        this.addElement(this.index1);
        this.addElement(new CommaNode(this.file));
        this.addElement(this.index2);
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/index-value.ts
  var IndexValue = class extends AbstractAlternatives {
    contents;
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        this.alternatives.push(new ExprNode(this.file));
        this.alternatives.push(new IndexDouble(this.file));
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/index.ts
  var Index = class extends AbstractSequence {
    contents;
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        this.addElement(new PunctuationNode(this.file, OPEN_SQ_BRACKET));
        this.contents = new IndexValue(this.file);
        this.addElement(this.contents);
        this.addElement(new PunctuationNode(this.file, CLOSE_SQ_BRACKET));
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/alternatives.ts
  var Alternatives = class extends AbstractAlternatives {
    elementConstructors;
    tokenTypes;
    context;
    constructor(file, elementConstructors, tokenTypes = /* @__PURE__ */ new Set(), context = () => "") {
      super(file);
      this.elementConstructors = elementConstructors;
      this.tokenTypes = tokenTypes;
      this.context = context;
    }
    parseText(text) {
      if (text.length > 0) {
        this.elementConstructors.forEach((ec) => {
          this.alternatives.push(ec());
        });
      }
      super.parseText(text);
    }
    symbolCompletion_tokenTypes() {
      return this.matchedText.length === 0 && this.tokenTypes.size > 0 ? this.tokenTypes : super.symbolCompletion_tokenTypes();
    }
  };

  // src/ide/frames/parse-nodes/dotted-term.ts
  var DottedTerm = class extends AbstractSequence {
    term;
    tokenTypes = /* @__PURE__ */ new Set([2 /* id_property */, 11 /* method_function */, 12 /* method_system */]);
    constructor(file) {
      super(file);
      const prop = () => new IdentifierUse(file, /* @__PURE__ */ new Set([2 /* id_property */]));
      const method = () => new MethodCallNode(file);
      this.term = new Alternatives(this.file, [prop, method], this.tokenTypes);
    }
    parseText(text) {
      if (text.length > 0) {
        this.addElement(new PunctuationNode(this.file, DOT));
        this.addElement(this.term);
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/bracketed-expression.ts
  var BracketedExpression = class extends AbstractSequence {
    expr;
    constructor(file) {
      super(file);
      this.completionWhenEmpty = "";
    }
    parseText(text) {
      if (text.length > 0) {
        this.addElement(new PunctuationNode(this.file, OPEN_BRACKET));
        this.expr = new ExprNode(this.file);
        this.addElement(this.expr);
        this.addElement(new SpaceNode(this.file, 0 /* ignored */));
        this.addElement(new PunctuationNode(this.file, CLOSE_BRACKET));
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/kvp-node.ts
  var KVPnode = class extends AbstractSequence {
    key;
    value;
    keyConstructor;
    valueConstructor;
    constructor(file, keyConstructor, valueConstructor) {
      super(file);
      this.keyConstructor = keyConstructor;
      this.valueConstructor = valueConstructor;
    }
    parseText(text) {
      if (text.length > 0) {
        this.key = this.keyConstructor();
        this.value = this.valueConstructor();
        this.addElement(this.key);
        this.addElement(new PunctuationNode(this.file, COLON));
        this.addElement(this.value);
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/dictionary-node.ts
  var DictionaryNode = class extends AbstractSequence {
    csv;
    elementConstructor;
    constructor(file, keyConstructor, valueConstructor) {
      super(file);
      this.elementConstructor = () => new KVPnode(file, keyConstructor, valueConstructor);
    }
    parseText(text) {
      if (text.length > 0) {
        this.addElement(new PunctuationNode(this.file, OPEN_SQ_BRACKET));
        this.csv = new CSV(this.file, this.elementConstructor, 1);
        this.addElement(this.csv);
        this.addElement(new PunctuationNode(this.file, CLOSE_SQ_BRACKET));
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/list-node.ts
  var ListNode = class extends AbstractSequence {
    csv;
    elementConstructor;
    constructor(file, elementConstructor) {
      super(file);
      this.elementConstructor = elementConstructor;
    }
    parseText(text) {
      if (text.length > 0) {
        const lang = this.file.language();
        this.addElement(new PunctuationNode(this.file, lang.LIST_START));
        this.csv = new CSV(this.file, this.elementConstructor, 1);
        this.addElement(this.csv);
        this.addElement(new SpaceNode(this.file, 0 /* ignored */));
        this.addElement(new PunctuationNode(this.file, lang.LIST_END));
        super.parseText(text);
      }
    }
    renderAsElanSource() {
      return this.status === 3 /* valid */ ? `${OPEN_SQ_BRACKET}${this.csv.renderAsElanSource()}${CLOSE_SQ_BRACKET}` : this.matchedText;
    }
    renderAsHtml() {
      const lang = this.file.language();
      return this.isValid() ? `${lang.LIST_START}${this.csv?.renderAsHtml()}${lang.LIST_END}` : this.matchedText;
    }
    renderAsExport() {
      const lang = this.file.language();
      return this.isValid() ? `${lang.LIST_START}${this.csv?.renderAsExport()}${lang.LIST_END}` : this.matchedText;
    }
  };

  // src/ide/frames/parse-nodes/enum-val-use.ts
  var EnumValUse = class extends AbstractSequence {
    type;
    val;
    parseText(text) {
      this.type = new TypeNameUse(this.file, /* @__PURE__ */ new Set([8 /* type_enum */]));
      this.addElement(this.type);
      this.addElement(new PunctuationNode(this.file, DOT));
      this.val = new IdentifierUse(
        this.file,
        /* @__PURE__ */ new Set([5 /* id_enumValue */]),
        () => this.type.matchedText
      );
      this.addElement(this.val);
      super.parseText(text.trimStart());
    }
  };

  // src/ide/frames/parse-nodes/lit-boolean.ts
  var LitBoolean = class extends AbstractParseNode {
    value = false;
    // i.e. indicates whether it is literal true or literal false (assuming parse Valid)
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        const textUC = text.toUpperCase();
        const TRUE = "TRUE";
        const FALSE = "FALSE";
        if (textUC.startsWith(TRUE)) {
          this.value = true;
          this.matchedText = text.substring(0, 4);
          this.remainingText = text.substring(4);
          this.status = 3 /* valid */;
          this._done = true;
        } else if (textUC.startsWith(FALSE)) {
          this.value = false;
          this.matchedText = text.substring(0, 5);
          this.remainingText = text.substring(5);
          this.status = 3 /* valid */;
          this._done = true;
        } else if (TRUE.startsWith(textUC) || FALSE.startsWith(textUC)) {
          this.matchedText = text;
          this.remainingText = "";
          this.status = 2 /* incomplete */;
        } else {
          this.status = 0 /* invalid */;
        }
      }
    }
    renderAsHtml() {
      const lang = this.file.language();
      return this.isValid() ? `<el-kw>${this.value ? lang.TRUE : lang.FALSE}</el-kw>` : this.matchedText;
    }
    renderAsElanSource() {
      return this.value ? "true" : "false";
    }
  };

  // src/ide/frames/parse-nodes/lit-int.ts
  var LitInt = class extends RegExMatchNode {
    constructor(file) {
      super(file, Regexes.negatableLitInt);
      this.completionWhenEmpty = "<i>integer value </i>";
    }
    parseText(text) {
      if (text.length > 0) {
        let regExp = Regexes.negatableBase10Number;
        const lang = this.file.language();
        const binary_prefix = lang.BINARY_PREFIX;
        const hex_prefix = lang.HEX_PREFIX;
        let trimmed = text.trimStart();
        if (trimmed.startsWith(binary_prefix)) {
          this.isBinary = true;
          trimmed = trimmed.replace(binary_prefix, "");
          regExp = Regexes.binaryNumber;
        } else if (trimmed.startsWith(hex_prefix)) {
          this.isHex = true;
          trimmed = trimmed.replace(hex_prefix, "");
          regExp = Regexes.hexNumber;
        }
        [this.status, this.matchedText, this.remainingText] = matchRegEx(trimmed, regExp);
        if (this.status === 0 /* invalid */) {
          this.remainingText = text;
        }
      }
    }
    isBinary = false;
    isHex = false;
    renderAsHtml() {
      const lang = this.file.language();
      const prefix = this.isBinary ? lang.BINARY_PREFIX : this.isHex ? lang.HEX_PREFIX : "";
      return `<el-lit>${prefix}${this.matchedText}</el-lit>`;
    }
    renderAsElanSource() {
      const prefix = this.isBinary ? "0b" : this.isHex ? "0x" : "";
      return `${prefix}${this.matchedText}`;
    }
  };

  // src/ide/frames/parse-nodes/lit-float.ts
  var LitFloat = class extends AbstractSequence {
    constructor(file) {
      super(file);
    }
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        this.addElement(new LitInt(this.file));
        this.addElement(new PunctuationNode(this.file, DOT));
        this.addElement(new RegExMatchNode(this.file, Regexes.literalInt));
        const exponent = new OptionalNode(
          this.file,
          new Sequence(this.file, [
            () => new RegExMatchNode(this.file, /e|E/),
            () => new RegExMatchNode(this.file, Regexes.negatableLitInt)
          ])
        );
        this.addElement(exponent);
        super.parseText(text);
      }
    }
    renderAsHtml() {
      return this.isValid() ? `<el-lit>${super.renderAsHtml()}</el-lit>` : this.matchedText;
    }
    compile() {
      return this.matchedText.toUpperCase();
    }
    //For the exponent e -> E
  };

  // src/ide/frames/parse-nodes/lit-regExp.ts
  var LitRegExp = class extends AbstractSequence {
    open;
    content;
    flags;
    close;
    constructor(file) {
      super(file);
    }
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        this.open = new PunctuationNode(this.file, DIVIDE);
        this.content = new RegExMatchNode(this.file, Regexes.anythingExceptUnescapedForwardSlash);
        this.close = new PunctuationNode(this.file, DIVIDE);
        this.flags = new OptionalNode(this.file, new RegExMatchNode(this.file, Regexes.flags));
        this.addElement(this.open);
        this.addElement(this.content);
        this.addElement(this.close);
        this.addElement(this.flags);
        super.parseText(text);
      }
    }
    renderAsElanSource() {
      return `${this.open?.matchedText}${this.content?.matchedText}${this.close?.matchedText}${this.flags?.matchedText}`;
    }
    renderAsHtml() {
      let flags = ``;
      if (this.flags) {
        flags = this.flags.matchedText.length > 0 ? `<el-regex>${this.flags?.renderAsHtml()}</el-regex>` : ``;
      }
      return `/<el-regex>${this.content?.renderAsHtml()}</el-regex>/${flags}`;
    }
  };

  // src/ide/frames/parse-nodes/lit-string-interpolated-insert.ts
  var LitStringInterpolatedInsert = class extends AbstractSequence {
    expr;
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        this.addElement(new PunctuationNode(this.file, OPEN_BRACE));
        this.expr = new ExprNode(this.file);
        this.addElement(this.expr);
        this.addElement(new PunctuationNode(this.file, CLOSE_BRACE));
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/lit-string-text.ts
  var LitStringText = class extends RegExMatchNode {
    constructor(file, constraints) {
      super(file, constraints);
    }
    renderAsHtml() {
      const contents = this.matchedText.length > 0 ? `<el-lit>${escapeHtmlChars(this.matchedText)}</el-lit>` : ``;
      return this.isValid() ? contents : this.matchedText;
    }
    renderAsExport() {
      return this.matchedText;
    }
  };

  // src/ide/frames/parse-nodes/lit-string-interpolated.ts
  var LitStringInterpolated = class extends AbstractSequence {
    segments;
    constructor(file) {
      super(file);
      this.completionWhenEmpty = `"string"`;
    }
    parseText(text) {
      if (text.length > 0) {
        const lang = this.file.language();
        const standardisedText = lang.standardiseInterpolatedString(this, text);
        if (standardisedText.length > 0) {
          const field = () => new LitStringInterpolatedInsert(this.file);
          const plainText = () => new LitStringText(this.file, /^[^%"\{]+/);
          const segment = () => new Alternatives(this.file, [field, plainText]);
          this.segments = new Multiple(this.file, segment, 1);
          this.addElement(new PunctuationNode(this.file, "$"));
          this.addElement(new PunctuationNode(this.file, DOUBLE_QUOTES));
          this.addElement(this.segments);
          this.addElement(new PunctuationNode(this.file, DOUBLE_QUOTES));
          super.parseText(standardisedText);
        } else {
          this.status = 0 /* invalid */;
          this.remainingText = text;
        }
      }
    }
    renderAsHtml() {
      return this.isValid() ? this.file.language().litStringInterpolatedAsHtml(this) : this.matchedText;
    }
    renderAsExport() {
      return this.isValid() ? removeHtmlTagsAndEscChars(this.renderAsHtml()) : this.matchedText;
    }
    renderAsElanSource() {
      return `$"${this.segments.renderAsElanSource()}"`;
    }
  };

  // src/ide/frames/parse-nodes/lit-string-interpolated-empty.ts
  var LitStringInterpolatedEmpty = class extends AbstractSequence {
    constructor(file) {
      super(file);
      this.completionWhenEmpty = `"string"`;
    }
    parseText(text) {
      if (text.length > 0) {
        const prefix = this.file.language().INTERPOLATED_STRING_PREFIX;
        this.addElement(new PunctuationNode(this.file, prefix));
        this.addElement(new PunctuationNode(this.file, DOUBLE_QUOTES));
        this.addElement(new PunctuationNode(this.file, DOUBLE_QUOTES));
        super.parseText(text);
      }
    }
    renderAsHtml() {
      const langPrefix = this.file.language().INTERPOLATED_STRING_PREFIX;
      return this.isValid() ? `${langPrefix}""` : this.matchedText;
    }
  };

  // src/ide/frames/parse-nodes/lit-string-ordinary.ts
  var LitStringOrdinary = class extends AbstractSequence {
    constructor(file) {
      super(file);
      this.contents = new LitStringText(this.file, /^[^"]*/);
      this.completionWhenEmpty = `"string"`;
    }
    contents;
    parseText(text) {
      if (text.length > 0) {
        this.addElement(new PunctuationNode(this.file, DOUBLE_QUOTES));
        this.addElement(this.contents);
        this.addElement(new PunctuationNode(this.file, DOUBLE_QUOTES));
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/lit-string.ts
  var LitString = class extends AbstractAlternatives {
    constructor(file) {
      super(file);
      this.completionWhenEmpty = `"string"`;
    }
    parseText(text) {
      if (text.length > 0) {
        this.alternatives.push(new LitStringOrdinary(this.file));
        this.alternatives.push(new LitStringInterpolatedEmpty(this.file));
        this.alternatives.push(new LitStringInterpolated(this.file));
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/lit-value-node.ts
  var LitValueNode = class extends AbstractAlternatives {
    constructor(file) {
      super(file);
      this.completionWhenEmpty = "";
    }
    parseText(text) {
      this.alternatives.push(new LitBoolean(this.file));
      this.alternatives.push(new LitInt(this.file));
      this.alternatives.push(new LitFloat(this.file));
      this.alternatives.push(new LitString(this.file));
      this.alternatives.push(new EnumValUse(this.file));
      this.alternatives.push(new LitRegExp(this.file));
      super.parseText(text);
    }
  };

  // src/ide/frames/parse-nodes/this-instance.ts
  var ThisInstance = class extends AbstractParseNode {
    parseText(text) {
      const kw = this.file.language().THIS_INSTANCE;
      if (text.length > 0) {
        const textUC = text.toUpperCase();
        const kwUC = kw.toUpperCase();
        if (textUC.startsWith(kwUC)) {
          this.status = 3 /* valid */;
          this.matchedText = kw;
          this.remainingText = text.substring(kw.length);
        } else if (kwUC.startsWith(textUC)) {
          this.status = 2 /* incomplete */;
          this.matchedText = text;
          this.remainingText = "";
        } else {
          this.status = 0 /* invalid */;
          this.matchedText = "";
          this.remainingText = text;
        }
      }
    }
    renderAsHtml() {
      const kw = this.file.language().THIS_INSTANCE;
      return this.isValid() ? `<el-kw>${kw}</el-kw>` : this.matchedText;
    }
    renderAsElanSource() {
      return this.isValid() ? thisKeyword : this.matchedText;
    }
    symbolCompletion_keywords() {
      const kw = this.file.language().THIS_INSTANCE;
      return /* @__PURE__ */ new Set([KeywordCompletion.create(kw, false, true)]);
    }
  };

  // src/ide/frames/parse-nodes/reference-node.ts
  var ReferenceNode = class extends AbstractAlternatives {
    tokenTypes = new Set(allIds);
    parseText(text) {
      if (text.length > 0) {
        this.alternatives.push(new ThisInstance(this.file));
        this.alternatives.push(new IdentifierUse(this.file, this.tokenTypes));
        this.alternatives.push(new MethodCallNode(this.file));
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/notOperator.ts
  var NotOperator = class extends AbstractParseNode {
    elanOp = notKeyword;
    langOp;
    constructor(file, langOp) {
      super(file);
      this.langOp = langOp ? langOp : (lang) => lang ? this.elanOp : this.elanOp;
      this.completionWhenEmpty = "";
    }
    parseText(text) {
      if (text.length > 0) {
        let langOp = this.langOp(this.file.language());
        langOp = /^[a-zA-Z]/.test(langOp) ? langOp + " " : langOp;
        const trimmed = text.trimStart();
        if (trimmed.startsWith(langOp)) {
          const n = this.numLeadingSpaces(text) + langOp.length;
          this.set(3 /* valid */, text.substring(0, n), text.substring(n));
          this._done = true;
        } else if (langOp.startsWith(trimmed)) {
          this.set(2 /* incomplete */, text, "");
        } else {
          this.set(0 /* invalid */, "", text);
        }
        if (this.status === 3 /* valid */ && this.numLeadingSpaces(this.remainingText) > 0) {
          const n = this.numLeadingSpaces(text);
          this.set(3 /* valid */, text.substring(0, n), text.substring(n));
        }
      }
    }
    notIsKeyword() {
      const langOp = this.langOp(this.file.language());
      return /^[a-zA-Z]/.test(langOp);
    }
    renderAsElanSource() {
      return `${this.elanOp} `;
    }
    renderAsHtml() {
      let html = this.matchedText;
      if (this.isValid()) {
        const langOp = this.langOp(this.file.language());
        const kw = this.notIsKeyword();
        const open = kw ? "<el-kw>" : "";
        const close = kw ? "</el-kw> " : "";
        html = `${open}${langOp}${close}`;
      }
      return html;
    }
    renderAsExport() {
      return this.isValid() ? `${removeHtmlTagsAndEscChars(this.renderAsHtml())}` : this.matchedText;
    }
  };

  // src/ide/frames/parse-nodes/unary-expression.ts
  var UnaryExpression = class extends AbstractSequence {
    unaryOp;
    term;
    constructor(file) {
      super(file);
    }
    parseText(text) {
      if (text.length > 0) {
        const minus = () => new PunctuationNode(this.file, MINUS);
        const not = () => new NotOperator(this.file, (lang) => lang.NOT);
        this.unaryOp = new Alternatives(this.file, [minus, not]);
        this.addElement(this.unaryOp);
        this.term = new Term(this.file);
        this.addElement(this.term);
        return super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/term-simple.ts
  var TermSimple = class extends AbstractAlternatives {
    defaultTokenTypes = /* @__PURE__ */ new Set([
      4 /* id_constant */,
      0 /* id_let */,
      3 /* id_parameter_regular */,
      2 /* id_property */,
      1 /* id_variable */,
      5 /* id_enumValue */,
      11 /* method_function */,
      12 /* method_system */
    ]);
    constructor(file) {
      super(file);
      this.completionWhenEmpty = "<i>expression</i>";
    }
    parseText(text) {
      if (text.trim().length > 0) {
        this.alternatives.push(new ListNode(this.file, () => new ExprNode(this.file)));
        this.alternatives.push(
          new DictionaryNode(
            this.file,
            () => new ExprNode(this.file),
            () => new ExprNode(this.file)
          )
        );
        this.alternatives.push(new UnaryExpression(this.file));
        this.alternatives.push(new BracketedExpression(this.file));
        this.alternatives.push(new LitValueNode(this.file));
        this.alternatives.push(new ReferenceNode(this.file));
        super.parseText(text);
      }
    }
    symbolCompletion_toMatch() {
      const startsWithBracket = /[\[\(\{].*/;
      if (startsWithBracket.test(this.matchedText)) {
        return this.matchedText.slice(1);
      } else {
        return super.symbolCompletion_toMatch();
      }
    }
  };

  // src/ide/frames/parse-nodes/term-chained.ts
  var TermChained = class extends AbstractSequence {
    chainedHead;
    tail;
    constructor(file) {
      super(file);
    }
    parseText(text) {
      if (text.length > 0) {
        this.chainedHead = new TermSimple(this.file);
        const dottedTerm = () => new DottedTerm(this.file);
        const index = () => new Index(this.file);
        const dottedSymbolOrIndex = () => new Alternatives(this.file, [dottedTerm, index]);
        this.tail = new Multiple(this.file, dottedSymbolOrIndex, 1);
        this.addElement(this.chainedHead);
        this.addElement(this.tail);
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/term-simple-with-opt-index.ts
  var TermSimpleWithOptIndex = class extends AbstractSequence {
    termSimple;
    optIndex;
    defaultTokenTypes = /* @__PURE__ */ new Set([
      4 /* id_constant */,
      0 /* id_let */,
      3 /* id_parameter_regular */,
      2 /* id_property */,
      1 /* id_variable */,
      5 /* id_enumValue */,
      11 /* method_function */,
      12 /* method_system */
    ]);
    constructor(file) {
      super(file);
      this.completionWhenEmpty = "<i>expression</i>";
    }
    parseText(text) {
      if (text.trim().length > 0) {
        this.termSimple = new TermSimple(this.file);
        this.addElement(this.termSimple);
        this.optIndex = new OptionalNode(this.file, new Index(this.file));
        this.addElement(this.optIndex);
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/term.ts
  var Term = class extends AbstractAlternatives {
    constructor(file) {
      super(file);
      this.completionWhenEmpty = "<i>expression</i>";
    }
    parseText(text) {
      this.alternatives.push(new IfExpr(this.file));
      this.alternatives.push(new TermSimpleWithOptIndex(this.file));
      this.alternatives.push(new TermChained(this.file));
      super.parseText(text);
    }
    symbolCompletion_tokenTypes() {
      if (this.alternatives.length === 0) {
        return new Set(allIdsAndMethods);
      } else {
        return super.symbolCompletion_tokenTypes();
      }
    }
    symbolCompletion_keywords() {
      if (this.alternatives.length === 0) {
        const thisInstance = this.file.language().THIS_INSTANCE;
        return /* @__PURE__ */ new Set([KeywordCompletion.create(thisInstance)]);
      } else {
        return super.symbolCompletion_keywords();
      }
    }
    getActiveNode() {
      const best = this.bestMatch;
      if (best) {
        return best.getActiveNode();
      } else {
        return this;
      }
    }
  };

  // src/ide/frames/parse-nodes/binary-expression.ts
  var BinaryExpression = class extends AbstractSequence {
    lhs;
    op;
    rhs;
    constructor(file) {
      super(file);
      this.completionWhenEmpty = "<i>expression</i>";
    }
    parseText(text) {
      this.lhs = new Term(this.file);
      this.addElement(this.lhs);
      this.op = new BinaryOperation(this.file);
      this.addElement(this.op);
      this.rhs = new ExprNode(this.file);
      this.addElement(this.rhs);
      return super.parseText(text);
    }
    renderAsHtml() {
      return this.isValid() ? `${this.lhs?.renderAsHtml()}${this.op.renderAsHtml()}${this.rhs?.renderAsHtml()}` : this.matchedText;
    }
    renderAsElanSource() {
      return `${this.lhs?.renderAsElanSource()}${this.op.renderAsElanSource()}${this.rhs?.renderAsElanSource()}`;
    }
    renderAsExport() {
      return this.isValid() ? `${this.lhs?.renderAsExport()}${this.op.renderAsExport()}${this.rhs?.renderAsExport()}` : this.matchedText;
    }
    symbolCompletion_tokenTypes() {
      if (this.getElements().length === 0) {
        return new Set(allIdsAndMethods);
      } else {
        return super.symbolCompletion_tokenTypes();
      }
    }
    symbolCompletion_keywords() {
      return this.getElements().length === 0 ? allKeywordsThatCanStartAnExpression : super.symbolCompletion_keywords();
    }
  };

  // src/ide/frames/parse-nodes/new-instance.ts
  var NewInstance = class extends AbstractSequence {
    type;
    args;
    parseText(text) {
      if (text.trim().length > 0) {
        this.file.language().addNodesForNewInstance(this);
        super.parseText(text);
      }
    }
    symbolCompletion_keywords() {
      return this.getElements().length === 0 ? /* @__PURE__ */ new Set([KeywordCompletion.create(newKeyword)]) : super.symbolCompletion_keywords();
    }
    renderAsHtml() {
      return this.isValid() ? this.file.language().newInstanceAsHtml(this) : this.matchedText;
    }
    renderAsElanSource() {
      return `${newKeyword} ${this.type?.renderAsElanSource()}(${this.args?.renderAsElanSource()})`;
    }
  };

  // src/ide/frames/parse-nodes/tuple-node.ts
  var TupleNode = class extends AbstractSequence {
    csv;
    parseText(text) {
      if (text.length > 0) {
        this.addElement(new PunctuationNode(this.file, OPEN_BRACKET));
        this.csv = new CSV(this.file, () => new ExprNode(this.file), 2);
        this.addElement(this.csv);
        this.addElement(new SpaceNode(this.file, 0 /* ignored */));
        this.addElement(new PunctuationNode(this.file, CLOSE_BRACKET));
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/expr-node.ts
  var ExprNode = class extends AbstractAlternatives {
    constructor(file) {
      super(file);
      this.completionWhenEmpty = "<i>value or expression</i>";
    }
    parseText(text) {
      if (text.trim().length > 0) {
        this.alternatives.push(new NewInstance(this.file));
        this.alternatives.push(new TupleNode(this.file));
        this.alternatives.push(new Term(this.file));
        this.alternatives.push(new BinaryExpression(this.file));
        super.parseText(text);
      }
    }
    getActiveNode() {
      let active = this;
      const best = this.bestMatch;
      if (this.bestMatchIsOnlyMatch() || best instanceof Term && this.potentialMatches().length === 2 && this.potentialMatches()[1] instanceof BinaryExpression) {
        active = best.getActiveNode();
      }
      return active;
    }
    symbolCompletion_tokenTypes() {
      return /* @__PURE__ */ new Set([
        4 /* id_constant */,
        0 /* id_let */,
        3 /* id_parameter_regular */,
        2 /* id_property */,
        1 /* id_variable */,
        5 /* id_enumValue */,
        11 /* method_function */,
        12 /* method_system */,
        8 /* type_enum */
      ]);
    }
    symbolCompletion_keywords() {
      const langExprKeywords = this.file.language().EXPRESSION_KEYWORDS;
      let kws = langExprKeywords.map((kw) => KeywordCompletion.create(kw));
      const trim = this.matchedText.trim();
      if (trim.length > 0) {
        kws = kws.filter((kw) => kw.keyword.startsWith(trim));
      }
      return new Set(kws);
    }
  };

  // src/ide/frames/parse-nodes/lambda.ts
  var Lambda = class extends AbstractSequence {
    params;
    expr;
    parseText(text) {
      if (text.trim().length > 0) {
        this.file.language().addNodesForLambda(this);
        super.parseText(text);
      }
    }
    symbolCompletion_keywords() {
      return this.getElements().length === 0 ? /* @__PURE__ */ new Set([KeywordCompletion.create(lambdaKeyword)]) : super.symbolCompletion_keywords();
    }
    renderAsHtml() {
      return this.isValid() || this.isIncomplete() ? this.file.language().lambdaAsHtml(this) : this.matchedText;
    }
    renderAsElanSource() {
      return this.isValid() ? `${lambdaKeyword} ${this.params?.renderAsElanSource()} ${ARROW} ${this.expr.renderAsElanSource()}` : this.matchedText;
    }
    renderAsExport() {
      const lang = this.file.language();
      return this.isValid() ? removeHtmlTagsAndEscChars(lang.lambdaAsHtml(this)) : this.matchedText;
    }
  };

  // src/ide/frames/parse-nodes/argument-node.ts
  var ArgumentNode = class extends AbstractAlternatives {
    constructor(file) {
      super(file);
      this.completionWhenEmpty = "<i>value or expression</i>";
    }
    parseText(text) {
      if (text.trim().length > 0) {
        this.alternatives.push(new Lambda(this.file));
        this.alternatives.push(new ExprNode(this.file));
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/arg-list-node.ts
  var ArgListNode = class extends CSV {
    context;
    constructor(file, context) {
      super(file, () => new ArgumentNode(file), 0);
      this.context = context;
    }
    getActiveNode() {
      return this.matchedText.length === 0 ? this : super.getActiveNode();
    }
  };

  // src/ide/frames/parse-nodes/method-name-use.ts
  var MethodNameUse = class extends AbstractParseNode {
    tokenTypes;
    contextGenerator;
    constructor(file, tokenTypes = /* @__PURE__ */ new Set(), contextGenerator = () => "") {
      super(file);
      this.tokenTypes = tokenTypes;
      this.contextGenerator = contextGenerator;
      this.completionWhenEmpty = "<i>name</i>";
    }
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        [this.status, this.matchedText, this.remainingText] = matchRegEx(
          text.trimStart(),
          Regexes.identifier
        );
      }
      if (this.isValid() && this.remainingText.length > 0) {
        this._done = true;
      }
    }
    symbolCompletion_tokenTypes() {
      return this.tokenTypes;
    }
    symbolCompletion_context() {
      return this.contextGenerator();
    }
    renderAsHtml() {
      return `<el-method>${this.matchedText.trim()}</el-method>`;
    }
  };

  // src/ide/frames/parse-nodes/method-call-node.ts
  var MethodCallNode = class extends AbstractSequence {
    name;
    args;
    tokenTypes;
    constructor(file, tokenTypes = /* @__PURE__ */ new Set([
      11 /* method_function */,
      12 /* method_system */
    ])) {
      super(file);
      this.tokenTypes = tokenTypes;
    }
    parseText(text) {
      if (text.trim().length > 0) {
        this.name = new MethodNameUse(this.file, this.tokenTypes);
        this.addElement(this.name);
        this.addElement(new PunctuationNode(this.file, OPEN_BRACKET));
        this.addElement(new SpaceNode(this.file, 0 /* ignored */));
        this.args = new ArgListNode(this.file, () => this.name.matchedText);
        this.addElement(this.args);
        this.addElement(new SpaceNode(this.file, 0 /* ignored */));
        this.addElement(new PunctuationNode(this.file, CLOSE_BRACKET));
        super.parseText(text);
      }
    }
    renderAsHtml() {
      return this.isValid() ? `${this.name.renderAsHtml()}(${this.args.renderAsHtml()})` : this.matchedText;
    }
    symbolCompletion_tokenTypes() {
      if (this.getElements().length === 0) {
        return /* @__PURE__ */ new Set([11 /* method_function */, 12 /* method_system */]);
      } else {
        return super.symbolCompletion_tokenTypes();
      }
    }
  };

  // src/ide/frames/parse-nodes/assert-actual-node.ts
  var AssertActualNode = class extends AbstractAlternatives {
    idTypes = /* @__PURE__ */ new Set([0 /* id_let */, 1 /* id_variable */]);
    methodTypes = /* @__PURE__ */ new Set([11 /* method_function */]);
    constructor(file) {
      super(file);
      this.alternatives.push(new IdentifierUse(file, this.idTypes));
      this.alternatives.push(new MethodCallNode(file, this.methodTypes));
      this.alternatives.push(new TermSimple(file));
      this.alternatives.push(new TermChained(file));
    }
    parseText(text) {
      super.parseText(text);
      if (this.status === 3 /* valid */ && text.includes(" is ")) {
        this.status = 0 /* invalid */;
      }
    }
  };

  // src/ide/frames/fields/assert-actual-field.ts
  var AssertActualField = class extends AbstractField {
    constructor(holder) {
      super(holder);
      this.setPlaceholder("<i>actual (computed) value</i>");
    }
    helpId() {
      return "AssertActualField";
    }
    initialiseRoot() {
      this.rootNode = new AssertActualNode(this.getFile());
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readUntil(/\sis\s/);
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
  };

  // src/ide/frames/fields/expression-field.ts
  var ExpressionField = class extends AbstractField {
    isParseByNodes = true;
    readUntil;
    constructor(holder, readUntil = /\r?\n/) {
      super(holder);
      this.readUntil = readUntil;
      this.setPlaceholder("<i>value or expression</i>");
    }
    helpId() {
      return "ExpressionField";
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_expr`;
    }
    initialiseRoot() {
      this.rootNode = new ExprNode(this.getFile());
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readUntil(this.readUntil);
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
    completionOverride = "";
    argumentDescriptions(scope) {
      let descriptions = "";
      const an = this.rootNode?.getActiveNode();
      if (an instanceof ArgListNode) {
        const context = an.context();
        const ps = scope?.resolveSymbol(context, true, scope);
        descriptions = "<i>arguments</i>";
        if (ps && !(ps instanceof UnknownSymbol)) {
          const names = parameterNames(ps.symbolType());
          descriptions = names.length > 0 ? names.join(", ") : "";
        }
      }
      return descriptions;
    }
    textAsHtml() {
      const holder = this.getHolder();
      const descriptions = this.argumentDescriptions(
        this.getFile().getAst(false)?.getScopeById(holder.getHtmlId())
      );
      this.completionOverride = descriptions ? `<i>${descriptions}</i>)` : "";
      let result = super.textAsHtml();
      if (this.getFile().doingExport) {
        result = this.getFile().language().translateExpression(result);
      }
      return result;
    }
    getCompletion() {
      return this.completionOverride || super.getCompletion();
    }
    getElanType() {
      const scope = this.getFile().getAst(false)?.getScopeById(this.getHolder().getHtmlId());
      if (isSymbol(scope)) {
        return scope.symbolType().name;
      }
      return "";
    }
  };

  // src/ide/frames/statements/assert-statement.ts
  var AssertStatement = class extends SingleLineFrame {
    isStatement = true;
    actual;
    expected;
    outcome;
    constructor(parent) {
      super(parent);
      this.actual = new AssertActualField(this);
      this.expected = new ExpressionField(this, /\r|\n/);
      this.expected.setPlaceholder("<i>expected value</i>");
    }
    initialKeywords() {
      return assertKeyword;
    }
    parseFrom(source) {
      source.removeIndent();
      source.remove("assert ");
      this.actual.parseFrom(source);
      source.remove(" is ");
      this.expected.parseFrom(source);
      source.removeNewLine();
    }
    getFields() {
      return this.language().getFields(this);
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_assert`;
    }
    frameSpecificAnnotation() {
      return "assert";
    }
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}assert ${this.actual.renderAsElanSource()} is ${this.expected.renderAsElanSource()}`;
    }
    setOutcome(outcome) {
      this.outcome = outcome;
    }
    getTestStatus() {
      return this.outcome ? this.outcome.status : 3 /* running */;
    }
    compileOrTestMsgAsHtml() {
      let msg = "";
      if (this.readCompileStatus() === 3 /* ok */ || this.readCompileStatus() === 2 /* advisory */) {
        msg = this.testMsgAsHtml();
      } else {
        msg = helper_compileMsgAsHtmlNew(this.getFile(), this);
      }
      return msg;
    }
    getMessage(outcome) {
      if (!outcome || outcome.status === 2 /* ignored */) {
        return "not run";
      } else if (outcome.status === 1 /* fail */) {
        const offset = outcome.diffOffset;
        if (offset !== void 0) {
          const a = this.getCharacter(outcome.actual, offset);
          const e = this.getCharacter(outcome.expected, offset);
          return `${a} found at [${offset}] (expected: ${e})`;
        }
        return `actual (computed): ${outcome.actual}`;
      } else if (outcome.status === 4 /* pass */) {
        return "pass";
      }
      return "";
    }
    getCharacter(from, offset) {
      let char = from.slice(offset, offset + 1);
      if (char === "") {
        char = "empty";
      } else if (char === " ") {
        char = "space";
      }
      return char;
    }
    getCls(outcome) {
      if (!outcome || outcome.status === 2 /* ignored */) {
        return DisplayColour[1 /* warning */];
      } else if (outcome.status === 1 /* fail */) {
        return DisplayColour[0 /* error */];
      } else if (outcome.status === 4 /* pass */) {
        return DisplayColour[3 /* ok */];
      }
      return "";
    }
    outerHtmlTag = "el-statement";
    testMsgAsHtml() {
      const cls = this.getCls(this.outcome);
      const msg = escapeHtmlChars(this.getMessage(this.outcome));
      return `<el-msg class="${cls}"> ${msg}</el-msg>`;
    }
    renderAsHtml() {
      return `<${this.outerHtmlTag} class="${this.cls()}" id='${this.htmlId}' tabindex="-1" ${this.toolTip()}>${this.contextMenu()}<el-top>${this.language().renderSingleLineAsHtml(this)}</el-top>${this.helpAsHtml()}${this.compileOrTestMsgAsHtml()}${this.getFrNo()}</${this.outerHtmlTag}>`;
    }
  };

  // src/ide/frames/code-source-from-string.ts
  var CodeSourceFromString = class {
    constructor(code, noError = false) {
      this.noError = noError;
      this.remainingCode = code;
    }
    remainingCode;
    mode = 0 /* loadNew */;
    pasting = false;
    pushBackOntoFrontOfCode(pushBack) {
      this.remainingCode = pushBack + this.remainingCode;
    }
    removeNewLine() {
      this.removeRegEx(Regexes.newLine, false);
      return this;
    }
    removeIndent() {
      this.removeRegEx(Regexes.indent, false);
      return this;
    }
    remove(match3) {
      if (!this.isMatch(match3)) {
        if (this.noError) {
          this.remainingCode = "";
          return this;
        }
        throw new Error(`${this.readToEndOfLine()} does not match ${match3}`);
      }
      this.remainingCode = this.remainingCode.substring(match3.length);
      return this;
    }
    removeRegEx(regx, optional) {
      if (!this.isMatchRegEx(regx)) {
        if (optional) {
          return "";
        } else if (this.noError) {
          return "";
        }
        throw new Error(`${this.readToEndOfLine()} does not match ${regx}`);
      } else {
        const match3 = this.remainingCode.match(regx)[0];
        this.remainingCode = this.remainingCode.replace(regx, "");
        return match3;
      }
    }
    isMatch(code) {
      return this.remainingCode.startsWith(code);
    }
    isMatchRegEx(regEx) {
      return regEx.test(this.remainingCode);
    }
    hasMoreCode() {
      return this.remainingCode.length > 0;
    }
    getRemainingCode() {
      return this.remainingCode;
    }
    peekNextChar() {
      return this.remainingCode[0];
    }
    readToEndOfLine() {
      return this.removeRegEx(Regexes.anythingToNewLineAsRegExp, false);
    }
    readUntil(regx) {
      const matchIndex = regx.exec(this.remainingCode)?.index;
      const uptoMatch = this.remainingCode.substring(0, matchIndex);
      this.remainingCode = this.remainingCode.slice(matchIndex);
      return uptoMatch;
    }
    readMatching(regx) {
      return this.removeRegEx(regx, true);
    }
    readToNonMatchingCloseBracket() {
      let insideDoubleQuotes = false;
      let insideSingleQuotes = false;
      let openBracketCount = 0;
      let cont = true;
      let result = "";
      while (cont) {
        const c = this.peekNextChar();
        if (insideDoubleQuotes) {
          if (c === `"`) {
            insideDoubleQuotes = false;
          }
        } else if (insideSingleQuotes) {
          if (c === `'`) {
            insideSingleQuotes = false;
          }
        } else if (c === `"`) {
          insideDoubleQuotes = true;
        } else if (c === `'`) {
          insideSingleQuotes = true;
        } else if (c === "(") {
          openBracketCount++;
        } else if (c === ")") {
          if (openBracketCount === 0) {
            cont = false;
          } else {
            openBracketCount--;
          }
        }
        if (cont) {
          result += c;
          this.remove(c);
        }
      }
      return result;
    }
  };

  // src/ide/frames/abstract-selector.ts
  var AbstractSelector = class _AbstractSelector extends AbstractFrame {
    isSelector = true;
    isStatement = true;
    text = "";
    profile;
    overtyper = new Overtyper();
    constructor(parent) {
      super(parent);
      this.profile = this.getFile().getProfile();
      this.setParseStatus(3 /* valid */);
    }
    initialKeywords() {
      return "selector";
    }
    helpAsHtml() {
      const active = this.helpActive ? ` class="active"` : "";
      this.helpActive = false;
      return this.isSelected() ? `<el-help contenteditable="false" title="Click to open Help for any of these instructions"> <a href="documentation/LangRef.html#${this.helpId()}" target="help-iframe" tabindex="-1"${active}>?</a></el-help>` : ``;
    }
    optionsFilteredByContext(userEntry) {
      return this.defaultOptions().filter((o) => this.validWithinCurrentContext(o[0], userEntry));
    }
    optionsFilteredByProfile(userEntry) {
      return this.optionsFilteredByContext(userEntry).filter((o) => this.profileAllows(o[0]));
    }
    parseFrom(source) {
      let compilerDirective = "";
      source.removeIndent();
      if (source.isMatchRegEx(Regexes.compilerDirective)) {
        compilerDirective = source.removeRegEx(Regexes.compilerDirective, false).replace("[", "").replace("] ", "");
      }
      const options = this.optionsFilteredByContext(source.pasting).filter(
        (o) => source.isMatch(o[0])
      );
      if (options.length === 1) {
        const typeToAdd = options[0][0];
        const frame = this.addFrame(typeToAdd, "");
        this.processCompilerDirective(frame, compilerDirective);
        frame.parseFrom(source);
        return frame;
      } else {
        throw new Error(`${options.length} matches found at ${source.readToEndOfLine()} `);
      }
    }
    processCompilerDirective(frame, compilerDirective) {
      if (compilerDirective === ghostedAnnotation) {
        frame.setGhosted(true);
      }
    }
    optionsMatchingUserInput(match3) {
      return this.optionsFilteredByProfile(true).filter((o) => o[1] === match3);
    }
    adjusted(kw, input, soFar) {
      const words = kw.split(" ");
      if (words.length === 1) {
        return kw;
      } else if (input.startsWith(`${words[0]}`)) {
        return words[1];
      } else if (soFar.includes(`${words[0]}...`)) {
        return "";
      } else {
        return `${words[0]}...`;
      }
    }
    addFrame(keyword, pendingChars) {
      const func = this.defaultOptions().filter((o) => o[0] === keyword)[0][3];
      const parent = this.getParent();
      const newFrame = func(parent);
      parent.addChildBefore(newFrame, this);
      newFrame.selectFirstField();
      const fields = newFrame.getFields();
      if (fields.length > 0) {
        fields[0].overtyper.consumeChars(pendingChars, 500);
      } else if (isFrameWithStatements(newFrame)) {
        const ss = newFrame.getFirstChild();
        if (ss instanceof _AbstractSelector) {
          ss.overtyper.consumeChars(pendingChars, 500);
        }
      }
      return newFrame;
    }
    setClasses() {
      super.setClasses();
      this.pushClass(this.text === "", "empty");
    }
    clearText() {
      this.text = "";
    }
    getFields() {
      return [];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_select`;
    }
    frameSpecificAnnotation() {
      return "";
    }
    deselect() {
      super.deselect();
      this.text = "";
    }
    renderAsHtml() {
      const message = this.isSelected() ? "press Enter, or <i>right</i>-click here, to view options" : "new code";
      return `<${this.outerHtmlTag} contenteditable spellcheck="false" class="${this.cls()}" id='${this.htmlId}' tabindex="-1">${this.contextMenu()}<el-top class="newcode">${message}</el-top></${this.outerHtmlTag}>`;
    }
    renderAsElanSource() {
      return `${this.indent()}`;
    }
    renderAsExport() {
      return `${this.indent()}`;
    }
    selectorControlKeys = ["d", "O", "v", "?"];
    processKey(e) {
      let codeHasChanged = false;
      let key = e.key;
      if (e.modKey.control && !this.selectorControlKeys.includes(key ?? "")) {
        return super.processKey(e);
      }
      switch (key) {
        case "Backspace": {
          this.text = this.text.substring(0, this.text.length - 1);
          break;
        }
        case "Delete": {
          this.deleteIfPermissible();
          codeHasChanged = true;
          break;
        }
        case "Enter": {
          this.showContextMenu = true;
          break;
        }
        case "d": {
          if (e.modKey.control) {
            this.deleteIfPermissible();
            codeHasChanged = true;
            break;
          }
        }
        case "v": {
          if (e.modKey.control) {
            this.paste(e.optionalData ?? "");
            codeHasChanged = true;
            break;
          }
        }
        case "O": {
          if (e.modKey.control) {
            this.expandCollapseAll();
            break;
          }
        }
        case "t": {
          if (e.modKey.alt) {
            this.getFile().removeAllSelectorsThatCanBe();
            break;
          }
        }
        case "?": {
          if (e.modKey.control) {
            this.showHelp();
            break;
          }
        }
        default: {
          if (!key || key.length === 1) {
            key = key?.toLowerCase();
            this.processOptions(key);
            codeHasChanged = true;
          } else {
            codeHasChanged = super.processKey(e);
          }
        }
      }
      return codeHasChanged;
    }
    handleContextMenuEvent(e) {
      let codeHasChanged = false;
      if (e.command) {
        const map = this.getContextMenuItems();
        codeHasChanged = map.get(e.command)[1]?.(e.optionalData);
      } else {
        if (!this.isSelected()) {
          this.select(true, false);
        }
        this.showContextMenu = true;
      }
      return codeHasChanged;
    }
    deleteIfPermissible() {
      if (this.getParent().minimumNumberOfChildrenExceeded()) {
        this.delete();
      }
    }
    paste = (code) => {
      try {
        code = (code ?? "").trim() + "\n";
        const source = new CodeSourceFromString(code, true);
        source.pasting = true;
        const newFrame = this.parseFrom(source);
        if (source.hasMoreCode() && source.getRemainingCode().trim()) {
          const remainingCode = source.getRemainingCode();
          const frame = this.getParent().getChildAfter(newFrame);
          const selector = isSelector(frame) ? frame : parentHelper_insertOrGotoChildSelector(this.getParent(), false, frame);
          selector.paste(remainingCode);
        }
        this.getFile().removeAllSelectorsThatCanBe();
      } catch (_e) {
        this.pasteError = `Paste failed: Cannot paste '${code}' into prompt`;
      }
      return true;
    };
    canBePastedIn(frame) {
      return this.optionsMatchingUserInput(frame.initialKeywords()).length === 1;
    }
    processOptions(key) {
      if (this.overtyper.hasNotConsumed(key)) {
        const options = this.optionsMatchingUserInput(this.text + key);
        if (options.length === 1) {
          const typeToAdd = options[0][0];
          const pendingChars = typeToAdd.slice((this.text + key).length);
          this.addFrame(typeToAdd, pendingChars);
          this.text = "";
        }
      }
    }
    insertPeerSelector(_after) {
      throw new Error("Should never be called on a Selector");
    }
    selectFirstField() {
      this.select(true, false);
      return true;
    }
    selectLastField() {
      this.select(true, false);
      return true;
    }
    worstParseStatusOfFields() {
      return this.text ? 2 /* incomplete */ : 3 /* valid */;
    }
    getContextMenuItems() {
      const map = /* @__PURE__ */ new Map();
      const allOptions = this.optionsFilteredByProfile(true);
      allOptions.forEach((o) => {
        const name = o[0];
        const action = () => {
          this.addFrame(name, "");
          return true;
        };
        const html = `${o[2]}`;
        map.set(name, [html, action]);
      });
      map.set("paste", ["separator paste <span class='kb'>Ctrl+v</span>", this.paste]);
      addDeleteToContextMenu(this, map);
      return map;
    }
    getCommentMarker() {
      return this.getFile().language().COMMENT_MARKER;
    }
  };

  // src/ide/frames/statements/statement-selector.ts
  var StatementSelector = class extends AbstractSelector {
    isStatement = true;
    factory;
    constructor(parent) {
      super(parent);
      this.factory = parent.getFactory();
    }
    helpId() {
      return "StatementInstructions";
    }
    defaultOptions() {
      return [
        [assertKeyword, "a", "<b>a</b>ssert", (parent) => this.factory.newAssert(parent)],
        ["print", "p", "<b>p</b>rint", (parent) => this.factory.newCall(parent, "print")],
        [
          letKeyword,
          "l",
          "<b>l</b>et statement",
          (parent) => this.factory.newLetStatement(parent)
        ],
        [
          variableKeyword,
          "v",
          "<b>v</b>ariable definition",
          (parent) => this.factory.newVar(parent)
        ],
        [
          reassignKeyword,
          "r",
          "<b>r</b>eassign variable",
          (parent) => this.factory.newSet(parent)
        ],
        [ifKeyword, "i", "<b>i</b>f", (parent) => this.factory.newIf(parent)],
        [elifKeyword, "s", "el<b>s</b>e if", (parent) => this.factory.newElif(parent)],
        [elseKeyword, "e", "<b>e</b>lse", (parent) => this.factory.newElse(parent)],
        [whileKeyword, "w", "<b>w</b>hile loop", (parent) => this.factory.newWhile(parent)],
        [forKeyword, "f", "<b>f</b>or loop", (parent) => this.factory.newFor(parent)],
        [
          callKeyword,
          "c",
          "<b>c</b>all procedure",
          (parent) => this.factory.newCall(parent, "")
        ],
        [tryKeyword, "y", "tr<b>y</b>", (parent) => this.factory.newTryCatch(parent)],
        // [catchKeyword, (parent: Parent) => this.factory.newCatch(parent)], // add back when multiple catches permitted
        [throwKeyword, "t", "<b>t</b>hrow", (parent) => this.factory.newThrow(parent)],
        [
          this.getCommentMarker(),
          this.getCommentMarker(),
          `<b>${this.getCommentMarker()}</b> comment`,
          (parent) => this.factory.newComment(parent)
        ]
      ];
    }
    profileAllows(_keyword) {
      return true;
    }
    validWithinCurrentContext(keyword, userEntry) {
      const parent = this.getParent();
      let result = true;
      if (keyword === elseKeyword || keyword === elifKeyword) {
        result = parent.getIdPrefix().includes(`_${ifKeyword}`);
      } else if (keyword === catchKeyword) {
        result = parent.getIdPrefix().includes(`_${tryKeyword}`);
      } else if (keyword === callKeyword || keyword === "print") {
        result = !(this.isWithinAFunction() || this.isWithinATest() || this.isWithinAConstructor());
      } else if (keyword === letKeyword) {
        result = !userEntry && (this.isWithinAFunction() || this.isWithinATest());
      } else if (keyword === assertKeyword) {
        result = this.isWithinATest();
      }
      if (this.isWithinATest()) {
        result = keyword === assertKeyword || keyword === variableKeyword || keyword === letKeyword || keyword === commentMarker;
      }
      if (this.profile.isFunctional() && userEntry) {
        if (this.isWithinAFunction()) {
          result = keyword === letKeyword || keyword === commentMarker;
        } else if (this.isWithinATest()) {
          result = keyword === assertKeyword || keyword === letKeyword || keyword === commentMarker;
        }
      }
      return result;
    }
    isWithinAFunction() {
      return this.isWithinContext(this.getParent(), "func");
    }
    isWithinATest() {
      return this.getParent().getIdPrefix().includes("_test");
    }
    isWithinAConstructor() {
      return this.isWithinContext(this.getParent(), "constructor");
    }
    isWithinContext(parent, parentPrefix) {
      return parent.getIdPrefix().includes(`_${parentPrefix}`) ? true : parent.hasParent() && this.isWithinContext(parent.getParent(), parentPrefix);
    }
    outerHtmlTag = "el-statement";
  };

  // src/ide/frames/frame-with-statements.ts
  var FrameWithStatements = class _FrameWithStatements extends AbstractFrame {
    isFrameWithStatements = true;
    isCollapsible = true;
    isParent = true;
    _children = new Array();
    constructor(parent) {
      super(parent);
      this.getChildren().push(new StatementSelector(this));
    }
    getProfile() {
      return this.getFile().getProfile();
    }
    setClasses() {
      super.setClasses();
      this.pushClass(true, "multiline");
    }
    getFactory() {
      return this.getParent().getFactory();
    }
    updateParseStatus() {
      this.getChildren().forEach((c) => c.updateParseStatus());
      const worstOfFieldsOrChildren = Math.min(
        this.worstParseStatusOfFields(),
        parentHelper_readWorstParseStatusOfChildren(this)
      );
      this.setParseStatus(worstOfFieldsOrChildren);
    }
    readCompileStatus() {
      const worstOfFieldsOrChildren = Math.min(
        this.worstCompileStatusOfFields(),
        parentHelper_readWorstCompileStatusOfChildren(this)
      );
      const newStatus = Math.min(super.readCompileStatus(), worstOfFieldsOrChildren);
      return newStatus;
    }
    getChildren() {
      return this._children;
    }
    minimumNumberOfChildrenExceeded() {
      return this.getChildren().length > 1;
    }
    expandCollapse() {
      if (this.isCollapsed()) {
        this.expand();
      } else {
        this.collapse();
      }
    }
    newChildSelector() {
      return new StatementSelector(this);
    }
    insertOrGotoChildSelector(after, child) {
      parentHelper_insertOrGotoChildSelector(this, after, child);
    }
    insertSelectorAfterLastField() {
      const firstChild = this._children[0];
      if (isSelector(firstChild)) {
        firstChild.select(true, false);
      } else {
        const selector = this.newChildSelector();
        this.addChildBefore(selector, firstChild);
        selector.select(true, false);
      }
    }
    selectNextFrame() {
      this._children[0]?.select(true, false);
    }
    removeChild(child) {
      parentHelper_removeChild(this, child);
    }
    getFirstChild() {
      return parentHelper_getFirstChild(this);
    }
    getLastChild() {
      return parentHelper_getLastChild(this);
    }
    getChildAfter(child) {
      return parentHelper_getChildAfter(this, child);
    }
    getChildBefore(child) {
      return parentHelper_getChildBefore(this, child);
    }
    getChildRange(first, last) {
      return parentHelper_getChildRange(this, first, last);
    }
    getFirstSelectorAsDirectChild() {
      return parentHelper_getFirstSelectorAsDirectChild(this);
    }
    selectFirstChild(multiSelect) {
      return parentHelper_selectFirstChild(this, multiSelect);
    }
    addChildBefore(child, before) {
      this.hasBeenAddedTo();
      parentHelper_addChildBefore(this, child, before);
    }
    addChildAfter(child, before) {
      this.hasBeenAddedTo();
      parentHelper_addChildAfter(this, child, before);
    }
    renderChildrenAsHtml() {
      return parentHelper_renderChildrenAsHtml(this);
    }
    renderChildrenAsElanSource() {
      return parentHelper_renderChildrenAsElanSource(this);
    }
    renderChildrenAsExport() {
      return parentHelper_renderChildrenAsExport(this);
    }
    selectFirstField() {
      let result = super.selectFirstField();
      if (!result) {
        result = this.getChildren()[0].selectFirstField();
      }
      return result;
    }
    selectFirstChildIfAny() {
      let result = false;
      if (this.getChildren().length > 0) {
        this.getChildren()[0].select(true, false);
        result = true;
      }
      return result;
    }
    deleteSelectedChildren() {
      parentHelper_deleteSelectedChildren(this);
    }
    copySelectedChildren(encode) {
      return parentHelper_copySelectedChildren(this, encode);
    }
    exportSelectedChildren() {
      return parentHelper_exportSelectedChildren(this);
    }
    moveSelectedChildrenUpOne() {
      parentHelper_moveSelectedChildrenUpOne(this);
    }
    moveSelectedChildrenDownOne() {
      parentHelper_moveSelectedChildrenDownOne(this);
    }
    parseFrom(source) {
      this.parseTop(source);
      while (!this.parseBottom(source)) {
        if (source.isMatchRegEx(Regexes.newLine)) {
          source.removeRegEx(Regexes.newLine, false);
        } else {
          this.getFirstSelectorAsDirectChild().parseFrom(source);
        }
        source.removeIndent();
      }
    }
    parseStandardEnding(source, keywords) {
      source.removeIndent();
      let result = false;
      if (source.isMatch(keywords)) {
        source.remove(keywords);
        result = true;
      }
      return result;
    }
    multipleIds(sid) {
      return sid.includes(",") || sid.includes(":");
    }
    getAsserts() {
      const children = this.getChildren();
      let asserts = children.filter(
        (c) => c instanceof AssertStatement && !c.isGhosted()
      );
      for (const f of children.filter((c) => c instanceof _FrameWithStatements)) {
        asserts = asserts.concat(f.getAsserts());
      }
      return asserts;
    }
    updateBreakpoints(event) {
      super.updateBreakpoints(event);
      parentHelper_updateBreakpoints(this, event);
    }
    ghostSelectedChildren() {
      setGhostOnSelectedChildren(this, true);
    }
    unghostSelectedChildren() {
      setGhostOnSelectedChildren(this, false);
    }
    deleteAllGhosted() {
      if (this.isGhosted()) {
        this.delete();
      } else {
        const children = this._children.slice();
        for (const child of children) {
          child.deleteAllGhosted();
        }
      }
    }
    renderAsHtml() {
      return `<${this.outerHtmlTag} class="${this.cls()}" id='${this.htmlId}' tabindex="-1" ${this.toolTip()}>
<el-top>${this.contextMenu()}${this.bpAsHtml()}<el-expand>+</el-expand>${this.language().renderTopAsHtml(this)}
${this.helpAsHtml()}${this.compileMsgAsHtml()}${this.annotationAsHtml()}${this.getFrNo()}</el-top>
${this.renderChildrenAsHtml()}
${this.language().renderBottomAsHtml(this)}
</${this.outerHtmlTag}>`;
    }
    renderAsExport() {
      const topAsExport = removeHtmlTagsAndEscChars(this.language().renderTopAsHtml(this));
      const bottom = removeHtmlTagsAndEscChars(this.language().renderBottomAsHtml(this));
      const bottomAsExport = bottom === `` ? `` : `\r
${this.indent()}${bottom}`;
      return `${this.indent()}${this.sourceAnnotations()}${topAsExport}${this.annotationAsSource()}
${this.renderChildrenAsExport()}${bottomAsExport}`;
    }
    resetFieldText() {
      super.resetFieldText();
      parentHelper_resetFieldTextOnChildren(this);
    }
  };

  // src/ide/frames/class-members/constructor.ts
  var Constructor = class extends FrameWithStatements {
    isConstructor = true;
    isMember = true;
    isAbstract = false;
    private = false;
    params;
    constructor(parent) {
      super(parent);
      this.params = new ParamListField(this);
    }
    isPrivate = false;
    isDeletable() {
      return false;
    }
    isOnAbstractClass() {
      return false;
    }
    initialKeywords() {
      return constructorKeyword;
    }
    getFields() {
      return [this.params];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_constructor`;
    }
    frameSpecificAnnotation() {
      return "constructor";
    }
    outerHtmlTag = "el-constructor";
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}constructor(${this.params.renderAsElanSource()})\r
${this.renderChildrenAsElanSource()}\r
${this.indent()}end constructor\r
`;
    }
    parseTop(source) {
      source.removeIndent();
      source.remove("constructor(");
      this.params.parseFrom(source);
      source.remove(")");
    }
    parseBottom(source) {
      return this.parseStandardEnding(source, "end constructor");
    }
    renderAsExport() {
      return `${super.renderAsExport()}\r
`;
    }
  };

  // src/ide/frames/class-members/member-selector.ts
  var MemberSelector = class extends AbstractSelector {
    isMember = true;
    isAbstract = false;
    isPrivate = false;
    class;
    constructor(parent) {
      super(parent);
      this.class = parent;
    }
    isOnAbstractClass() {
      throw new Error("Should not be called");
    }
    helpId() {
      return "MemberInstructions";
    }
    getClass() {
      return this.getParent();
    }
    defaultOptions() {
      return [
        [constructorKeyword, "c", "constructor", (_parent) => this.class.createConstructor()],
        [propertyKeyword, "p", "<b>p</b>roperty", (_parent) => this.class.createProperty()],
        [
          procedureKeyword,
          "c",
          "pro<b>c</b>edure method",
          (_parent) => this.class.createProcedure()
        ],
        [
          functionKeyword,
          "f",
          "<b>f</b>unction method",
          (_parent) => this.class.createFunction()
        ],
        [withKeyword, "w", "<b>w</b>ith method", (_parent) => this.class.createWithMethod()],
        [
          abstractPropertyKeywords,
          "",
          "abstract property",
          (_parent) => this.class.createAbstractProperty()
        ],
        [
          abstractProcedureKeywords,
          "",
          "abstract procedure",
          (_parent) => this.class.createAbstractProcedure()
        ],
        [
          abstractFunctionKeywords,
          "",
          "abstract function",
          (_parent) => this.class.createAbstractFunction()
        ],
        [
          privatePropertyKeywords,
          "",
          "private property",
          (_parent) => this.class.createProperty(true)
        ],
        [
          privateProcedureKeywords,
          "",
          "private procedure",
          (_parent) => this.class.createProcedure(true)
        ],
        [
          privateFunctionKeywords,
          "",
          "private function",
          (_parent) => this.class.createFunction(true)
        ],
        [
          this.getCommentMarker(),
          this.getCommentMarker(),
          `<b>${this.getCommentMarker()}</b> comment`,
          (_parent) => this.class.createComment()
        ]
      ];
    }
    profileAllows(_keyword) {
      return true;
    }
    validWithinCurrentContext(keyword, userEntry) {
      let result = true;
      if (keyword.startsWith(privateKeyword)) {
        result = !userEntry;
      } else if (keyword.startsWith(abstractKeyword)) {
        result = this.class.isAbstract || this.class.isInterface;
      } else if (this.class.isInterface) {
        result = keyword === commentMarker;
      } else if (this.class.isRecord) {
        result = keyword === propertyKeyword || keyword === functionKeyword || keyword === this.getCommentMarker();
      } else if (keyword === constructorKeyword) {
        result = this.class.isConcrete && !this.getClass().getConstructor();
      } else if (keyword === procedureKeyword) {
        result = !(this.profile.isFunctional() && userEntry);
      } else if (keyword === withKeyword) {
        result = !userEntry || this.profile.isFunctional();
      }
      return result;
    }
    outerHtmlTag = "el-member";
    indent() {
      return singleIndent();
    }
  };

  // src/ide/frames/globals/procedure-frame.ts
  var ProcedureFrame = class extends FrameWithStatements {
    name;
    params;
    file;
    constructor(parent) {
      super(parent);
      this.file = parent;
      this.name = new MethodNameField(this);
      this.params = new ParamListField(this);
    }
    isProcedure = true;
    initialKeywords() {
      return procedureKeyword;
    }
    getFields() {
      return [this.name, this.params];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_proc`;
    }
    frameSpecificAnnotation() {
      return "procedure";
    }
    outerHtmlTag = "el-proc";
    parseTop(source) {
      source.remove("procedure ");
      this.name.parseFrom(source);
      source.remove("(");
      this.params.parseFrom(source);
      source.remove(")");
    }
    parseBottom(source) {
      return this.parseStandardEnding(source, "end procedure");
    }
  };

  // src/ide/frames/class-members/procedure-method.ts
  var ProcedureMethod = class extends ProcedureFrame {
    isMember = true;
    isPrivate;
    isAbstract = false;
    constructor(parent, priv = false) {
      super(parent);
      this.isPrivate = priv;
    }
    isOnAbstractClass() {
      return this.getParent() instanceof AbstractClass;
    }
    helpId() {
      return "procedure_method";
    }
    indent() {
      return singleIndent();
    }
    frameSpecificAnnotation() {
      const priv = this.isPrivate ? "private " : "";
      return `${priv}procedure method`;
    }
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}${modifierAsElanSource(this)}procedure ${this.name.renderAsElanSource()}(${this.params.renderAsElanSource()})\r
${this.renderChildrenAsElanSource()}\r
${this.indent()}end procedure\r
`;
    }
    parseTop(source) {
      source.removeIndent();
      const priv = `${privateKeyword} `;
      if (source.isMatch(priv)) {
        source.remove(priv);
        this.isPrivate = true;
      }
      return super.parseTop(source);
    }
    parseBottom(source) {
      return super.parseBottom(source);
    }
    makePublic = () => {
      this.isPrivate = false;
      return true;
    };
    makePrivate = () => {
      this.isPrivate = true;
      return true;
    };
    getContextMenuItems() {
      const map = super.getContextMenuItems();
      addPrivateToggleToContextMenu(this, map);
      return map;
    }
    processKey(e) {
      if (e.modKey.control && e.key === "p") {
        return togglePrivatePublic(this);
      }
      return super.processKey(e);
    }
    renderAsExport() {
      return `${super.renderAsExport()}\r
`;
    }
  };

  // src/ide/frames/class-members/property.ts
  var Property = class extends SingleLineFrame {
    isMember = true;
    isProperty = true;
    isAbstract = false;
    name;
    type;
    isPrivate = false;
    constructor(parent, priv = false) {
      super(parent);
      this.name = new IdentifierField(this);
      this.type = new TypeField(this);
      this.isPrivate = priv;
      this.canHaveBreakPoint = false;
    }
    isOnAbstractClass() {
      return this.getParent() instanceof AbstractClass;
    }
    initialKeywords() {
      return propertyKeyword;
    }
    getFields() {
      return [this.name, this.type];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_prop`;
    }
    frameSpecificAnnotation() {
      const priv = this.isPrivate ? "private " : "";
      return `${priv}property`;
    }
    outerHtmlTag = "el-prop";
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}${modifierAsElanSource(this)}${propertyKeyword} ${this.name.renderAsElanSource()} ${asKeyword} ${this.type.renderAsElanSource()}\r
`;
    }
    isGlobalClass(st) {
      return st instanceof ClassType && !st.typeOptions.isIndexable;
    }
    parseFrom(source) {
      source.removeIndent();
      const priv = `${privateKeyword} `;
      if (source.isMatch(priv)) {
        source.remove(priv);
        this.isPrivate = true;
      }
      source.remove(`${propertyKeyword} `);
      this.name.parseFrom(source);
      source.remove(` ${asKeyword} `);
      this.type.parseFrom(source);
    }
    makePublic = () => {
      this.isPrivate = false;
      return true;
    };
    makePrivate = () => {
      this.isPrivate = true;
      return true;
    };
    getContextMenuItems() {
      const map = super.getContextMenuItems();
      addPrivateToggleToContextMenu(this, map);
      return map;
    }
    processKey(e) {
      if (e.modKey.control && e.key === "p") {
        return togglePrivatePublic(this);
      }
      return super.processKey(e);
    }
    renderAsExport() {
      return `${super.renderAsExport()}\r
`;
    }
  };

  // src/ide/frames/parse-nodes/inheritanceNode.ts
  var InheritanceNode = class extends CSV {
    constructor(file) {
      super(file, () => new TypeNode(file), 0);
    }
    getAllTypeNames() {
      return this.matchedText.split(", ");
    }
    rootNode() {
      return this.file.getAst(true);
    }
    getAbstractClassNames() {
      const rootNode = this.rootNode();
      return this.getAllTypeNames().filter(
        (t) => getClassType(t, rootNode) === 1 /* abstract */
      );
    }
    getInterfaceNames() {
      const rootNode = this.rootNode();
      return this.getAllTypeNames().filter(
        (t) => getClassType(t, rootNode) === 2 /* interface */
      );
    }
  };

  // src/ide/frames/fields/inherits-from-field.ts
  var InheritsFromField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this.setOptional(true);
      this.setPlaceholder(" <i>inheritance</i>");
    }
    helpId() {
      return "InheritsFromField";
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_text`;
    }
    initialiseRoot() {
      this.rootNode = new InheritanceNode(this.getFile());
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readToEndOfLine();
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
    renderAsHtml() {
      let result = "";
      if (this.isSelected()) {
        result = ` ${super.renderAsHtml()}`;
      } else {
        const textAsHtml = this.getFile().language().inheritsFromTextAsHtml(this);
        result = `<el-field id="${this.htmlId}" class="${this.cls()}" tabindex="-1"><el-txt>${textAsHtml}</el-txt><el-place>${this._placeholder}</el-place>${this.getMessage()}${this.helpAsHtml()}</el-field>`;
      }
      return result;
    }
    default_renderasHtml() {
      return super.renderAsHtml();
    }
  };

  // src/ide/frames/parse-nodes/type-name-def.ts
  var TypeNameDef = class extends AbstractParseNode {
    tokenTypes = /* @__PURE__ */ new Set();
    elanTypeName = "";
    constructor(file, tokenTypes = /* @__PURE__ */ new Set([
      7 /* type_abstract */,
      6 /* type_concrete */,
      9 /* type_notInheritable */,
      8 /* type_enum */
    ])) {
      super(file);
      this.completionWhenEmpty = "<i>Type</i>";
      this.tokenTypes = tokenTypes;
    }
    langInt = RegExp(`^\\s*${this.file.language().INT_NAME}`);
    langFloat = RegExp(`^\\s*${this.file.language().FLOAT_NAME}`);
    langBool = RegExp(`^\\s*${this.file.language().BOOL_NAME}`);
    langString = RegExp(`^\\s*${this.file.language().STRING_NAME}`);
    langList = RegExp(`^\\s*${this.file.language().LIST_NAME}`);
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        [this.status, this.matchedText, this.remainingText] = matchRegEx(
          text,
          Regexes.typeSimpleName
        );
        this.elanTypeName = this.matchedText;
        if (this.status === 3 /* valid */ && ReservedWords.Instance.matchesIgnoringCase(this.matchedText)) {
          this.status = 0 /* invalid */;
          this.message = `matches a reserved word.`;
        }
      }
    }
    renderAsHtml() {
      return `<el-type>${this.renderAsExport()}</el-type>`;
    }
    symbolCompletion_tokenTypes() {
      return this.tokenTypes;
    }
    renderAsExport() {
      const lang = this.file.language();
      const elan = this.elanTypeName;
      let target = elan;
      if (elan === "Int") {
        target = lang.INT_NAME;
      } else if (elan === "Float") {
        target = lang.FLOAT_NAME;
      } else if (elan === "Boolean") {
        target = lang.BOOL_NAME;
      } else if (elan === "String") {
        target = lang.STRING_NAME;
      } else if (elan === "List") {
        target = lang.LIST_NAME;
      }
      return target;
    }
  };

  // src/ide/frames/fields/type-name-field.ts
  var TypeNameField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this.useHtmlTags = true;
      this.setPlaceholder("Name");
    }
    helpId() {
      return "TypeNameField";
    }
    initialiseRoot() {
      this.rootNode = new TypeNameDef(this.getFile(), /* @__PURE__ */ new Set());
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readUntil(/[^a-zA-Z0-9_]/);
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_type`;
    }
    textAsHtml() {
      if (this.selected) {
        return super.textAsHtml();
      } else {
        return `<el-type>${this.text}</el-type>`;
      }
    }
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
  };

  // src/ide/frames/parse-nodes/comment-node.ts
  var CommentNode = class extends RegExMatchNode {
    constructor(file) {
      super(file, Regexes.anythingToNewLineAsRegExp);
    }
  };

  // src/ide/frames/fields/comment-field.ts
  var CommentField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this.setOptional(true);
      this.setPlaceholder("<i>comment</i>");
    }
    helpId() {
      return "CommentField";
    }
    initialiseRoot() {
      this.rootNode = new CommentNode(this.getFile());
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readToEndOfLine();
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_comment`;
    }
    renderAsHtml() {
      const txt = this.isSelected() ? this.textAsHtml() : this.handleLeadingAndMultipleSpaces(escapeHtmlChars(this.textAsHtml()));
      return `<el-field id="${this.htmlId}" class="${this.cls()}" tabindex="-1"><el-txt>${txt}</el-txt><el-place>${this._placeholder}</el-place><el-compl>${this.getCompletion()}</el-compl>${this.getMessage()}${this.helpAsHtml()}</el-field>`;
    }
    // Converts leading spaces to &nbsp; and multi-spaces to a space + &nbsp;s
    handleLeadingAndMultipleSpaces(raw) {
      const words = raw.split(" ");
      const withNbsp = words.map((w) => w === "" ? "&nbsp;" : w + " ");
      return withNbsp.join("").trimEnd();
    }
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
    //Overridden to avoid trimming
    parseCompleteTextUsingNode(text, root) {
      if (text.length === 0) {
        this.setParseStatus(this.isOptional() ? 3 /* valid */ : 2 /* incomplete */);
      } else {
        root.parseText(text);
        this.setParseStatus(root.status);
        this.text = root.renderAsElanSource();
      }
    }
  };

  // src/ide/frames/statements/comment-statement.ts
  var CommentStatement = class extends SingleLineFrame {
    isStatement = true;
    isMember = true;
    isAbstract = false;
    private = false;
    canHaveBreakPoint = false;
    text;
    constructor(parent) {
      super(parent);
      this.text = new CommentField(this);
    }
    initialKeywords() {
      return commentMarker;
    }
    parseFrom(source) {
      source.removeIndent();
      source.remove("# ");
      this.text.parseFrom(source);
      source.removeNewLine();
    }
    getFields() {
      return [this.text];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_com`;
    }
    frameSpecificAnnotation() {
      return "";
    }
    renderAsHtml() {
      return `<el-statement>${this.contextMenu()}<el-comment class="${this.cls()}" id='${this.htmlId}' tabindex="-1" ${this.toolTip()}><el-top>${this.language().renderSingleLineAsHtml(this)}</el-top></el-comment></el-statement>`;
    }
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}# ${this.text.renderAsElanSource()}`;
    }
    deleteIfPermissible() {
      this.insertNewSelectorIfNecessary();
      this.delete();
    }
  };

  // src/ide/frames/fields/identifier-def-field.ts
  var IdentifierDefField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this.setPlaceholder("<i>name</i>");
    }
    helpId() {
      return "ValueDefField";
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_var`;
    }
    initialiseRoot() {
      this.rootNode = new IdentifierDef(this.getFile());
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readUntil(/(\s+((set to)|(be))\s+)|\r|\n/);
    isEndMarker(key) {
      return this.text.length === 0 ? false : key === " ";
    }
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
  };

  // src/ide/frames/statements/abstract-definition.statement.ts
  var AbstractDefinitionStatement = class extends SingleLineFrame {
    isStatement = true;
    name;
    expr;
    constructor(parent) {
      super(parent);
      this.name = new IdentifierDefField(this);
      this.expr = new ExpressionField(this);
    }
    getFields() {
      return [this.name, this.expr];
    }
  };

  // src/ide/frames/statements/let-statement.ts
  var LetStatement = class extends AbstractDefinitionStatement {
    isStatement = true;
    constructor(parent) {
      super(parent);
    }
    isConstant = false;
    initialKeywords() {
      return constantKeyword;
    }
    parseFrom(source) {
      source.removeIndent();
      source.remove(`${letKeyword} `);
      this.name.parseFrom(source);
      source.remove(` ${beKeyword} `);
      this.expr.parseFrom(source);
      source.removeNewLine();
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_let`;
    }
    frameSpecificAnnotation() {
      return "let";
    }
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}${letKeyword} ${this.name.renderAsElanSource()} ${beKeyword} ${this.expr.renderAsElanSource()}`;
    }
  };

  // src/ide/frames/parse-nodes/instanceNode.ts
  var InstanceNode = class extends AbstractSequence {
    variable;
    index;
    tokenTypes = /* @__PURE__ */ new Set([
      0 /* id_let */,
      3 /* id_parameter_regular */,
      2 /* id_property */,
      1 /* id_variable */
    ]);
    parseText(text) {
      if (text.length > 0) {
        this.variable = new IdentifierUse(this.file, this.tokenTypes);
        this.index = new Multiple(this.file, () => new Index(this.file), 0);
        this.addElement(this.variable);
        this.addElement(this.index);
        super.parseText(text);
      }
    }
    symbolCompletion_tokenTypes() {
      if (this.getElements().length === 0) {
        return new Set(allIds);
      } else {
        return super.symbolCompletion_tokenTypes();
      }
    }
  };

  // src/ide/frames/parse-nodes/property-instance-ref.ts
  var PropertyInstanceRef = class extends AbstractSequence {
    qualifier;
    name;
    constructor(file) {
      super(file);
      this.qualifier = new IdentifierUse(file);
      this.addElement(this.qualifier);
      this.addElement(new PunctuationNode(this.file, DOT));
      this.name = new InstanceNode(file);
      this.addElement(this.name);
    }
    renderAsHtml() {
      return this.isValid() ? `${this.qualifier.renderAsHtml()}.${this.name.renderAsHtml()}` : this.matchedText;
    }
  };

  // src/ide/frames/parse-nodes/property-ref.ts
  var PropertyRef = class extends AbstractSequence {
    name;
    constructor(file) {
      super(file);
      this.addElement(new ThisInstance(this.file));
      this.addElement(new PunctuationNode(this.file, DOT));
      this.name = new InstanceNode(file);
      this.addElement(this.name);
    }
    renderAsHtml() {
      const this_instance = this.file.language().THIS_INSTANCE;
      return this.isValid() ? `<el-kw>${this_instance}</el-kw>.${this.name.renderAsHtml()}` : this.matchedText;
    }
    renderAsElanSource() {
      return `${thisKeyword}.${this.name.renderAsElanSource()}`;
    }
  };

  // src/ide/frames/parse-nodes/assignable-node.ts
  var AssignableNode = class extends AbstractAlternatives {
    tokenTypes = /* @__PURE__ */ new Set([2 /* id_property */, 1 /* id_variable */]);
    constructor(file) {
      super(file);
      this.alternatives.push(new InstanceNode(file));
      this.alternatives.push(new PropertyRef(file));
      this.alternatives.push(new PropertyInstanceRef(file));
    }
    symbolCompletion_tokenTypes() {
      return /* @__PURE__ */ new Set([1 /* id_variable */, 2 /* id_property */]);
    }
    symbolCompletion_keywords() {
      const langExprKeywords = [this.file.language().THIS_INSTANCE];
      let kws = langExprKeywords.map((kw) => KeywordCompletion.create(kw));
      const trim = this.matchedText.trim();
      if (trim.length > 0) {
        kws = kws.filter((kw) => kw.keyword.startsWith(trim));
      }
      return new Set(kws);
    }
  };

  // src/ide/frames/fields/assignableField.ts
  var AssignableField = class extends AbstractField {
    delimiter;
    constructor(holder, delimiter = /(\s+to\s+)|\r|\n/) {
      super(holder);
      this.delimiter = delimiter;
      this.setPlaceholder("<i>variable</i>");
    }
    helpId() {
      return "AssignableField";
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_ident`;
    }
    initialiseRoot() {
      this.rootNode = new AssignableNode(this.getFile());
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readUntil(this.delimiter);
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
  };

  // src/ide/frames/statements/reassign-variable.ts
  var ReAssignVariable = class extends SingleLineFrame {
    isStatement = true;
    assignable;
    expr;
    constructor(parent) {
      super(parent);
      this.assignable = new AssignableField(this);
      this.assignable.setPlaceholder("<i>variableName</i>");
      this.expr = new ExpressionField(this);
    }
    initialKeywords() {
      return reassignKeyword;
    }
    parseFrom(source) {
      source.removeIndent();
      source.remove(`${reassignKeyword} `);
      this.assignable.parseFrom(source);
      source.remove(` ${toKeyword} `);
      this.expr.parseFrom(source);
      source.removeNewLine();
    }
    getFields() {
      return [this.assignable, this.expr];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_set`;
    }
    frameSpecificAnnotation() {
      return "reassign variable";
    }
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}${reassignKeyword} ${this.assignable.renderAsElanSource()} ${toKeyword} ${this.expr.renderAsElanSource()}`;
    }
  };

  // src/ide/frames/globals/class-frame.ts
  var ClassFrame = class extends AbstractFrame {
    isCollapsible = true;
    isParent = true;
    isClass = true;
    isAbstract = false;
    isConcrete = false;
    isRecord = false;
    isInterface = false;
    name;
    isNotInheritable = false;
    inheritance;
    _children = new Array();
    constructor(parent) {
      super(parent);
      this.name = new TypeNameField(this);
      this.inheritance = new InheritsFromField(this);
      this.getChildren().push(new MemberSelector(this));
      this.canHaveBreakPoint = false;
    }
    updateOfTypes(_ofTypes) {
      return this;
    }
    get subType() {
      if (this.isInterface) {
        return 2 /* interface */;
      }
      if (this.isAbstract) {
        return 1 /* abstract */;
      }
      return 0 /* concrete */;
    }
    getFile() {
      return this.getParent();
    }
    initialKeywords() {
      return classKeyword;
    }
    getProfile() {
      return this.getFile().getProfile();
    }
    setClasses() {
      super.setClasses();
      this.pushClass(true, "multiline");
    }
    updateParseStatus() {
      this.getChildren().forEach((c) => c.updateParseStatus());
      const worstOfFieldOrChildParseStatus = Math.min(
        this.worstParseStatusOfFields(),
        parentHelper_readWorstParseStatusOfChildren(this)
      );
      this.setParseStatus(worstOfFieldOrChildParseStatus);
    }
    readCompileStatus() {
      const worstOfChildren = parentHelper_readWorstCompileStatusOfChildren(this);
      const newStatus = Math.min(super.readCompileStatus(), worstOfChildren);
      return newStatus;
    }
    getFactory() {
      return this.getParent().getFactory();
    }
    getChildren() {
      return this._children;
    }
    getFirstChild() {
      return parentHelper_getFirstChild(this);
    }
    getLastChild() {
      return parentHelper_getLastChild(this);
    }
    getChildAfter(child) {
      return parentHelper_getChildAfter(this, child);
    }
    getChildBefore(child) {
      return parentHelper_getChildBefore(this, child);
    }
    getChildRange(first, last) {
      return parentHelper_getChildRange(this, first, last);
    }
    getFirstSelectorAsDirectChild() {
      return parentHelper_getFirstSelectorAsDirectChild(this);
    }
    addChildBefore(child, before) {
      parentHelper_addChildBefore(this, child, before);
    }
    addChildAfter(child, after) {
      parentHelper_addChildAfter(this, child, after);
    }
    removeChild(child) {
      parentHelper_removeChild(this, child);
    }
    insertOrGotoChildSelector(after, child) {
      parentHelper_insertOrGotoChildSelector(this, after, child);
    }
    deleteSelectedChildren() {
      parentHelper_deleteSelectedChildren(this);
    }
    copySelectedChildren(encode) {
      return parentHelper_copySelectedChildren(this, encode);
    }
    exportSelectedChildren() {
      return parentHelper_exportSelectedChildren(this);
    }
    moveSelectedChildrenUpOne() {
      parentHelper_moveSelectedChildrenUpOne(this);
    }
    moveSelectedChildrenDownOne() {
      parentHelper_moveSelectedChildrenDownOne(this);
    }
    fieldUpdated(_field) {
    }
    minimumNumberOfChildrenExceeded() {
      return this.getChildren().length > 1;
    }
    selectNextFrame() {
      this._children[0]?.select(true, false);
    }
    doesInherit() {
      return this.inheritance.text !== "";
    }
    getFields() {
      return [this.name, this.inheritance];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_class`;
    }
    inheritanceAsHtml() {
      return this.inheritance.renderAsHtml();
    }
    inheritanceAsElanSource() {
      return this.doesInherit() ? ` ${inheritsKeyword} ${this.inheritance.renderAsElanSource()}` : ``;
    }
    indent() {
      return "";
    }
    properties() {
      return this.getChildren().filter(
        (c) => c instanceof Property || c instanceof AbstractProperty
      );
    }
    seenTwice(name, seenNames) {
      return seenNames.filter((s) => s === name).length > 1;
    }
    createConstructor() {
      return new Constructor(this);
    }
    createFunction(priv = false) {
      return new FunctionMethod(this, priv);
    }
    createWithMethod() {
      const wm = new FunctionMethod(this, false);
      wm.name.setPlaceholder("<i>withPropertyName</i>");
      const className = this.name.text;
      wm.returnType.setFieldToKnownValidText(className);
      const defaultSelector = wm.getFirstSelectorAsDirectChild();
      const letCopyOfThis = new LetStatement(this);
      letCopyOfThis.name.setFieldToKnownValidText("copyOfThis");
      letCopyOfThis.expr.setFieldToKnownValidText("copy(this)");
      wm.addChildBefore(letCopyOfThis, defaultSelector);
      const firstProp = new ReAssignVariable(this);
      firstProp.assignable.setPlaceholder("copyOfThis.propertyName");
      wm.addChildBefore(firstProp, defaultSelector);
      const ret = wm.getLastChild();
      ret.expr.setFieldToKnownValidText("copyOfThis");
      wm.removeChild(defaultSelector);
      return wm;
    }
    createProperty(priv = false) {
      return new Property(this, priv);
    }
    createProcedure(priv = false) {
      return new ProcedureMethod(this, priv);
    }
    createAbstractFunction() {
      return new AbstractFunction(this);
    }
    createAbstractProperty() {
      return new AbstractProperty(this);
    }
    createAbstractProcedure() {
      return new AbstractProcedure(this);
    }
    createComment() {
      return new CommentStatement(this);
    }
    getConstructor() {
      return this.getChildren().filter((m) => isConstructor(m))[0];
    }
    parseFrom(source) {
      this.parseTop(source);
      while (!this.parseBottom(source)) {
        if (source.isMatchRegEx(Regexes.newLine)) {
          source.removeRegEx(Regexes.newLine, false);
          source.removeIndent();
        } else {
          this.getFirstSelectorAsDirectChild().parseFrom(source);
        }
      }
    }
    parseTop(source) {
      source.remove(this.topKeywords());
      this.name.parseFrom(source);
      source.removeRegEx(/^\sinherits\s/, true);
      this.inheritance.parseFrom(source);
      return true;
    }
    parseBottom(source) {
      let result = false;
      source.removeIndent();
      if (source.isMatch(this.bottomKeywords())) {
        source.remove(this.bottomKeywords());
        result = true;
      }
      return result;
    }
    newChildSelector() {
      return new MemberSelector(this);
    }
    getClassIndex() {
      return this.getParent().getChildren().indexOf(this);
    }
    updateBreakpoints(event) {
      super.updateBreakpoints(event);
      parentHelper_updateBreakpoints(this, event);
    }
    ghostSelectedChildren() {
      setGhostOnSelectedChildren(this, true);
    }
    unghostSelectedChildren() {
      setGhostOnSelectedChildren(this, false);
    }
    deleteAllGhosted() {
      if (this.isGhosted()) {
        this.delete();
      } else {
        for (const child of this._children) {
          child.deleteAllGhosted();
        }
      }
    }
    outerHtmlTag = "el-member";
    renderAsHtml() {
      return `<el-class class="${this.cls()}" id='${this.htmlId}' tabindex="-1" ${this.toolTip()}>
<el-top>${this.contextMenu()}${this.bpAsHtml()}<el-expand>+</el-expand>${this.language().renderTopAsHtml(this)}${this.helpAsHtml()}${this.compileMsgAsHtml()}${this.annotationAsHtml()}${this.getFrNo()}</el-top>
${parentHelper_renderChildrenAsHtml(this)}
${this.language().renderBottomAsHtml(this)}
</el-class>`;
    }
    renderAsExport() {
      const topAsExport = removeHtmlTagsAndEscChars(this.language().renderTopAsHtml(this));
      const bottomAsExport = removeHtmlTagsAndEscChars(this.language().renderBottomAsHtml(this));
      return `${this.indent()}${this.sourceAnnotations()}${topAsExport}${this.annotationAsSource()}\r

${parentHelper_renderChildrenAsExport(this)}
${bottomAsExport}`;
    }
    resetFieldText() {
      super.resetFieldText();
      parentHelper_resetFieldTextOnChildren(this);
    }
  };

  // src/ide/frames/globals/abstract-class.ts
  var AbstractClass = class extends ClassFrame {
    constructor(parent) {
      super(parent);
      this.isAbstract = true;
    }
    initialKeywords() {
      return abstractClassKeywords;
    }
    doesInherit() {
      return this.inheritance.text !== "";
    }
    getFields() {
      return [this.name, this.inheritance];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_class`;
    }
    frameSpecificAnnotation() {
      return "abstract class";
    }
    renderAsElanSource() {
      return `${this.sourceAnnotations()}${abstractKeyword} ${classKeyword} ${this.name.renderAsElanSource()}${this.inheritanceAsElanSource()}\r
${parentHelper_renderChildrenAsElanSource(this)}\r
${endKeyword} ${classKeyword}\r
`;
    }
    topKeywords() {
      return `${abstractClassKeywords} `;
    }
    bottomKeywords() {
      return `${endKeyword} ${classKeyword}`;
    }
  };

  // src/ide/frames/statements/return-statement.ts
  var ReturnStatement = class extends SingleLineFrame {
    isStatement = true;
    isReturnStatement = true;
    expr;
    constructor(parent) {
      super(parent);
      this.ghostable = false;
      this.expr = new ExpressionField(this);
    }
    initialKeywords() {
      return returnKeyword;
    }
    isDeletable() {
      return false;
    }
    isMovable() {
      return false;
    }
    getFields() {
      return [this.expr];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_return`;
    }
    frameSpecificAnnotation() {
      return "return";
    }
    renderAsElanSource() {
      return `${this.indent()}return ${this.expr.renderAsElanSource()}`;
    }
    parseFrom(source) {
      source.removeIndent();
      source.remove("return ");
      this.expr.parseFrom(source);
    }
    canInsertAfter() {
      return false;
    }
  };

  // src/ide/frames/globals/function-frame.ts
  var FunctionFrame = class extends FrameWithStatements {
    name;
    params;
    returnType;
    isFunction = true;
    constructor(parent) {
      super(parent);
      this.name = new MethodNameField(this);
      this.params = new ParamListField(this);
      this.returnType = new TypeField(this);
      this.getChildren().push(new ReturnStatement(this));
    }
    initialKeywords() {
      return functionKeyword;
    }
    getProfile() {
      return this.getFile().getProfile();
    }
    minimumNumberOfChildrenExceeded() {
      return this.getChildren().length > 1;
    }
    getFields() {
      return this.file.language().getFields(this);
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_func`;
    }
    frameSpecificAnnotation() {
      return "function";
    }
    outerHtmlTag = "el-func";
    parseTop(source) {
      source.remove(`${functionKeyword} `);
      this.name.parseFrom(source);
      source.remove("(");
      this.params.parseFrom(source);
      source.remove(`) ${returnsKeyword} `);
      this.returnType.parseFrom(source);
    }
    parseBottom(source) {
      let result = false;
      source.removeIndent();
      if (source.isMatch(`${returnKeyword} `)) {
        const ret = this.getLastChild();
        ret.parseFrom(source);
        source.removeNewLine().removeIndent();
        this.parseStandardEnding(source, `${endKeyword} ${functionKeyword}`);
        result = true;
      }
      return result;
    }
  };

  // src/ide/frames/class-members/function-method.ts
  var FunctionMethod = class extends FunctionFrame {
    isMember = true;
    isPrivate;
    isAbstract = false;
    file;
    constructor(parent, priv = false) {
      super(parent);
      this.file = parent.getFile();
      this.isPrivate = priv;
    }
    isOnAbstractClass() {
      return this.getParent() instanceof AbstractClass;
    }
    helpId() {
      return "function_method";
    }
    indent() {
      return singleIndent();
    }
    frameSpecificAnnotation() {
      const priv = this.isPrivate ? "private " : "";
      return `${priv}function method`;
    }
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}${modifierAsElanSource(this)}${functionKeyword} ${this.name.renderAsElanSource()}(${this.params.renderAsElanSource()}) ${returnsKeyword} ${this.returnType.renderAsElanSource()}\r
${this.renderChildrenAsElanSource()}\r
${this.indent()}${endKeyword} ${functionKeyword}\r
`;
    }
    parseTop(source) {
      source.removeIndent();
      const priv = `${privateKeyword} `;
      if (source.isMatch(priv)) {
        source.remove(priv);
        this.isPrivate = true;
      }
      super.parseTop(source);
    }
    parseBottom(source) {
      return super.parseBottom(source);
    }
    makePublic = () => {
      this.isPrivate = false;
      return true;
    };
    makePrivate = () => {
      this.isPrivate = true;
      return true;
    };
    getContextMenuItems() {
      const map = super.getContextMenuItems();
      addPrivateToggleToContextMenu(this, map);
      return map;
    }
    processKey(e) {
      if (e.modKey.control && e.key === "p") {
        return togglePrivatePublic(this);
      }
      return super.processKey(e);
    }
    renderAsExport() {
      return `${super.renderAsExport()}\r
`;
    }
  };

  // src/ide/frames/globals/concrete-class.ts
  var ConcreteClass = class extends ClassFrame {
    constr;
    toString;
    constructor(parent) {
      super(parent);
      this.isConcrete = true;
      this.constr = new Constructor(this);
      this.getChildren().push(this.constr);
      this.toString = new FunctionMethod(this);
      this.toString.name.setFieldToKnownValidText("toString");
      this.toString.returnType.setFieldToKnownValidText("String");
      const newCode = this.toString.getFirstChild();
      this.toString.removeChild(newCode);
      this.toString.getLastChild().expr.setFieldToKnownValidText(`"undefined"`);
      this.getChildren().push(this.toString);
    }
    initialKeywords() {
      return classKeyword;
    }
    doesInherit() {
      return this.inheritance.text !== "";
    }
    getFields() {
      return [this.name, this.inheritance];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_class`;
    }
    frameSpecificAnnotation() {
      return "concrete class";
    }
    renderAsElanSource() {
      return `${this.sourceAnnotations()}${classKeyword} ${this.name.renderAsElanSource()}${this.inheritanceAsElanSource()}\r
${parentHelper_renderChildrenAsElanSource(this)}\r
${endKeyword} ${classKeyword}\r
`;
    }
    topKeywords() {
      return `${classKeyword} `;
    }
    bottomKeywords() {
      return `${endKeyword} ${classKeyword}`;
    }
    parseBottom(source) {
      source.removeIndent();
      if (source.isMatchRegEx(/^constructor\(/)) {
        this.constr.parseFrom(source);
        this.removeChild(this.getFirstSelectorAsDirectChild());
        this.addChildAfter(new MemberSelector(this), this.constr);
      }
      source.removeIndent();
      if (source.isMatchRegEx(/^function toString\(/)) {
        this.toString.parseFrom(source);
        this.removeChild(this.getFirstSelectorAsDirectChild());
        this.addChildAfter(new MemberSelector(this), this.toString);
      }
      return super.parseBottom(source);
    }
  };

  // src/ide/frames/parse-nodes/constant-value-node.ts
  var ConstantValueNode = class _ConstantValueNode extends AbstractAlternatives {
    constructor(file) {
      super(file);
      this.completionWhenEmpty = "";
    }
    parseText(text) {
      this.alternatives.push(new LitValueNode(this.file));
      this.alternatives.push(new IdentifierUse(this.file));
      this.alternatives.push(new TupleNode(this.file));
      this.alternatives.push(new ListNode(this.file, () => new _ConstantValueNode(this.file)));
      this.alternatives.push(
        new DictionaryNode(
          this.file,
          () => new _ConstantValueNode(this.file),
          () => new _ConstantValueNode(this.file)
        )
      );
      super.parseText(text);
    }
  };

  // src/ide/frames/fields/constant-value-field.ts
  var ConstantValueField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this.setPlaceholder("<i>literal</i>");
    }
    helpId() {
      return "ConstantValueField";
    }
    initialiseRoot() {
      this.rootNode = new ConstantValueNode(this.getFile());
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readToEndOfLine();
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
    getElanType() {
      const scope = this.getFile().getAst(true)?.getScopeById(this.getHolder().getHtmlId());
      if (isSymbol(scope)) {
        return scope.symbolType().name;
      }
      return "";
    }
  };

  // src/ide/frames/globals/constant-global.ts
  var ConstantGlobal = class extends SingleLineFrame {
    isCollapsible = true;
    isGlobal = true;
    name;
    value;
    file;
    isConstant = true;
    constructor(parent) {
      super(parent);
      this.file = parent;
      this.name = new IdentifierDefField(this);
      this.value = new ConstantValueField(this);
      this.value.setPlaceholder("<i>literal value or data structure</i>");
      this.canHaveBreakPoint = false;
    }
    initialKeywords() {
      return constantKeyword;
    }
    parseFrom(source) {
      source.remove("constant ");
      this.name.parseFrom(source);
      source.remove(" set to ");
      this.value.parseFrom(source);
    }
    setClasses() {
      super.setClasses();
      this.pushClass(true, "multiline");
    }
    getFields() {
      return [this.name, this.value];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_const`;
    }
    frameSpecificAnnotation() {
      return "constant";
    }
    outerHtmlTag = "el-const";
    renderAsHtml() {
      return `<${this.outerHtmlTag} class="${this.cls()}" id='${this.htmlId}' tabindex="-1" ${this.toolTip()}><el-top>${this.contextMenu()}${this.bpAsHtml()}<el-expand>+</el-expand>${this.language().renderSingleLineAsHtml(this)}${this.helpAsHtml()}${this.compileMsgAsHtml()}${this.annotationAsHtml()}${this.getFrNo()}</${this.outerHtmlTag}>`;
    }
    indent() {
      return "";
    }
    renderAsElanSource() {
      return `${this.sourceAnnotations()}constant ${this.name.renderAsElanSource()} set to ${this.value.renderAsElanSource()}\r
`;
    }
  };

  // src/ide/frames/parse-nodes/enum-values-list.ts
  var EnumValuesList = class extends CSV {
    constructor(file) {
      super(file, () => new IdentifierUse(file), 1);
      this.setSyntaxCompletionWhenEmpty("<i>enum values (comma separated)</i>");
    }
  };

  // src/ide/frames/fields/enum-values-field.ts
  var EnumValuesField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this.setPlaceholder("<i>values</i>");
    }
    helpId() {
      return "EnumValuesField";
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_enumVals`;
    }
    initialiseRoot() {
      this.rootNode = new EnumValuesList(this.getFile());
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readToEndOfLine();
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
    renderAsHtml() {
      let result = "";
      if (this.isSelected()) {
        result = super.renderAsHtml();
      } else {
        const textAsHtml = this.getFile().language().enumValuesListAsHtml(this);
        result = `<el-field id="${this.htmlId}" class="${this.cls()}" tabindex="-1"><el-txt>${textAsHtml}</el-txt><el-place>${this._placeholder}</el-place>${this.getMessage()}${this.helpAsHtml()}</el-field>`;
      }
      return result;
    }
    default_renderAsHtml() {
      return super.renderAsHtml();
    }
  };

  // src/ide/frames/globals/enum.ts
  var Enum = class extends SingleLineFrame {
    isGlobal = true;
    name;
    values;
    file;
    constructor(parent) {
      super(parent);
      this.file = parent;
      this.name = new TypeNameField(this);
      this.name.setPlaceholder("<i>Name</i>");
      this.values = new EnumValuesField(this);
      this.canHaveBreakPoint = false;
    }
    setClasses() {
      super.setClasses();
      this.pushClass(true, "multiline");
    }
    initialKeywords() {
      return enumKeyword;
    }
    getFields() {
      return [this.name, this.values];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_enum`;
    }
    frameSpecificAnnotation() {
      return "enum";
    }
    outerHtmlTag = "el-enum";
    indent() {
      return "";
    }
    renderAsElanSource() {
      return `${this.sourceAnnotations()}enum ${this.name.renderAsElanSource()} ${this.values.renderAsElanSource()}\r
`;
    }
    parseFrom(source) {
      source.remove("enum ");
      this.name.parseFrom(source);
      this.values.parseFrom(source);
    }
  };

  // src/ide/frames/globals/global-comment.ts
  var GlobalComment = class extends SingleLineFrame {
    isGlobal = true;
    text;
    file;
    canHaveBreakPoint = false;
    constructor(parent) {
      super(parent);
      this.file = parent;
      this.text = new CommentField(this);
    }
    initialKeywords() {
      return commentMarker;
    }
    getFields() {
      return [this.text];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_com`;
    }
    frameSpecificAnnotation() {
      return "";
    }
    outerHtmlTag = "";
    renderAsHtml() {
      return `<el-global>${this.contextMenu()}<el-comment class="${this.cls()}" id='${this.htmlId}' tabindex="-1" ${this.toolTip()}><el-top>${this.language().renderSingleLineAsHtml(this)}</el-top></el-comment></el-global>`;
    }
    indent() {
      return "";
    }
    renderAsElanSource() {
      return `${this.sourceAnnotations()}# ${this.text.renderAsElanSource()}`;
    }
    parseFrom(source) {
      source.removeIndent();
      source.remove("# ");
      this.text.parseFrom(source);
      source.removeNewLine();
    }
    deleteIfPermissible() {
      this.insertNewSelectorIfNecessary();
      this.delete();
    }
  };

  // src/ide/frames/globals/global-function.ts
  var GlobalFunction = class extends FunctionFrame {
    isGlobal = true;
    file;
    constructor(parent) {
      super(parent);
      this.file = parent;
    }
    indent() {
      return "";
    }
    renderAsElanSource() {
      return `${this.sourceAnnotations()}${functionKeyword} ${this.name.renderAsElanSource()}(${this.params.renderAsElanSource()}) ${returnsKeyword} ${this.returnType.renderAsElanSource()}\r
${this.renderChildrenAsElanSource()}\r
${endKeyword} ${functionKeyword}\r
`;
    }
  };

  // src/ide/frames/globals/global-procedure.ts
  var GlobalProcedure = class extends ProcedureFrame {
    isGlobal = true;
    constructor(parent) {
      super(parent);
    }
    indent() {
      return "";
    }
    renderAsElanSource() {
      return `${this.sourceAnnotations()}procedure ${this.name.renderAsElanSource()}(${this.params.renderAsElanSource()})\r
${this.renderChildrenAsElanSource()}\r
end procedure\r
`;
    }
  };

  // src/ide/frames/globals/interface-frame.ts
  var InterfaceFrame = class extends ClassFrame {
    constructor(parent) {
      super(parent);
      this.isAbstract = true;
      this.isInterface = true;
      this.canHaveBreakPoint = false;
    }
    initialKeywords() {
      return interfaceKeyword;
    }
    doesInherit() {
      return this.inheritance.text !== "";
    }
    getFields() {
      return [this.name, this.inheritance];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_class`;
    }
    frameSpecificAnnotation() {
      return "interface";
    }
    renderAsElanSource() {
      return `${this.sourceAnnotations()}${interfaceKeyword} ${this.name.renderAsElanSource()}${this.inheritanceAsElanSource()}\r
${parentHelper_renderChildrenAsElanSource(this)}\r
${endKeyword} ${interfaceKeyword}\r
`;
    }
    topKeywords() {
      return `${interfaceKeyword} `;
    }
    bottomKeywords() {
      return `${endKeyword} ${interfaceKeyword}`;
    }
  };

  // src/ide/frames/globals/main-frame.ts
  var MainFrame = class extends FrameWithStatements {
    isMain = true;
    isGlobal = true;
    file;
    constructor(parent) {
      super(parent);
      this.file = parent;
    }
    initialKeywords() {
      return mainKeyword;
    }
    getFields() {
      return [];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_main`;
    }
    frameSpecificAnnotation() {
      return "main";
    }
    get symbolId() {
      return "__main";
    }
    outerHtmlTag = "el-main";
    indent() {
      return "";
    }
    renderAsElanSource() {
      return `${this.sourceAnnotations()}main\r
${this.renderChildrenAsElanSource()}\r
end main\r
`;
    }
    parseTop(source) {
      source.remove("main");
    }
    parseBottom(source) {
      return this.parseStandardEnding(source, "end main");
    }
  };

  // src/ide/frames/parse-nodes/testName.ts
  var TestName = class extends AbstractParseNode {
    tokenTypes;
    contextGenerator;
    prefix = "test_";
    constructor(file, tokenTypes = /* @__PURE__ */ new Set(), contextGenerator = () => "") {
      super(file);
      this.tokenTypes = tokenTypes;
      this.contextGenerator = contextGenerator;
    }
    parseText(text) {
      if (text.length === 0 || this.prefix.startsWith(text)) {
        text = this.prefix;
        this.status = 2 /* incomplete */;
        this.matchedText = text;
        this.remainingText = "";
      } else {
        if (!text.startsWith(this.prefix)) {
          text = this.prefix + text;
        }
        [this.status, this.matchedText, this.remainingText] = matchRegEx(
          text.trimStart(),
          /test_[a-zA-Z0-9_]+/
        );
      }
      if (this.isValid() && this.remainingText.length > 0) {
        this._done = true;
      }
    }
    symbolCompletion_tokenTypes() {
      return this.tokenTypes;
    }
    symbolCompletion_context() {
      return this.contextGenerator();
    }
    renderAsHtml() {
      return this.isValid() ? `<el-method>${this.matchedText.trim()}</el-method>` : this.matchedText;
    }
  };

  // src/ide/frames/fields/test-name-field.ts
  var TestNameField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this._placeholder = "test_name";
    }
    helpId() {
      return "IdentifierField";
    }
    initialiseRoot() {
      this.rootNode = new TestName(this.getFile());
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readUntil(/[^a-zA-Z0-9_]/);
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_ident`;
    }
    isEndMarker(key) {
      return key === " " || key === "(";
    }
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
  };

  // src/ide/frames/globals/test-frame.ts
  var TestFrame = class extends FrameWithStatements {
    isTest = true;
    isGlobal = true;
    testName;
    file;
    _testStatus;
    canHaveBreakPoint = false;
    constructor(parent) {
      super(parent);
      this.file = parent;
      this.testName = new TestNameField(this);
      this._testStatus = 5 /* default */;
    }
    readDisplayStatus() {
      let overall = 0 /* error */;
      const parseCompile = helper_CompileOrParseAsDisplayStatus(this);
      if (parseCompile !== 3 /* ok */) {
        overall = parseCompile;
      } else {
        overall = helper_testStatusAsDisplayStatus(this._testStatus);
      }
      return overall;
    }
    readTestStatus() {
      return this._testStatus;
    }
    updateTestStatus() {
      const tests = this.getChildren().filter((c) => c instanceof AssertStatement && !c.isGhosted()).map((c) => c);
      const worstOf = (a, b) => a < b ? a : b;
      const worst = tests.reduce((prev, t) => worstOf(t.getTestStatus(), prev), 5 /* default */);
      this._testStatus = worstOf(this._testStatus, worst);
    }
    resetTestStatus() {
      this._testStatus = 5 /* default */;
      for (const assert of this.getAsserts()) {
        assert.outcome = void 0;
      }
    }
    initialKeywords() {
      return testKeyword;
    }
    getFields() {
      return [this.testName];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_test`;
    }
    frameSpecificAnnotation() {
      return "test";
    }
    outerHtmlTag = "el-test";
    indent() {
      return "";
    }
    renderAsElanSource() {
      return `${this.sourceAnnotations()}test ${this.testName.renderAsElanSource()}\r
${this.renderChildrenAsElanSource()}\r
end test\r
`;
    }
    parseTop(source) {
      source.remove("test ");
      this.testName.parseFrom(source);
    }
    parseBottom(source) {
      return this.parseStandardEnding(source, "end test");
    }
    setAssertOutcomes(outcomes) {
      this.resetTestStatus();
      const asserts = this.getAsserts();
      if (outcomes.some((o) => o.status === 0 /* error */)) {
        this._testStatus = 0 /* error */;
        for (const assert of asserts) {
          assert.outcome = void 0;
        }
      } else {
        for (const assert of asserts) {
          const match3 = outcomes.filter((o) => o.htmlId === assert.getHtmlId());
          if (match3.length === 1) {
            assert.setOutcome(match3[0]);
          }
        }
      }
    }
    compileOrTestMsgAsHtml() {
      if (this._testStatus === 0 /* error */) {
        return this.testMsgAsHtml();
      }
      return super.compileMsgAsHtml();
    }
    testMsgAsHtml() {
      return ` <el-msg class="${DisplayColour[0 /* error */]}">failed to run</el-msg>`;
    }
    clearBreakPoint = () => {
      this.breakpointStatus = 0 /* none */;
      return false;
    };
  };

  // src/ide/frames/parse-nodes/type-simple-or-generic.ts
  var TypeSimpleOrGeneric = class extends AbstractAlternatives {
    tokenTypes = /* @__PURE__ */ new Set();
    constructor(file, tokenTypes = /* @__PURE__ */ new Set()) {
      super(file);
      this.completionWhenEmpty = "<i>Type</i>";
      this.tokenTypes = tokenTypes;
    }
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        this.alternatives.push(new TypeNameUse(this.file, this.tokenTypes));
        this.alternatives.push(new TypeGenericNode(this.file, this.tokenTypes));
        super.parseText(text);
      }
    }
    symbolCompletion_tokenTypes() {
      return this.matchedText.length === 0 ? this.tokenTypes : super.symbolCompletion_tokenTypes();
    }
    symbolCompletion_context() {
      return "none";
    }
  };

  // src/ide/frames/fields/arg-list-field.ts
  var ArgListField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this.setPlaceholder("<i>arguments</i>");
      this.setOptional(true);
    }
    helpId() {
      return "ArgListField";
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_args`;
    }
    contentAsSource() {
      if (this.text) {
        return this.text;
      } else {
        return "";
      }
    }
    initialiseRoot() {
      this.rootNode = new ArgListNode(this.getFile(), () => "");
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readToNonMatchingCloseBracket();
    isEndMarker(key) {
      return this.text === "" && key === ")";
    }
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
    completionOverride = "";
    argumentDescriptions(holder, scope) {
      const proc = holder.proc.text;
      const ps = scope?.resolveSymbol(proc, true, scope);
      let descriptions = ["<i>arguments</i>"];
      if (ps && !(ps instanceof UnknownSymbol)) {
        descriptions = parameterNames(ps.symbolType());
      }
      return descriptions;
    }
    textAsHtml() {
      const holder = this.getHolder();
      const descriptions = this.argumentDescriptions(
        holder,
        this.getFile().getAst(false)?.getScopeById(holder.getHtmlId())
      );
      if (this.text) {
        const count = currentParameterIndex(this.text);
        const remainingTypes = descriptions.slice(count).join(", ");
        this.completionOverride = remainingTypes ? `<i>${remainingTypes}</i>` : "";
      } else {
        this.completionOverride = "";
        const allTypes = descriptions.join(", ");
        this.setPlaceholder(`<i>${allTypes}</i>`);
      }
      let result = super.textAsHtml();
      if (this.getFile().doingExport) {
        result = this.getFile().language().translateExpression(result);
      }
      return result;
    }
    getCompletion() {
      return this.completionOverride || super.getCompletion();
    }
    parseCurrentText() {
      super.parseCurrentText();
      if (this.readParseStatus() === 0 /* invalid */ && this.text.endsWith(")")) {
        const oldText = this.text;
        this.text = this.text.slice(0, this.text.length - 1);
        super.parseCurrentText();
        if (this.readParseStatus() !== 3 /* valid */) {
          this.text = oldText;
        }
      }
    }
  };

  // src/ide/frames/parse-nodes/dot-after.ts
  var DotAfter = class extends AbstractSequence {
    node;
    constructor(file, node) {
      super(file);
      this.node = node;
    }
    parseText(text) {
      if (text.length > 0) {
        this.addElement(this.node);
        this.addElement(new PunctuationNode(this.file, DOT));
        super.parseText(text);
      }
    }
  };

  // src/ide/frames/parse-nodes/instanceProcRef.ts
  var InstanceProcRef = class extends AbstractSequence {
    prefix;
    procName;
    tokenTypes = /* @__PURE__ */ new Set([
      0 /* id_let */,
      3 /* id_parameter_regular */,
      2 /* id_property */,
      1 /* id_variable */,
      10 /* method_procedure */
    ]);
    parseText(text) {
      if (text.length > 0) {
        const instance = new InstanceNode(this.file);
        this.prefix = new DotAfter(this.file, instance);
        this.procName = new MethodNameUse(
          this.file,
          /* @__PURE__ */ new Set([10 /* method_procedure */]),
          () => instance.matchedText
        );
        this.addElement(this.prefix);
        this.addElement(this.procName);
        super.parseText(text);
      }
    }
    renderAsHtml() {
      return this.isValid() ? `${this.prefix.renderAsHtml()}<el-method>${this.procName?.renderAsHtml()}</el-method>` : this.matchedText;
    }
    symbolCompletion_tokenTypes() {
      if (this.getElements().length === 0) {
        return new Set(this.tokenTypes);
      } else {
        return super.symbolCompletion_tokenTypes();
      }
    }
    symbolCompletion_keywords() {
      const thisInstance = this.file.language().THIS_INSTANCE;
      return this.getElements().length === 0 ? /* @__PURE__ */ new Set([KeywordCompletion.create(thisInstance, false, true)]) : super.symbolCompletion_keywords();
    }
  };

  // src/ide/frames/parse-nodes/thisProcRef.ts
  var ThisProcRef = class extends AbstractSequence {
    thisInstance;
    procName;
    tokenTypes = /* @__PURE__ */ new Set([
      0 /* id_let */,
      3 /* id_parameter_regular */,
      2 /* id_property */,
      1 /* id_variable */,
      10 /* method_procedure */
    ]);
    parseText(text) {
      if (text.length > 0) {
        this.thisInstance = new ThisInstance(this.file);
        this.procName = new MethodNameUse(this.file);
        this.addElement(this.thisInstance);
        this.addElement(new PunctuationNode(this.file, DOT));
        this.addElement(this.procName);
        super.parseText(text);
      }
    }
    renderAsHtml() {
      return this.isValid() ? `${this.thisInstance.renderAsHtml()}.<el-method>${this.procName?.renderAsHtml()}</el-method>` : this.matchedText;
    }
    renderAsElanSource() {
      return this.isValid() ? `${thisKeyword}.${this.procName?.renderAsElanSource()}` : this.matchedText;
    }
    symbolCompletion_tokenTypes() {
      if (this.getElements().length === 0) {
        return new Set(this.tokenTypes);
      } else {
        return super.symbolCompletion_tokenTypes();
      }
    }
    symbolCompletion_keywords() {
      const thisInstance = this.file.language().THIS_INSTANCE;
      return this.getElements().length === 0 ? /* @__PURE__ */ new Set([KeywordCompletion.create(thisInstance, false, true)]) : super.symbolCompletion_keywords();
    }
  };

  // src/ide/frames/parse-nodes/proc-ref-node.ts
  var ProcRefNode = class extends AbstractAlternatives {
    constructor(f) {
      super(f);
      this.alternatives.push(new MethodNameUse(f, /* @__PURE__ */ new Set([10 /* method_procedure */])));
      this.alternatives.push(new ThisProcRef(f));
      this.alternatives.push(new InstanceProcRef(f));
    }
    getProcName() {
      let procName = "";
      if (this.bestMatch instanceof InstanceProcRef) {
        procName = this.bestMatch.procName.matchedText;
      } else if (this.bestMatch instanceof MethodNameUse) {
        procName = this.matchedText;
      }
      return procName;
    }
  };

  // src/ide/frames/fields/proc-ref-field.ts
  var ProcRefField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this.setPlaceholder("<i>procedureName</i>");
    }
    helpId() {
      return "ProcRefField";
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_ident`;
    }
    initialiseRoot() {
      this.rootNode = new ProcRefNode(this.getFile());
      this.rootNode.setSyntaxCompletionWhenEmpty(this._placeholder);
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readUntil(/\(/);
    textAsHtml() {
      let text;
      if (this.isSelected()) {
        text = this.fieldAsInput() + this.symbolCompletion();
      } else if (this.readParseStatus() === 3 /* valid */) {
        const bestMatch = this.rootNode.bestMatch;
        if (bestMatch instanceof MethodNameUse) {
          text = bestMatch.renderAsHtml();
        } else {
          text = bestMatch.renderAsHtml();
        }
      } else {
        text = super.textAsHtml();
      }
      return text;
    }
    isEndMarker(key) {
      return key === "(";
    }
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
  };

  // src/ide/frames/statements/call-statement.ts
  var CallStatement = class extends SingleLineFrame {
    isStatement = true;
    isCall = true;
    proc;
    args;
    constructor(parent) {
      super(parent);
      this.proc = new ProcRefField(this);
      this.proc.setPlaceholder("<i>procedureName</i>");
      this.args = new ArgListField(this);
    }
    initialKeywords() {
      return callKeyword;
    }
    parseFrom(source) {
      source.removeIndent();
      source.remove("call ");
      this.proc.parseFrom(source);
      source.remove("(");
      this.args.parseFrom(source);
      source.remove(")");
      source.removeNewLine();
    }
    getFields() {
      return [this.proc, this.args];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_call`;
    }
    frameSpecificAnnotation() {
      return this.proc.text === "print" ? "" : "call procedure";
    }
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}call ${this.proc.renderAsElanSource()}(${this.args.renderAsElanSource()})`;
    }
  };

  // src/ide/frames/statements/variable-statement.ts
  var VariableStatement = class extends AbstractDefinitionStatement {
    isVariableStatement = true;
    constructor(parent) {
      super(parent);
    }
    initialKeywords() {
      return variableKeyword;
    }
    parseFrom(source) {
      source.removeIndent();
      source.remove(`${variableKeyword} `);
      this.name.parseFrom(source);
      source.remove(` ${setKeyword} ${toKeyword} `);
      this.expr.parseFrom(source);
      source.removeNewLine();
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_var`;
    }
    frameSpecificAnnotation() {
      return "variable definition";
    }
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}${variableKeyword} ${this.name.renderAsElanSource()} ${setKeyword} ${toKeyword} ${this.expr.renderAsElanSource()}`;
    }
  };

  // src/ide/frames/language-abstract.ts
  var LanguageAbstract = class {
    constructor() {
    }
    commentRegex() {
      return /# [^\r\n]*/;
    }
    languageHtmlClass = "python";
    languageFullName = "Python";
    defaultFileExtension = "py";
    defaultMimeType = "text/x-python";
    annotation(frame) {
      let annotation = "";
      if (frame instanceof VariableStatement || frame instanceof ConstantGlobal || frame instanceof LetStatement || frame instanceof FunctionFrame || frame instanceof ProcedureFrame || frame instanceof CallStatement || frame instanceof ReAssignVariable) {
        annotation = frame.frameSpecificAnnotation();
      }
      return annotation;
    }
    default_litStringInterpolatedAsHtml(node) {
      return `${this.INTERPOLATED_STRING_PREFIX}"${node.segments.renderAsHtml()}"`;
    }
    default_typeTupleAsHtml(node) {
      return `(${node.types?.renderAsHtml()})`;
    }
    default_standardiseInterpolatedString(_node, text) {
      return text.startsWith(this.INTERPOLATED_STRING_PREFIX) ? "$" + text.substring(1) : text;
    }
    addCommonElementsForNewInstance(node) {
      node.type = new TypeSimpleOrGeneric(node.file, /* @__PURE__ */ new Set([6 /* type_concrete */]));
      node.addElement(node.type);
      node.addElement(new SpaceNode(node.file, 0 /* ignored */));
      node.addElement(new PunctuationNode(node.file, OPEN_BRACKET));
      node.addElement(new SpaceNode(node.file, 0 /* ignored */));
      node.args = new ArgListNode(node.file, () => node.type.matchedText);
      node.addElement(node.args);
      node.addElement(new SpaceNode(node.file, 0 /* ignored */));
      node.addElement(new PunctuationNode(node.file, CLOSE_BRACKET));
    }
    addCommonElementsForTypeTuple(node) {
      node.types = new CSV(
        node.file,
        () => new TypeNode(
          node.file,
          /* @__PURE__ */ new Set([
            6 /* type_concrete */,
            7 /* type_abstract */,
            9 /* type_notInheritable */
          ])
        ),
        2
      );
      node.addElement(new PunctuationNode(node.file, OPEN_BRACKET));
      node.addElement(node.types);
      node.addElement(new PunctuationNode(node.file, CLOSE_BRACKET));
    }
    getFields(frame) {
      let fields = [];
      if (frame instanceof FunctionFrame) {
        fields = this.functionFrameFields(frame);
      } else if (frame instanceof AssertStatement) {
        fields = this.assertStatementFields(frame);
      }
      return fields;
    }
    default_functionFrameFields(frame) {
      return [frame.name, frame.params, frame.returnType];
    }
    default_assertStatementFields(frame) {
      return [frame.actual, frame.expected];
    }
    implements(frame) {
      const superImpl = implementsAbstractMethodOnClassOrInterface(
        frame.name,
        frame.getParent()
      );
      let implementsClause = "";
      if (superImpl[0] !== "" && !superImpl[1]) {
        implementsClause = ` <el-kw>${this.IMPLEMENTS}</el-kw> <el-type>${superImpl[0]}</el-type>.${frame.name.renderAsHtml()}`;
      }
      return implementsClause;
    }
    overrides(frame) {
      const superImpl = implementsAbstractMethodOnClassOrInterface(
        frame.name,
        frame.getParent()
      );
      let overridesKw = "";
      if (superImpl[0] !== "" && superImpl[1]) {
        overridesKw = `<el-kw>${this.OVERRIDES}</el-kw> `;
      }
      return overridesKw;
    }
    spaced(text) {
      return ` ${text} `;
    }
  };

  // src/ide/frames/language-helpers.ts
  function languageHelper_enumValuesList(field, format, startingNumber, ending) {
    let result = "";
    if (field.readParseStatus() === 3 /* valid */) {
      if (format === 1 /* multiline */) {
        const rawValues = field.getRootNode().matchedText.split(",");
        for (let i = 0; i < rawValues.length; i++) {
          const value = rawValues[i].trim();
          const line = `<br>  <el-id>${value}</el-id> = <el-lit>${i + startingNumber}</el-lit>`;
          result += line;
        }
        result += ending;
      } else {
        result = field.default_renderAsHtml();
      }
    }
    return result;
  }
  var languageHelper_mathFunctions = [
    "pow",
    "abs",
    "acos",
    "asin",
    "atan",
    "cos",
    "exp",
    "logE",
    "log10",
    "log2",
    "sin",
    "sqrt",
    "tan",
    "radians",
    "degrees"
  ];

  // src/ide/frames/fields/exception-type-field.ts
  var ExceptionTypeField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this.useHtmlTags = true;
      this.setFieldToKnownValidText("CustomError");
      this.setPlaceholder("<i>exception type</i>");
    }
    helpId() {
      return "TypeField";
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_type`;
    }
    initialiseRoot() {
      this.rootNode = new TypeNameUse(this.getFile(), /* @__PURE__ */ new Set([]));
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readUntil(/\s/);
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
  };

  // src/ide/frames/statements/catch-statement.ts
  var CatchStatement = class extends SingleLineFrame {
    isStatement = true;
    isCatch = true;
    variable;
    exceptionType;
    constructor(parent) {
      super(parent);
      this.variable = new IdentifierField(this);
      this.variable.setPlaceholder("<i>variableName</i>");
      this.variable.setFieldToKnownValidText("e");
      this.exceptionType = new ExceptionTypeField(this);
      this.exceptionType.setPlaceholder(`type e.g. ElanRuntimeError or CustomError`);
      this.ghostable = false;
    }
    setClasses() {
      super.setClasses();
      this.pushClass(true, "outdent");
    }
    isDeletable() {
      return false;
    }
    deleteIfPermissible() {
    }
    initialKeywords() {
      return catchKeyword;
    }
    getFields() {
      return [this.variable];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_catch`;
    }
    frameSpecificAnnotation() {
      return "catch";
    }
    indent() {
      return this.getParent().indent();
    }
    parentIndent() {
      return this.getParent().indent();
    }
    renderAsElanSource() {
      return `${this.indent()}${catchKeyword} ${this.variable.renderAsElanSource()} ${asKeyword} ${this.exceptionType.renderAsElanSource()}`;
    }
    parseFrom(source) {
      source.removeIndent();
      source.remove(catchKeyword);
      source.remove(" ");
      this.variable.parseFrom(source);
      source.remove(" ");
      source.remove(asKeyword);
      source.remove(" ");
      this.exceptionType.parseFrom(source);
      source.removeNewLine();
    }
    isGhosted() {
      return false;
    }
  };

  // src/ide/frames/statements/else.ts
  var Else = class extends SingleLineFrame {
    isStatement = true;
    setClasses() {
      super.setClasses();
      this.pushClass(true, "outdent");
    }
    initialKeywords() {
      return elseKeyword;
    }
    getFields() {
      return [];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_else`;
    }
    frameSpecificAnnotation() {
      return "";
    }
    indent() {
      return this.getParent().indent();
    }
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}${elseKeyword}`;
    }
    parseFrom(source) {
      source.remove("else");
    }
  };

  // src/ide/frames/statements/elseIf.ts
  var ElseIf = class extends SingleLineFrame {
    isStatement = true;
    hasIf = true;
    condition;
    constructor(parent) {
      super(parent);
      this.condition = new ExpressionField(this);
      this.condition.setPlaceholder("<i>condition</i>");
    }
    setClasses() {
      super.setClasses();
      this.pushClass(true, "outdent");
    }
    initialKeywords() {
      return elseKeyword;
    }
    getFields() {
      return [this.condition];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_else`;
    }
    frameSpecificAnnotation() {
      return "else if";
    }
    indent() {
      return this.getParent().indent();
    }
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}${elifKeyword} ${this.condition.renderAsElanSource()} ${thenKeyword}`;
    }
    parseFrom(source) {
      source.remove(`${elifKeyword} `);
      const condition = source.readUntil(/\sthen/);
      this.condition.parseFrom(new CodeSourceFromString(condition));
      source.remove(` ${thenKeyword}`);
    }
  };

  // src/ide/frames/statements/for.ts
  var For = class extends FrameWithStatements {
    isStatement = true;
    variable;
    iter;
    constructor(parent) {
      super(parent);
      this.variable = new IdentifierField(this);
      this.variable.setPlaceholder("<i>item</i>");
      this.iter = new ExpressionField(this);
      this.iter.setPlaceholder("<i>source</i>");
    }
    initialKeywords() {
      return forKeyword;
    }
    getFields() {
      return [this.variable, this.iter];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_for`;
    }
    frameSpecificAnnotation() {
      return "for";
    }
    outerHtmlTag = "el-statement";
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}${forKeyword} ${this.variable.renderAsElanSource()} in ${this.iter.renderAsElanSource()}\r
${this.renderChildrenAsElanSource()}\r
${this.indent()}${endKeyword} ${forKeyword}`;
    }
    parseTop(source) {
      source.remove(`${forKeyword} `);
      this.variable.parseFrom(source);
      source.remove(` ${inKeyword} `);
      this.iter.parseFrom(source);
    }
    parseBottom(source) {
      return this.parseStandardEnding(source, `${endKeyword} ${forKeyword}`);
    }
  };

  // src/ide/frames/statements/if-statement.ts
  var IfStatement = class extends FrameWithStatements {
    isStatement = true;
    condition;
    constructor(parent) {
      super(parent);
      this.condition = new ExpressionField(this);
      this.condition.setPlaceholder("<i>condition</i>");
    }
    initialKeywords() {
      return ifKeyword;
    }
    getFields() {
      return [this.condition];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_if`;
    }
    frameSpecificAnnotation() {
      return "if";
    }
    outerHtmlTag = "el-statement";
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}${ifKeyword} ${this.condition.renderAsElanSource()} ${thenKeyword}\r
${this.renderChildrenAsElanSource()}\r
${this.indent()}${endKeyword} ${ifKeyword}`;
    }
    parseTop(source) {
      source.remove("if ");
      const condition = source.readUntil(/\sthen/);
      this.condition.parseFrom(new CodeSourceFromString(condition));
      source.remove(" then");
      source.removeNewLine();
    }
    parseBottom(source) {
      source.removeIndent();
      return this.parseStandardEnding(source, "end if");
    }
    insertSelectorAfterLastField() {
      this.getFirstChild().select(true, false);
    }
  };

  // src/ide/frames/parse-nodes/exception-msg-node.ts
  var ExceptionMsgNode = class extends AbstractAlternatives {
    tokenTypes = /* @__PURE__ */ new Set([
      4 /* id_constant */,
      0 /* id_let */,
      1 /* id_variable */
    ]);
    constructor(file) {
      super(file);
      this.alternatives.push(new LitString(file));
      this.alternatives.push(new IdentifierUse(file, this.tokenTypes));
    }
  };

  // src/ide/frames/fields/exception-message-field.ts
  var ExceptionMessageField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this.setPlaceholder("<i>message</i>");
    }
    helpId() {
      return "ExceptionMessageField";
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_msg`;
    }
    initialiseRoot() {
      this.rootNode = new ExceptionMsgNode(this.getFile());
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readToEndOfLine();
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
  };

  // src/ide/frames/statements/throw.ts
  var Throw = class extends SingleLineFrame {
    isStatement = true;
    type;
    text;
    constructor(parent) {
      super(parent);
      this.text = new ExceptionMessageField(this);
      this.type = new ExceptionTypeField(this);
    }
    initialKeywords() {
      return throwKeyword;
    }
    parseFrom(source) {
      source.removeIndent();
      source.remove(`${throwKeyword} `);
      this.type.parseFrom(source);
      source.remove(" ");
      this.text.parseFrom(source);
      source.removeNewLine();
    }
    getFields() {
      return [this.type, this.text];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_throw`;
    }
    frameSpecificAnnotation() {
      return "throw";
    }
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}${throwKeyword} ${this.type.renderAsElanSource()} ${this.text.renderAsElanSource()}`;
    }
  };

  // src/ide/frames/statements/try.ts
  var TryStatement = class extends FrameWithStatements {
    catch;
    constructor(parent) {
      super(parent);
      this.catch = new CatchStatement(this);
      this.getChildren().push(this.catch);
      this.getChildren().push(new StatementSelector(this));
    }
    initialKeywords() {
      return tryKeyword;
    }
    minimumNumberOfChildrenExceeded() {
      return this.getChildren().length > 2;
    }
    getFields() {
      return [];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_try`;
    }
    frameSpecificAnnotation() {
      return "try";
    }
    outerHtmlTag = "el-statement";
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}try\r
${this.renderChildrenAsElanSource()}\r
${this.indent()}${endKeyword} ${tryKeyword}`;
    }
    parseTop(source) {
      source.remove(tryKeyword);
    }
    parseBottom(source) {
      source.removeIndent();
      if (source.isMatchRegEx(/^catch\s/)) {
        this.catch.parseFrom(source);
        const redundantSelector = this.getFirstSelectorAsDirectChild();
        this.removeChild(redundantSelector);
      }
      return this.parseStandardEnding(source, `${endKeyword} ${tryKeyword}`);
    }
  };

  // src/ide/frames/statements/while.ts
  var While = class extends FrameWithStatements {
    isStatement = false;
    condition;
    constructor(parent) {
      super(parent);
      this.condition = new ExpressionField(this);
      this.condition.setPlaceholder("<i>condition</i>");
    }
    initialKeywords() {
      return whileKeyword;
    }
    getFields() {
      return [this.condition];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_while`;
    }
    frameSpecificAnnotation() {
      return "";
    }
    outerHtmlTag = "el-statement";
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}while ${this.condition.renderAsElanSource()}\r
${this.renderChildrenAsElanSource()}\r
${this.indent()}end while`;
    }
    parseTop(source) {
      source.remove(`${whileKeyword} `);
      this.condition.parseFrom(source);
    }
    parseBottom(source) {
      return this.parseStandardEnding(source, `${endKeyword} ${whileKeyword}`);
    }
  };

  // src/ide/frames/language-elan.ts
  var LanguageElan = class _LanguageElan extends LanguageAbstract {
    constructor() {
      super();
    }
    static Instance = new _LanguageElan();
    commentRegex() {
      return /# [^\r\n]*/;
    }
    languageHtmlClass = "elan";
    languageFullName = "Reference Language";
    defaultFileExtension = "elan";
    defaultMimeType = "text/plain";
    annotation(_frame) {
      return "";
    }
    renderSingleLineAsHtml(frame) {
      let html = `Html not specified for this frame`;
      if (frame instanceof AssertStatement) {
        html = `<el-kw>assert </el-kw>${frame.actual.renderAsHtml()}<el-kw> is </el-kw>${frame.expected.renderAsHtml()}`;
      } else if (frame instanceof CallStatement) {
        html = `<el-kw>${this.CALL} </el-kw>${frame.proc.renderAsHtml()}(${frame.args.renderAsHtml()})`;
      } else if (frame instanceof CatchStatement) {
        html = `<el-kw>${this.CATCH} ${frame.variable.renderAsHtml()} <el-kw>${this.AS}</el-kw> ${frame.exceptionType.renderAsHtml()}`;
      } else if (frame instanceof CommentStatement) {
        html = `<el-kw>${this.COMMENT_MARKER} </el-kw>${frame.text.renderAsHtml()}`;
      } else if (frame instanceof ConstantGlobal) {
        html = `<el-kw>${this.CONSTANT} </el-kw>${frame.name.renderAsHtml()}</el-top><el-kw> set to </el-kw>${frame.value.renderAsHtml()}`;
      } else if (frame instanceof ElseIf) {
        html = `<el-kw>${this.ELIF} </el-kw>${frame.condition.renderAsHtml()}<el-kw> ${this.THEN}`;
      } else if (frame instanceof Else) {
        html = `<el-kw>${this.ELSE}`;
      } else if (frame instanceof Enum) {
        html = `<el-kw>${this.ENUM} </el-kw>${frame.name.renderAsHtml()} ${frame.values.renderAsHtml()}`;
      } else if (frame instanceof GlobalComment) {
        html = `<el-kw>${this.COMMENT_MARKER} </el-kw>${frame.text.renderAsHtml()}`;
      } else if (frame instanceof LetStatement) {
        html = `<el-kw>${this.LET} </el-kw>${frame.name.renderAsHtml()}<el-kw> ${this.BE} </el-kw>${frame.expr.renderAsHtml()}`;
      } else if (frame instanceof Property) {
        html = `${this.modifierAsHtml(frame)}<el-kw>${this.PROPERTY} </el-kw>${frame.name.renderAsHtml()}<el-kw> ${this.AS} </el-kw>${frame.type.renderAsHtml()}`;
      } else if (frame instanceof ReturnStatement) {
        html = `<el-kw>${this.RETURN} </el-kw>${frame.expr.renderAsHtml()}`;
      } else if (frame instanceof ReAssignVariable) {
        html = `<el-kw>${this.REASSIGN} </el-kw>${frame.assignable.renderAsHtml()}<el-kw> ${this.TO} </el-kw>${frame.expr.renderAsHtml()}`;
      } else if (frame instanceof Throw) {
        html = `<el-kw>${this.THROW}</el-kw> ${frame.type.renderAsHtml()} ${frame.text.renderAsHtml()}`;
      } else if (frame instanceof VariableStatement) {
        html = `<el-kw>${this.VARIABLE} </el-kw>${frame.name.renderAsHtml()}<el-kw> ${this.SET} ${this.TO} </el-kw>${frame.expr.renderAsHtml()}`;
      } else if (frame instanceof AbstractFunction) {
        html = `<el-kw>${this.ABSTRACT} ${this.FUNCTION} </el-kw><el-method>${frame.name.renderAsHtml()}</el-method>(${frame.params.renderAsHtml()})<el-kw> ${this.RETURNS} </el-kw>${frame.returnType.renderAsHtml()}`;
      } else if (frame instanceof AbstractProcedure) {
        html = `<el-kw>${this.ABSTRACT} ${this.PROCEDURE} </el-kw><el-method>${frame.name.renderAsHtml()}</el-method>(${frame.params.renderAsHtml()})`;
      } else if (frame instanceof AbstractProperty) {
        html = `<el-kw>${this.ABSTRACT} ${this.PROPERTY} </el-kw>${frame.name.renderAsHtml()}<el-kw> ${this.AS} </el-kw>${frame.type.renderAsHtml()}`;
      }
      return html;
    }
    renderSingleLineAsExport(_frame) {
      return "";
    }
    renderTopAsHtml(frame) {
      let html = `Html not specified for this frame`;
      if (frame instanceof AbstractClass) {
        html = `<el-kw>${this.ABSTRACT} ${this.CLASS} </el-kw>${frame.name.renderAsHtml()} ${frame.inheritance.renderAsHtml()}`;
      } else if (frame instanceof ConcreteClass) {
        html = `<el-kw>${this.CLASS} </el-kw>${frame.name.renderAsHtml()} ${frame.inheritance.renderAsHtml()}`;
      } else if (frame instanceof Constructor) {
        html = `<el-kw>${this.CONSTRUCTOR}</el-kw>(${frame.params.renderAsHtml()})`;
      } else if (frame instanceof For) {
        html = `<el-kw>${this.FOR} </el-kw>${frame.variable.renderAsHtml()}<el-kw> ${this.IN} </el-kw>${frame.iter.renderAsHtml()}`;
      } else if (frame instanceof GlobalFunction) {
        html = `<el-kw>${this.FUNCTION} </el-kw>${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()})<el-kw> ${this.RETURNS} </el-kw>${frame.returnType.renderAsHtml()}`;
      } else if (frame instanceof GlobalProcedure) {
        html = `<el-kw>${this.PROCEDURE} </el-kw>${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()})`;
      } else if (frame instanceof FunctionMethod) {
        html = `${this.modifierAsHtml(frame)}<el-kw>${this.FUNCTION} </el-kw>${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()})<el-kw> ${this.RETURNS} </el-kw>${frame.returnType.renderAsHtml()}`;
      } else if (frame instanceof ProcedureMethod) {
        html = `${this.modifierAsHtml(frame)}<el-kw>${this.PROCEDURE} </el-kw>${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()})`;
      } else if (frame instanceof IfStatement) {
        html = `<el-kw>${this.IF} </el-kw>${frame.condition.renderAsHtml()}<el-kw> ${this.THEN}</el-kw>`;
      } else if (frame instanceof InterfaceFrame) {
        html = `<el-kw>${this.INTERFACE} </el-kw>${frame.name.renderAsHtml()} ${frame.inheritance.renderAsHtml()}`;
      } else if (frame instanceof MainFrame) {
        html = `<el-kw>${this.MAIN}</el-kw>`;
      } else if (frame instanceof TestFrame) {
        html = `<el-kw>${this.TEST} </el-kw>${frame.testName.renderAsHtml()}`;
      } else if (frame instanceof TryStatement) {
        html = `<el-kw>${this.TRY} </el-kw>`;
      } else if (frame instanceof While) {
        html = `<el-kw>${this.WHILE} </el-kw>${frame.condition.renderAsHtml()}`;
      }
      return html;
    }
    inheritsFromTextAsHtml(field) {
      const frame = field.getHolder();
      return frame.doesInherit() ? ` <el-kw>${this.INHERITS}</el-kw> ${field.default_renderasHtml()}` : ``;
    }
    renderTopAsExport(_frame) {
      return "";
    }
    renderBottomAsHtml(frame) {
      return `<el-kw>${this.END} ${frame.initialKeywords()}</el-kw>`;
    }
    renderFileImportsAsHtml() {
      return "";
    }
    renderFileTrailerAsHtml(_f) {
      return "";
    }
    translateExpression(expr) {
      return expr;
    }
    ABSTRACT = "abstract";
    AS = "as";
    ASSERT = "assert";
    BE = "be";
    CALL = "call";
    CATCH = "catch";
    CLASS = "class";
    CONSTANT = "constant";
    CONSTRUCTOR = "constructor";
    COPY = "copy";
    DIV = "div";
    EACH = "each";
    ELIF = "elif";
    ELSE = "else";
    EMPTY = "empty";
    END = "end";
    ENUM = "enum";
    EXCEPTION = "exception";
    FOR = "for";
    FROM = "from";
    FUNCTION = "function";
    GLOBAL = "global";
    IF = "if";
    IMPORT = "import";
    IN = "in";
    INHERITS = "inherits";
    INTERFACE = "interface";
    lambdaKeyword = "lambda";
    LET = "let";
    LIBRARY = "library";
    MAIN = "main";
    NEW = "new";
    OF = "of";
    OUT = "out";
    PRINT = "print";
    PRIVATE = "private";
    PROCEDURE = "procedure";
    PROPERTY = "property";
    REASSIGN = "reassign";
    REF = "ref";
    RETURN = "return";
    RETURNS = "returns";
    SET = "set";
    STEP = "step";
    TEST = "test";
    THEN = "then";
    THIS = "this";
    THROW = "throw";
    TO = "to";
    TRY = "try";
    VARIABLE = "variable";
    WHILE = "while";
    WITH = "with";
    POWER = "^";
    EQUAL = "is";
    NOT_EQUAL = "isnt";
    MOD = "mod";
    AND = "and";
    OR = "or";
    NOT = "not";
    COMMENT_MARKER = "#";
    LIST_START = "[";
    LIST_END = "]";
    INTERPOLATED_STRING_PREFIX = "$";
    NEW_INSTANCE_PREFIX = this.NEW;
    INT_NAME = "Int";
    FLOAT_NAME = "Float";
    BOOL_NAME = "Boolean";
    STRING_NAME = "String";
    LIST_NAME = "List";
    TRUE = "true";
    FALSE = "false";
    BINARY_PREFIX = "0b";
    HEX_PREFIX = "0x";
    START_OF_GENERIC = `<${this.OF} `;
    END_OF_GENERIC = `>`;
    THIS_INSTANCE = this.THIS;
    OVERRIDES = "";
    IMPLEMENTS = "";
    EXPRESSION_KEYWORDS = [
      this.NEW,
      this.IF,
      this.lambdaKeyword,
      this.REF,
      this.THIS,
      this.NOT
    ];
    addNodesForNewInstance(node) {
      node.addElement(new KeywordNode(node.file, this.NEW_INSTANCE_PREFIX));
      node.addElement(new SpaceNode(node.file, 2 /* required */));
      this.addCommonElementsForNewInstance(node);
    }
    addNodesForParamDef(node) {
      node.name = new IdentifierDef(node.file);
      node.addElement(node.name);
      node.addElement(new SpaceNode(node.file, 2 /* required */));
      node.addElement(new KeywordNode(node.file, asKeyword));
      node.addElement(new SpaceNode(node.file, 2 /* required */));
      node.type = new TypeNode(
        node.file,
        /* @__PURE__ */ new Set([
          6 /* type_concrete */,
          7 /* type_abstract */,
          9 /* type_notInheritable */
        ])
      );
      node.addElement(node.type);
    }
    addNodesForTypeGeneric(node) {
      node.qualifiedName = new TypeNameUse(node.file, node.tokenTypes);
      const typeConstr = () => new TypeNode(node.file, node.concreteAndAbstract);
      node.genericTypes = new CSV(node.file, typeConstr, 1);
      node.addElement(node.qualifiedName);
      node.addElement(new PunctuationNode(node.file, LT));
      node.addElement(new KeywordNode(node.file, ofKeyword));
      node.addElement(new SpaceNode(node.file, 2 /* required */));
      node.addElement(node.genericTypes);
      node.addElement(new PunctuationNode(node.file, GT));
    }
    paramDefAsHtml(node) {
      return `${node.name?.renderAsHtml()} <el-kw>as</el-kw> ${node.type?.renderAsHtml()}`;
    }
    typeGenericAsHtml(node) {
      return `${node.qualifiedName?.renderAsHtml()}&lt;<el-kw>of</el-kw> ${node.genericTypes?.renderAsHtml()}&gt;`;
    }
    newInstanceAsHtml(node) {
      return `<el-kw>${this.NEW_INSTANCE_PREFIX}</el-kw> ${node.type?.renderAsHtml()}(${node.args?.renderAsHtml()})`;
    }
    addNodesForTypeTuple(node) {
      this.addCommonElementsForTypeTuple(node);
    }
    typeTupleAsHtml(node) {
      return this.default_typeTupleAsHtml(node);
    }
    addNodesForLambda(node) {
      node.addElement(new KeywordNode(node.file, lambdaKeyword));
      node.addElement(new SpaceNode(node.file, 2 /* required */));
      node.params = new CSV(node.file, () => new ParamDefNode(node.file), 0);
      node.addElement(node.params);
      node.addElement(new SpaceNode(node.file, 1 /* added */));
      node.addElement(new PunctuationNode(node.file, ARROW));
      node.addElement(new SpaceNode(node.file, 1 /* added */));
      node.expr = new ExprNode(node.file);
      node.addElement(node.expr);
    }
    lambdaAsHtml(node) {
      return `<el-kw>${lambdaKeyword}</el-kw> ${node.params.renderAsHtml()} ${ARROW} ${node.expr.renderAsHtml()}`;
    }
    enumValuesListAsHtml(field) {
      return languageHelper_enumValuesList(field, 0 /* inline */, 0, "");
    }
    standardiseInterpolatedString(_node, text) {
      return text;
    }
    litStringInterpolatedAsHtml(node) {
      return this.default_litStringInterpolatedAsHtml(node);
    }
    functionFrameFields(frame) {
      return this.default_functionFrameFields(frame);
    }
    assertStatementFields(frame) {
      return this.default_assertStatementFields(frame);
    }
    modifierAsHtml(member) {
      return member.isPrivate ? `<el-kw>${this.PRIVATE} </el-kw>` : "";
    }
    // Elan keywords followed by JavaScript keywords
    reservedWords = /* @__PURE__ */ new Set([
      `abstract`,
      `and`,
      `as`,
      `assert`,
      `be`,
      `call`,
      `catch`,
      `class`,
      `constant`,
      `constructor`,
      `each`,
      `elif`,
      `else`,
      `end`,
      `enum`,
      `exception`,
      `for`,
      `from`,
      `function`,
      `global`,
      `if`,
      `in`,
      `inherits`,
      `interface`,
      `is`,
      `isnt`,
      `lambda`,
      `library`,
      `main`,
      `mod`,
      `new`,
      `not`,
      `of`,
      `or`,
      `private`,
      `procedure`,
      `property`,
      `return`,
      `returns`,
      `set`,
      `step`,
      `test`,
      `then`,
      `this`,
      `throw`,
      `to`,
      `try`,
      `variable`,
      `while`,
      `action`,
      `arguments`,
      `array`,
      `async`,
      `await`,
      `boolean`,
      `break`,
      `by`,
      `byte`,
      `case`,
      `catch`,
      `char`,
      `const`,
      `continue`,
      `debugger`,
      `default`,
      `delete`,
      `do`,
      `double`,
      `eval`,
      `export`,
      `extends`,
      `final`,
      `finally`,
      `float`,
      `goto`,
      `implements`,
      `instanceof`,
      `int`,
      `into`,
      `list`,
      `long`,
      `match`,
      `mock`,
      `namespace`,
      `native`,
      `null`,
      `on`,
      `otherwise`,
      `record`,
      `package`,
      `partial`,
      `pattern`,
      `protected`,
      `public`,
      `scenario`,
      `short`,
      `static`,
      `stdlib`,
      `string`,
      `super`,
      `switch`,
      `system`,
      `synchronized`,
      `throws`,
      `transient`,
      `typeof`,
      `void`,
      `volatile`,
      `var`,
      `when`,
      `yield`
    ]);
  };

  // src/ide/frames/language-c-family.ts
  var LanguageCfamily = class extends LanguageAbstract {
    constructor() {
      super();
    }
    common_commentRegex() {
      return /\/\/ [^\r\n]*/;
    }
    common_Annotation(frame) {
      let annotation = "";
      if (frame instanceof ProcedureFrame || frame instanceof FunctionFrame || frame instanceof CallStatement || frame instanceof LetStatement || frame instanceof ReAssignVariable || frame instanceof Property || frame instanceof AbstractProperty || frame instanceof AbstractProcedure || frame instanceof AbstractFunction) {
        annotation = frame.frameSpecificAnnotation();
      }
      return annotation;
    }
    common_renderSingleLineAsHtml(frame) {
      let html = `Html not specified for this frame`;
      if (frame instanceof CallStatement) {
        html = `${frame.proc.renderAsHtml()}(${frame.args.renderAsHtml()});`;
      } else if (frame instanceof CatchStatement) {
        html = `} <el-kw>${this.CATCH}</el-kw> (${frame.exceptionType.renderAsHtml()} ${frame.variable.renderAsHtml()}) {`;
      } else if (frame instanceof CommentStatement) {
        html = `<el-kw>${this.COMMENT_MARKER} </el-kw>${frame.text.renderAsHtml()}`;
      } else if (frame instanceof ElseIf) {
        html = `} <el-kw>${this.ELSE} ${this.IF} </el-kw>(${frame.condition.renderAsHtml()}) {`;
      } else if (frame instanceof Else) {
        html = `} <el-kw>${this.ELSE} {`;
      } else if (frame instanceof Enum) {
        html = `<el-kw>${this.ENUM} </el-kw>${frame.name.renderAsHtml()} {${frame.values.renderAsHtml()}}`;
      } else if (frame instanceof GlobalComment) {
        html = `<el-kw>${this.COMMENT_MARKER} </el-kw>${frame.text.renderAsHtml()}`;
      } else if (frame instanceof LetStatement) {
        html = `<el-kw>${this.VAR}</el-kw> ${frame.name.renderAsHtml()} = ${frame.expr.renderAsHtml()};`;
      } else if (frame instanceof ReturnStatement) {
        html = `<el-kw>${this.RETURN} </el-kw>${frame.expr.renderAsHtml()};`;
      } else if (frame instanceof ReAssignVariable) {
        html = `${frame.assignable.renderAsHtml()}<el-kw> = </el-kw>${frame.expr.renderAsHtml()};`;
      } else if (frame instanceof Throw) {
        html = `<el-kw>${this.THROW} ${this.NEW_INSTANCE_PREFIX}</el-kw> ${frame.type.renderAsHtml()}(${frame.text.renderAsHtml()});`;
      } else if (frame instanceof VariableStatement) {
        html = `<el-kw>${this.VAR} </el-kw>${frame.name.renderAsHtml()} = ${frame.expr.renderAsHtml()};`;
      } else if (frame instanceof AbstractFunction) {
        html = `<el-kw>${this.ABSTRACT} </el-kw>${frame.returnType.renderAsHtml()} <el-method>${frame.name.renderAsHtml()}</el-method>(${frame.params.renderAsHtml()});`;
      } else if (frame instanceof AbstractProcedure) {
        html = `<el-kw>${this.ABSTRACT} ${this.VOID} </el-kw><el-method>${frame.name.renderAsHtml()}</el-method>(${frame.params.renderAsHtml()});`;
      }
      return html;
    }
    modifierAsHtml(member) {
      let modifier = "";
      if (member.isPrivate && member.isOnAbstractClass()) {
        modifier = this.PROTECTED;
      } else if (member.isPrivate) {
        modifier = this.PRIVATE;
      } else {
        modifier = this.PUBLIC;
      }
      return modifier === "" ? "" : `<el-kw>${modifier} </el-kw>`;
    }
    common_renderTopAsHtml(frame) {
      let html = `Html not specified for this frame`;
      if (frame instanceof AbstractClass) {
        html = `<el-kw>${this.ABSTRACT} ${this.CLASS} </el-kw>${frame.name.renderAsHtml()}${frame.inheritance.renderAsHtml()} {`;
      } else if (frame instanceof ConcreteClass) {
        html = `<el-kw>${this.CLASS} </el-kw>${frame.name.renderAsHtml()}${frame.inheritance.renderAsHtml()} {`;
      } else if (frame instanceof Constructor) {
        html = `<el-kw>${this.PUBLIC} ${selfTypeAsHtml(frame)}(${frame.params.renderAsHtml()}) {`;
      } else if (frame instanceof FunctionMethod) {
        html = `${this.modifierAsHtml(frame)}${this.overrides(frame)}<el-kw></el-kw>${frame.returnType.renderAsHtml()} ${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()}) {`;
      } else if (frame instanceof ProcedureMethod) {
        html = `${this.modifierAsHtml(frame)}${this.overrides(frame)}<el-kw>${this.VOID} </el-kw>${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()}) {`;
      } else if (frame instanceof For) {
        html = `<el-kw>${this.FOREACH} </el-kw></el-kw>(${frame.variable.renderAsHtml()}<el-kw> ${this.IN} </el-kw>${frame.iter.renderAsHtml()}</el-kw>) {`;
      } else if (frame instanceof GlobalFunction) {
        html = `<el-kw>${this.STATIC} </el-kw>${frame.returnType.renderAsHtml()} ${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()}) {`;
      } else if (frame instanceof GlobalProcedure) {
        html = `<el-kw>${this.STATIC} ${this.VOID} </el-kw>${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()}) {`;
      } else if (frame instanceof IfStatement) {
        html = `<el-kw>${this.IF} </el-kw>(${frame.condition.renderAsHtml()}) {`;
      } else if (frame instanceof InterfaceFrame) {
        html = `<el-kw>${this.INTERFACE} </el-kw>${frame.name.renderAsHtml()}${frame.inheritance.renderAsHtml()} {`;
      } else if (frame instanceof MainFrame) {
        html = `<el-kw>${this.STATIC} ${this.VOID}</el-kw> <el-method>main</el-method>() {`;
      } else if (frame instanceof TryStatement) {
        html = `<el-kw>${this.TRY}</el-kw> {`;
      } else if (frame instanceof While) {
        html = `<el-kw>${this.WHILE} (</el-kw>${frame.condition.renderAsHtml()}) {`;
      }
      return html;
    }
    common_renderBottomAsHtml(frame) {
      let html = "<el-punc>}</el-punc><el-comment> // ";
      if (frame instanceof AbstractClass || frame instanceof ConcreteClass) {
        html += this.CLASS;
      } else if (frame instanceof Constructor) {
        html += "constructor";
      } else if (frame instanceof FunctionMethod) {
        html += "function method";
      } else if (frame instanceof ProcedureMethod) {
        html += "procedure method";
      } else if (frame instanceof For) {
        html += this.FOREACH;
      } else if (frame instanceof GlobalFunction) {
        html += "function";
      } else if (frame instanceof GlobalProcedure) {
        html += "procedure";
      } else if (frame instanceof IfStatement) {
        html += "if";
      } else if (frame instanceof InterfaceFrame) {
        html += this.INTERFACE;
      } else if (frame instanceof MainFrame) {
        html += "main";
      } else if (frame instanceof TryStatement) {
        html += this.TRY;
      } else if (frame instanceof While) {
        html += this.WHILE;
      } else if (frame instanceof TestFrame) {
        html += "test";
      }
      return html + "</el-comment>";
    }
    common_functionFrameFields(frame) {
      return [frame.returnType, frame.name, frame.params];
    }
    common_assertStatementFields(frame) {
      return [frame.expected, frame.actual];
    }
    ABSTRACT = "abstract";
    CATCH = "catch";
    CLASS = "class";
    CONST = "const";
    FOREACH = "foreach";
    ELSE = "else";
    ENUM = "enum";
    FOR = "for";
    IF = "if";
    IN = "in";
    INHERITS = "inherits";
    INTERFACE = "interface";
    PRIVATE = "private";
    PROTECTED = "protected";
    PUBLIC = "public";
    RETURN = "return";
    STATIC = "static";
    THIS = "this";
    THROW = "throw";
    TRY = "try";
    VAR = "var";
    VOID = "void";
    WHILE = "while";
    EQUAL = "==";
    NOT_EQUAL = "!=";
    MOD = "%";
    AND = "&&";
    OR = "||";
    NOT = "!";
    COMMENT_MARKER = "//";
    LIST_START = "[";
    LIST_END = "]";
    INT_NAME = "int";
    FLOAT_NAME = "double";
    BOOL_NAME = "bool";
    STRING_NAME = "string";
    LIST_NAME = "List";
    NEW_INSTANCE_PREFIX = "new";
    TRUE = "true";
    FALSE = "false";
    BINARY_PREFIX = "0b";
    HEX_PREFIX = "0x";
    START_OF_GENERIC = "<";
    END_OF_GENERIC = ">";
    THIS_INSTANCE = this.THIS;
    EXPRESSION_KEYWORDS = [this.NEW_INSTANCE_PREFIX, this.THIS];
    c_langs_addNodesForParamDef(node) {
      node.type = new TypeNode(
        node.file,
        /* @__PURE__ */ new Set([
          6 /* type_concrete */,
          7 /* type_abstract */,
          9 /* type_notInheritable */
        ])
      );
      node.addElement(node.type);
      node.addElement(new SpaceNode(node.file, 2 /* required */));
      node.name = new IdentifierDef(node.file);
      node.addElement(node.name);
    }
    c_langs_paramDefAsHtml(node) {
      return `${node.type?.renderAsHtml()} ${node.name?.renderAsHtml()}`;
    }
    c_langs_addNodesForTypeGeneric(node) {
      node.qualifiedName = new TypeNameUse(node.file, node.tokenTypes);
      const typeConstr = () => new TypeNode(node.file, node.concreteAndAbstract);
      node.genericTypes = new CSV(node.file, typeConstr, 1);
      node.addElement(node.qualifiedName);
      node.addElement(new PunctuationNode(node.file, LT));
      node.addElement(node.genericTypes);
      node.addElement(new PunctuationNode(node.file, GT));
    }
    c_langs_typeGenericAsHtml(node) {
      return `${node.qualifiedName?.renderAsHtml()}&lt;${node.genericTypes?.renderAsHtml()}&gt;`;
    }
    c_langs_newInstanceAsHtml(node) {
      return `<el-kw>${this.NEW_INSTANCE_PREFIX} ${node.type?.renderAsHtml()}(${node.args?.renderAsHtml()})</el-kw>`;
    }
    c_langs_enumValuesListAsHtml(field) {
      return languageHelper_enumValuesList(field, 0 /* inline */, 0, "");
    }
  };

  // src/ide/frames/language-java.ts
  var LanguageJava = class _LanguageJava extends LanguageCfamily {
    static Instance = new _LanguageJava();
    languageHtmlClass = "java";
    languageFullName = "Java";
    defaultFileExtension = "java";
    defaultMimeType = "text/plain";
    commentRegex() {
      return this.common_commentRegex();
    }
    annotation(frame) {
      let annotation = this.common_Annotation(frame);
      if (frame instanceof ConstantGlobal) {
        annotation = frame.frameSpecificAnnotation();
      }
      return annotation;
    }
    renderSingleLineAsHtml(frame) {
      let html = "";
      if (frame instanceof AssertStatement) {
        html = `<el-method>assertEquals</el-method>(${frame.expected.renderAsHtml()}, ${frame.actual.renderAsHtml()})`;
      } else if (frame instanceof ConstantGlobal) {
        html = `<el-kw>${this.FINAL} </el-kw><el-type>${frame.value.getElanType()} </el-type>${frame.name.renderAsHtml()}</el-top> = ${frame.value.renderAsHtml()}`;
      } else if (frame instanceof Property) {
        html = `${this.modifierAsHtml(frame)}${frame.type.renderAsHtml()} ${frame.name.renderAsHtml()};`;
      } else if (frame instanceof AbstractProperty) {
        html = `<el-kw>${this.ABSTRACT}</el-kw> ${frame.type.renderAsHtml()} ${frame.name.renderAsHtml()};`;
      } else {
        html = this.common_renderSingleLineAsHtml(frame);
      }
      return html;
    }
    renderTopAsHtml(frame) {
      let html = "";
      if (frame instanceof TestFrame) {
        html = `@<el-type>Test</el-type> <el-kw>${this.STATIC} ${this.VOID} </el-kw>${frame.testName.renderAsHtml()}() {`;
      } else {
        html = this.common_renderTopAsHtml(frame);
      }
      return html;
    }
    inheritsFromTextAsHtml(field) {
      const frame = field.getHolder();
      const node = field.getRootNode();
      let result = "";
      if (frame.doesInherit() && field.readParseStatus() === 3 /* valid */) {
        const inheritsKw = `<el-kw>${this.EXTENDS}</el-kw> `;
        const implementsKw = `<el-kw>${this.IMPLEMENTS}</el-kw> `;
        const abstractClasses = node.getAbstractClassNames();
        if (abstractClasses.length > 0) {
          const typesAsHtml = abstractClasses.map((t) => `<el-type>${t}</el-type>`);
          const csvTypes = typesAsHtml.join(", ");
          result += ` ${inheritsKw}${csvTypes}`;
        }
        const interfaces = node.getInterfaceNames();
        if (interfaces.length > 0) {
          const typesAsHtml = interfaces.map((t) => `<el-type>${t}</el-type>`);
          const csvTypes = typesAsHtml.join(", ");
          const keyWord = frame.isInterface ? inheritsKw : implementsKw;
          result += ` ${keyWord}${csvTypes}`;
        }
      } else {
        result = field.default_renderasHtml();
      }
      return result;
    }
    renderBottomAsHtml(frame) {
      return this.common_renderBottomAsHtml(frame);
    }
    renderFileImportsAsHtml() {
      return "";
    }
    renderFileTrailerAsHtml(_f) {
      return "";
    }
    translateExpression(expr) {
      return expr;
    }
    FINAL = "final";
    OVERRIDES = "";
    EXTENDS = "extends";
    IMPLEMENTS = "implements";
    STRING_NAME = "String";
    INTERPOLATED_STRING_PREFIX = "";
    // No prefix because of custom processing
    addNodesForParamDef(node) {
      this.c_langs_addNodesForParamDef(node);
    }
    paramDefAsHtml(node) {
      return this.c_langs_paramDefAsHtml(node);
    }
    addNodesForTypeGeneric(node) {
      this.c_langs_addNodesForTypeGeneric(node);
    }
    typeGenericAsHtml(node) {
      return this.c_langs_typeGenericAsHtml(node);
    }
    addNodesForLambda(node) {
      node.addElement(new PunctuationNode(node.file, OPEN_BRACKET));
      node.params = new CSV(node.file, () => new ParamDefNode(node.file), 0);
      node.addElement(node.params);
      node.addElement(new PunctuationNode(node.file, CLOSE_BRACKET));
      node.addElement(new SpaceNode(node.file, 1 /* added */));
      node.addElement(new PunctuationNode(node.file, this.ARROW));
      node.addElement(new SpaceNode(node.file, 1 /* added */));
      node.expr = new ExprNode(node.file);
      node.addElement(node.expr);
    }
    lambdaAsHtml(node) {
      return `(${node.params.renderAsHtml()}) ${this.ARROW} ${node.expr.renderAsHtml()}`;
    }
    litStringInterpolatedAsHtml(node) {
      let definingString = "";
      let csv = "";
      node.segments.getElements().forEach((element) => {
        const seg = element.bestMatch;
        if (seg instanceof LitStringInterpolatedInsert) {
          definingString += "%";
          csv += `${seg.expr.renderAsHtml()}, `;
        } else if (seg instanceof LitStringText) {
          definingString += seg.renderAsHtml();
        }
      });
      csv = csv.endsWith(", ") ? csv.substring(0, csv.length - 2) : csv;
      return `<el-type>String</el-type>.<el-method>format</el-method>("<el-lit>${definingString}</el-lit>", ${csv})`;
    }
    enumValuesListAsHtml(field) {
      return this.c_langs_enumValuesListAsHtml(field);
    }
    standardiseInterpolatedString(node, text) {
      const f = node.file;
      const java = new Sequence(f, []);
      const numFields = text.split("%").length - 1;
      java.addElement(new RegExMatchNode(f, /String\.format\(/));
      const str = new LitStringOrdinary(f);
      java.addElement(str);
      java.addElement(new CommaNode(f));
      const csvExpr = new CSV(f, () => new ExprNode(f), numFields);
      java.addElement(csvExpr);
      java.addElement(new PunctuationNode(f, CLOSE_BRACKET));
      java.parseText(text);
      let standardised = "";
      if (java.status === 3 /* valid */) {
        let elan = `$${str.matchedText}`;
        const contents = this.justTheExpressions(csvExpr);
        for (let i = 0; i < numFields; i++) {
          elan = elan.replace("%", "{" + contents[i].renderAsElanSource() + "}");
        }
        standardised = elan;
      }
      return standardised;
    }
    justTheExpressions(csv) {
      const contents = [];
      const first = csv.getElements()[0];
      const secondOnwards = csv.getElements()[1].getElements();
      contents.push(first);
      for (let i = 0; i < secondOnwards.length; i++) {
        const commaPlus = secondOnwards[i];
        const contentNode = commaPlus.getElements()[1];
        contents.push(contentNode);
      }
      return contents;
    }
    addNodesForNewInstance(node) {
      node.addElement(new KeywordNode(node.file, this.NEW_INSTANCE_PREFIX));
      node.addElement(new SpaceNode(node.file, 2 /* required */));
      this.addCommonElementsForNewInstance(node);
    }
    newInstanceAsHtml(node) {
      return this.c_langs_newInstanceAsHtml(node);
    }
    addNodesForTypeTuple(node) {
      this.addCommonElementsForTypeTuple(node);
    }
    typeTupleAsHtml(node) {
      return this.default_typeTupleAsHtml(node);
    }
    functionFrameFields(frame) {
      return this.common_functionFrameFields(frame);
    }
    assertStatementFields(frame) {
      return this.common_assertStatementFields(frame);
    }
    ARROW = "->";
    reservedWords = /* @__PURE__ */ new Set([
      `abstract`,
      `continue`,
      `for`,
      `new`,
      `switch`,
      `assert`,
      `default`,
      `goto`,
      `package`,
      `synchronized`,
      `boolean`,
      `do`,
      `if`,
      `private`,
      `this`,
      `break`,
      `double`,
      `implements`,
      `protected`,
      `throw`,
      `byte`,
      `else`,
      `import`,
      `public`,
      `throws`,
      `case`,
      `enum`,
      `instanceof`,
      `return`,
      `transient`,
      `catch`,
      `extends`,
      `int`,
      `short`,
      `try`,
      `char`,
      `final`,
      `interface`,
      `static`,
      `void`,
      `class`,
      `finally`,
      `long`,
      `strictfp`,
      `volatile`,
      `const`,
      `float`,
      `native`,
      `super`,
      `while`
    ]);
  };

  // src/ide/frames/language-export-helpers.ts
  var LanguageExportHelpers = class {
    constructor(languageExport) {
      this.languageExport = languageExport;
    }
    // a master flag which turns the expression processing on and off
    // with a single line of code
    enableExportTranslation = false;
    // a record of which polyfills we need
    polyfillsUsed = {};
    // A variable to accumulate the imports required by any functions calls we see
    // Each string in the set is an import statement, complete with newline
    // Using a Set to deduplicate
    importSet = /* @__PURE__ */ new Set();
    // return the import statements built up during the processing of the file
    renderFileImportsAsHtml() {
      let result = Array.from(this.importSet.values()).sort().join("");
      for (const p in this.polyfillsUsed) {
        result += this.languageExport.polyfillTable[p];
      }
      this.importSet = /* @__PURE__ */ new Set();
      this.polyfillsUsed = {};
      return result + (result ? "\n" : "");
    }
    translateExpression(expr) {
      if (!this.enableExportTranslation) {
        return expr;
      }
      const regexp = new RegExp(
        `(<el-method>)(${languageHelper_mathFunctions.join("|")})(</el-method>)`,
        "g"
      );
      let result = expr.replace(regexp, this.lookupmath);
      result = this.translatePlainMethods(result);
      result = this.translateExtension(result);
      result = this.translateStandaloneWithParams(result);
      result = this.languageExport.translateOddities(result);
      this.registerPolyfills(expr);
      return result;
    }
    // 'this' is undefined inside a traditional function definition
    // when used as a callback from string "replace()"
    // so we use an arrow function so it has access to 'this'
    lookupmath = (_match, p1, p2, p3, _offset, _string) => {
      const result = this.languageExport.mathExceptions[p2] ?? `${this.languageExport.mathPrefix}.${p2}`;
      this.importSet.add(this.languageExport.getImportNeeded(result));
      return `${p1}${result}${p3}`;
    };
    // non-math functions which are dot methods and stay dot methods
    // or standalone and stay standalone
    // these just need the name changing, and no import statement is needed
    // could use regexp lookahead and lookbehind to handle the tags
    // but I am doing it the way I know for now
    translatePlainMethods(expr) {
      return expr.replace(
        new RegExp(
          `(${this.METHOPTAG})(${Object.keys(this.languageExport.plainMethodTable).join("|")})(${this.METHCLTAG})`,
          "g"
        ),
        (_match, p1, p2, p3) => `${p1}${this.languageExport.plainMethodTable[p2]}${p3}`
      );
    }
    METHOPTAG = "<el-method>";
    // open tag
    METHCLTAG = "</el-method>";
    // close tag
    // we need to distinguish opening and closing quotes
    // we do this by substituting different characters for them
    // while we work out the positions of the strings to be moved around
    // these two characters look a bit like brackets and are unlikely to be entered by users
    // they go into a local variable in translateExtension() and shouldn't leak out!
    OPENQUOTE = "\u2770";
    // HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT (U+2770)
    CLOSEQUOTE = "\u2771";
    // HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT (U+2771)
    // Dot methods which translate to standalone functions
    translateExtension(expr) {
      let result = expr;
      const regexp = new RegExp(
        `(${this.METHOPTAG})(${Object.keys(this.languageExport.extensionTable).join("|")})(${this.METHCLTAG})`,
        "g"
      );
      let match3;
      while (match3 = regexp.exec(expr)) {
        const pos2 = match3.index + result.length - expr.length;
        const funcName = match3[2];
        const working = result.replaceAll(this.OPENQUOTE, "z").replaceAll(this.CLOSEQUOTE, "z").replaceAll('"<', this.OPENQUOTE + "<").replaceAll('>"', ">" + this.CLOSEQUOTE).replaceAll("</", "<@");
        let cont = true;
        let pos1 = pos2;
        while (cont) {
          const c = working[pos1];
          if (" ([{,*/".includes(c)) {
            cont = false;
          } else {
            if ((")]" + this.CLOSEQUOTE).includes(c)) {
              pos1 = this.findmatch(working, pos1, -1);
            }
            pos1--;
          }
          if (pos1 < 0) {
            cont = false;
          }
        }
        const argsPos = pos2 + `${this.METHOPTAG}${funcName}${this.METHCLTAG}(`.length;
        const replacement = this.languageExport.extensionTable[funcName];
        result = result.substring(0, pos1 + 1) + // up to the delimiter
        `${this.METHOPTAG}${replacement}${this.METHCLTAG}(` + // new function name
        result.substring(pos1 + 1, pos2 - 1) + // argument
        (result[argsPos] === ")" ? "" : ", ") + // if there is already an argument add comma
        result.substring(argsPos);
        this.importSet.add(this.languageExport.getImportNeeded(replacement));
      }
      return result;
    }
    // lookup table for the finding of matching brackets and quotes
    // it accepts some things which are not legal in Elan
    // dir = 1 = forwards (left to right), dir = -1 = backwards (right to left)
    matchtable = {
      "(": { close: ")", nest: this.OPENQUOTE + "([", dir: 1 },
      ")": { close: "(", nest: this.CLOSEQUOTE + ")]", dir: -1 },
      [this.OPENQUOTE]: { close: this.CLOSEQUOTE, nest: this.OPENQUOTE, dir: 1 },
      [this.CLOSEQUOTE]: { close: this.OPENQUOTE, nest: this.CLOSEQUOTE, dir: -1 },
      "[": { close: "]", nest: this.OPENQUOTE + "([", dir: 1 },
      "]": { close: "[", nest: this.CLOSEQUOTE + ")]", dir: -1 }
    };
    // dir = 1 for forwards, -1 for backwards
    findmatch(text, start, dir) {
      const lup = this.matchtable[text[start]];
      if (!lup) {
        throw new Error("Bad opening character /" + text[start] + "/");
      }
      if (lup.dir !== 0 && lup.dir !== dir) {
        throw new Error("Opening character /" + text[start] + "/ doesn't match dir " + dir);
      }
      let index = start + dir;
      while (index >= 0 && index < text.length) {
        const c = text[index];
        if (c === lup.close) {
          return index;
        }
        if (lup.nest.includes(c)) {
          index = this.findmatch(text, index, dir);
        }
        index += dir;
      }
      throw new Error("No match");
    }
    translateStandaloneWithParams(expr) {
      const strRev = (s) => [...s].reverse().join("");
      let result = expr;
      const regexp = new RegExp(
        strRev(
          `(${this.METHOPTAG})(${Object.keys(this.languageExport.standaloneTable).join("|")})(${this.METHCLTAG})`.replace(
            /[()]/g,
            (c) => c === "(" ? ")" : "("
          )
        ),
        "g"
      );
      let match3;
      while (match3 = regexp.exec(strRev(expr))) {
        const funcName = strRev(match3[2]);
        const funcLength = match3[0].length;
        const pos2 = expr.length - match3.index - funcLength;
        const working = result.replaceAll(this.OPENQUOTE, "z").replaceAll(this.CLOSEQUOTE, "z").replaceAll('"<', this.OPENQUOTE + "<").replaceAll('>"', ">" + this.CLOSEQUOTE).replaceAll("</", "<@");
        const pos1 = pos2 + funcLength + 1;
        const params = this.getparams(working, pos1);
        const replacement = this.languageExport.standaloneTable[funcName];
        const dotAdjust = pos2 > 0 && result[pos2 - 1] === "." ? 1 : 0;
        result = result.substring(0, pos2 - dotAdjust) + // up to the function name
        replacement.replace(
          /\$(\d)/g,
          (_match, p1) => result.substring(params.prms[+p1][0], params.prms[+p1][1])
        ) + // params in expression
        result.substring(params.end + 1);
        this.importSet.add(this.languageExport.getImportNeeded(replacement));
      }
      return result;
    }
    // start points to first character of params, after the open bracket
    // returns array of [start, end] positions for the params and the offset of the end
    // can't return the actual strings as we are working on the "working" version
    // with adjusted quotes
    getparams(text, start) {
      const params = [];
      const lup = { close: ")", nest: this.OPENQUOTE + "([", sep: ",)" };
      let index = start;
      let pstart = index;
      while (index < text.length) {
        const c = text[index];
        if (lup.sep.includes(c)) {
          params.push([pstart, index]);
          pstart = index + 2;
        }
        if (c === lup.close) {
          return { prms: params, end: index };
        }
        if (lup.nest.includes(c)) {
          index = this.findmatch(text, index, 1);
        }
        index++;
      }
      throw new Error("Bad param syntax");
    }
    registerPolyfills(expr) {
      let match3;
      const regexp = new RegExp(
        `(${this.METHOPTAG})(${Object.keys(this.languageExport.polyfillTable).join("|")})(${this.METHCLTAG})`,
        "g"
      );
      while (match3 = regexp.exec(expr)) {
        const funcName = match3[2];
        this.polyfillsUsed[funcName] = true;
      }
    }
  };

  // src/ide/frames/language-export-python.ts
  var LanguageExportPython = class {
    // the math functions that don't just add "math."
    mathExceptions = {
      pow: "pow",
      abs: "abs",
      logE: "math.log"
    };
    mathPrefix = "math";
    // non-math functions which are
    // - dot methods and stay dot methods, or
    // - standalone and stay standalone
    // these just need the name changing, and no import statement is needed
    plainMethodTable = {
      unicode: "chr",
      rangeInSteps: "range",
      indexOf: "find",
      // "index" raises an exception on not found
      upperCase: "upper",
      lowerCase: "lower",
      trim: "strip",
      parseAsInt: "int"
    };
    // omitting 'split: "split"' as the name is the same
    // Dot methods which translate to standalone functions
    extensionTable = {
      toString: "str",
      asUnicode: "ord",
      length: "len",
      floor: "math.floor",
      ceiling: "math.ceil",
      isNaN: "math.isnan",
      isInfinite: "math.isinf",
      round: "round",
      // these are adjusted in a later pass
      withAppend: "withAppendPy",
      equals: "equalsPy"
    };
    // Table for functions with parameters that need moving
    // Add brackets round the whole expression
    // if there may be a higher-priority operator adjacent
    standaloneTable = {
      // there is no confusion with "if" statements
      // as this code is only run for expressions
      if: "($1 if $0 else $2)",
      divAsInt: "math.floor(($0)/($1))",
      divAsFloat: "(($0)/($1))",
      createList: "[$1 for n in range($0)]",
      bitAnd: "(($0) & ($1))",
      bitOr: "($0 | $1)",
      bitXor: "($0 ^ $1)",
      bitNot: "(~$0)",
      bitShiftL: "($0 &lt;&lt; $1)",
      bitShiftR: "(($0 & (1&lt;&lt;32)-1) &gt;&gt; $1)",
      // copy TBD
      subString: "[$0:$1]",
      printNoLine: "print($0, end='')",
      withAppendPy: "($0 + [($1)])",
      // list + [value]
      equalsPy: "($0 == ($1))"
    };
    // some replacement functions are so simple
    // that they may as well be put in line as polyfills
    polyfillTable = {
      clock: `import time
def clock():
  return int(time.time()*1000)
`
    };
    // one piece of code which is language-specific and belongs in this file
    translateOddities(expr) {
      return expr.replace(/\.<el-id>item_(\d)<\/el-id>/g, "[$1]");
    }
    // oh and another piece of code
    // return the required import line for a given function (after translation)
    getImportNeeded(funcname) {
      return funcname.startsWith("math.") ? "import math\n" : "";
    }
  };

  // src/ide/frames/language-python.ts
  var LanguagePython = class _LanguagePython extends LanguageAbstract {
    static Instance = new _LanguagePython();
    commentRegex() {
      return /# [^\r\n]*/;
    }
    languageHtmlClass = "python";
    languageFullName = "Python";
    defaultFileExtension = "py";
    defaultMimeType = "text/x-python";
    annotation(frame) {
      let annotation = "";
      if (frame instanceof VariableStatement || frame instanceof ConstantGlobal || frame instanceof LetStatement || frame instanceof FunctionFrame || frame instanceof ElseIf || frame instanceof ProcedureFrame || frame instanceof CallStatement || frame instanceof ReAssignVariable || frame instanceof CatchStatement || frame instanceof ConcreteClass || frame instanceof AbstractClass || frame instanceof InterfaceFrame || frame instanceof Property || frame instanceof FunctionMethod || frame instanceof ProcedureMethod || frame instanceof AbstractFunction || frame instanceof AbstractProcedure || frame instanceof AbstractProperty) {
        annotation = frame.frameSpecificAnnotation();
      }
      return annotation;
    }
    renderSingleLineAsHtml(frame) {
      let html = `Html not specified for ${typeof frame}`;
      if (frame instanceof AbstractFunction) {
        html = `<el-comment>@abstractmethod</el-comment><br><el-kw>${this.DEF} </el-kw>${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()}) -> ${frame.returnType.renderAsHtml()}:<br>&nbsp;&nbsp;<el-kw>pass</el-kw>`;
      } else if (frame instanceof AbstractProcedure) {
        html = `<el-comment>@abstractmethod</el-comment><br><el-kw>${this.DEF} </el-kw>${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()}) -> <el-kw>${this.NONE}</el-kw><br>&nbsp;&nbsp;<el-kw>pass</el-kw>`;
      } else if (frame instanceof AbstractProperty) {
        html = html = `<el-comment>@property</el-comment><br><el-comment>@abstractmethod</el-comment><br><el-kw>${this.DEF} </el-kw>${frame.name.renderAsHtml()}(<el-kw>${this.SELF}</el-kw>: ${selfTypeAsHtml(frame)}) -> ${frame.type.renderAsHtml()}:<br>&nbsp;&nbsp;<el-kw>pass</el-kw>`;
      } else if (frame instanceof AssertStatement) {
        html = `<el-kw>self</el-kw>.<el-method>assertEqual</el-method>(${frame.actual.renderAsHtml()}, ${frame.expected.renderAsHtml()})`;
      } else if (frame instanceof CallStatement) {
        html = `${frame.proc.renderAsHtml()}(${frame.args.renderAsHtml()})`;
      } else if (frame instanceof CatchStatement) {
        html = `<el-kw>${this.EXCEPT}</el-kw> ${frame.exceptionType.renderAsHtml()} <el-kw>${this.AS}</el-kw> ${frame.variable.renderAsHtml()}:`;
      } else if (frame instanceof CommentStatement) {
        html = `<el-kw>${this.COMMENT_MARKER} </el-kw>${frame.text.renderAsHtml()}`;
      } else if (frame instanceof ConstantGlobal) {
        html = `${frame.name.renderAsHtml()}</el-top> = ${frame.value.renderAsHtml()}`;
      } else if (frame instanceof ElseIf) {
        html = `<el-kw>${this.ELIF} </el-kw>${frame.condition.renderAsHtml()}:`;
      } else if (frame instanceof Else) {
        html = `<el-kw>${this.ELSE}</el-kw>:`;
      } else if (frame instanceof Enum) {
        html = `<el-kw>${this.CLASS}</el-kw> ${frame.name.renderAsHtml()}(<el-type>Enum</el-type>):${frame.values.renderAsHtml()}`;
      } else if (frame instanceof GlobalComment) {
        html = `<el-kw>${this.COMMENT_MARKER} </el-kw>${frame.text.renderAsHtml()}`;
      } else if (frame instanceof LetStatement) {
        html = `${frame.name.renderAsHtml()} = ${frame.expr.renderAsHtml()}`;
      } else if (frame instanceof Property) {
        html = `${frame.name.renderAsHtml()}: ${frame.type.renderAsHtml()}`;
      } else if (frame instanceof ReturnStatement) {
        html = `<el-kw>${this.RETURN} </el-kw>${frame.expr.renderAsHtml()}`;
      } else if (frame instanceof ReAssignVariable) {
        html = `${frame.assignable.renderAsHtml()} = ${frame.expr.renderAsHtml()}`;
      } else if (frame instanceof Throw) {
        html = `<el-kw>${this.RAISE}</el-kw> ${frame.type.renderAsHtml()}(${frame.text.renderAsHtml()})`;
      } else if (frame instanceof VariableStatement) {
        html = `${frame.name.renderAsHtml()} = ${frame.expr.renderAsHtml()}`;
      }
      return html;
    }
    renderTopAsHtml(frame) {
      let html = `Html not specified for ${typeof frame}`;
      if (frame instanceof AbstractClass) {
        html = `<el-kw>${this.CLASS} </el-kw><el-type>${frame.name.renderAsHtml()}</el-type>${frame.inheritance.renderAsHtml()}`;
      } else if (frame instanceof ConcreteClass) {
        html = `<el-kw>${this.CLASS} </el-kw><el-type>${frame.name.renderAsHtml()}</el-type>${frame.inheritance.renderAsHtml()}`;
      } else if (frame instanceof Constructor) {
        html = `<el-kw>${this.DEF}</el-kw> <el-method>__init__</el-method>(${this.paramsListAsHtml(frame, frame.params)}) -> <el-kw>None</el-kw>:`;
      } else if (frame instanceof For) {
        html = `<el-kw>${this.FOR} </el-kw>${frame.variable.renderAsHtml()}<el-kw> ${this.IN} </el-kw>${frame.iter.renderAsHtml()}:`;
      } else if (frame instanceof GlobalFunction) {
        html = `<el-kw>${this.DEF} </el-kw>${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()}) -> ${frame.returnType.renderAsHtml()}:`;
      } else if (frame instanceof GlobalProcedure) {
        html = `<el-kw>${this.DEF} </el-kw>${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()}) -> <el-kw>${this.NONE}</el-kw>:`;
      } else if (frame instanceof IfStatement) {
        html = `<el-kw>${this.IF} </el-kw>${frame.condition.renderAsHtml()}:`;
      } else if (frame instanceof InterfaceFrame) {
        html = `<el-kw>${this.CLASS} </el-kw><el-type>${frame.name.renderAsHtml()}</el-type>${frame.inheritance.renderAsHtml()}`;
      } else if (frame instanceof MainFrame) {
        html = `<el-kw>${this.DEF} </el-kw><el-method>main</el-method>() -> <el-kw>${this.NONE}</el-kw>:`;
      } else if (frame instanceof Property) {
        html = `${frame.name.renderAsHtml()}: ${frame.type.renderAsHtml()}`;
      } else if (frame instanceof FunctionMethod) {
        html = `<el-kw>${this.DEF} </el-kw>${frame.name.renderAsHtml()}(${this.paramsListAsHtml(frame, frame.params)}) -> ${frame.returnType.renderAsHtml()}:`;
      } else if (frame instanceof ProcedureMethod) {
        html = `<el-kw>${this.DEF} </el-kw>${frame.name.renderAsHtml()}(${this.paramsListAsHtml(frame, frame.params)}) -> <el-kw>${this.NONE}</el-kw>:`;
      } else if (frame instanceof TestFrame) {
        html = `<el-kw>${this.DEF}</el-kw> <el-method>${frame.testName.renderAsHtml()}</el-method>(<el-kw>${this.SELF}</el-kw>) -> <el-kw>${this.NONE}:`;
      } else if (frame instanceof TryStatement) {
        html = `<el-kw>${this.TRY}</el-kw>:`;
      } else if (frame instanceof While) {
        html = `<el-kw>${this.WHILE} </el-kw>${frame.condition.renderAsHtml()}:`;
      }
      return html;
    }
    paramsListAsHtml(frame, field) {
      const self2 = `<el-kw>${this.SELF}</el-kw>: ${selfTypeAsHtml(frame)}`;
      return field.text === "" ? self2 : `${self2}, ${field.renderAsHtml()}`;
    }
    enumValuesListAsHtml(field) {
      return languageHelper_enumValuesList(field, 1 /* multiline */, 1, "");
    }
    inheritsFromTextAsHtml(field) {
      let result = "";
      const frame = field.getHolder();
      if (frame.doesInherit()) {
        result = `(${field.default_renderasHtml()})`;
      } else if (frame.isAbstract) {
        result = `(<el-type>ABC</el-type>)`;
      }
      return result;
    }
    renderBottomAsHtml(_frame) {
      return "";
    }
    renderFileImportsAsHtml() {
      return this.languageExportHelpers.renderFileImportsAsHtml();
    }
    renderFileTrailerAsHtml(f) {
      return f.containsMain() ? "\n\n<el-method>main</el-method>()" : "";
    }
    // make instances of the two classes needed for export of expressions
    languageExportHelpers = new LanguageExportHelpers(new LanguageExportPython());
    // translate the library functions in an expression
    // Note that this translation may be turned off by a master flag in LanguageExportHelpers
    translateExpression(expr) {
      return this.languageExportHelpers.translateExpression(expr);
    }
    AS = "as";
    DEF = "def";
    CLASS = "class";
    ELIF = "elif";
    ELSE = "else";
    EXCEPT = "except";
    FOR = "for";
    IF = "if";
    IN = "in";
    LAMBDA = "lambda";
    NONE = "None";
    RAISE = "raise";
    RETURN = "return";
    SELF = "self";
    TRY = "try";
    WHILE = "while";
    OPEN_SQUARE_BRACKET = "[";
    CLOSE_SQUARE_BRACKET = "]";
    MOD = "%";
    EQUAL = "==";
    NOT_EQUAL = "!=";
    AND = "and";
    OR = "or";
    NOT = "not";
    COMMENT_MARKER = "#";
    LIST_START = "[";
    LIST_END = "]";
    INTERPOLATED_STRING_PREFIX = "f";
    NEW_INSTANCE_PREFIX = "";
    // i.e. there is no Python equivalent to 'new' keyword
    INT_NAME = "int";
    FLOAT_NAME = "float";
    BOOL_NAME = "bool";
    STRING_NAME = "str";
    LIST_NAME = "list";
    TRUE = "True";
    FALSE = "False";
    BINARY_PREFIX = "0b";
    HEX_PREFIX = "0x";
    START_OF_GENERIC = "[";
    END_OF_GENERIC = "]";
    THIS_INSTANCE = this.SELF;
    OVERRIDES = "";
    IMPLEMENTS = "";
    EXPRESSION_KEYWORDS = [this.LAMBDA, this.SELF, this.NOT];
    addNodesForParamDef(node) {
      node.name = new IdentifierDef(node.file);
      node.addElement(node.name);
      node.addElement(new PunctuationNode(node.file, COLON));
      node.addElement(new SpaceNode(node.file, 1 /* added */));
      node.type = new TypeNode(
        node.file,
        /* @__PURE__ */ new Set([
          6 /* type_concrete */,
          7 /* type_abstract */,
          9 /* type_notInheritable */
        ])
      );
      node.addElement(node.type);
    }
    paramDefAsHtml(node) {
      return `${node.name?.renderAsHtml()}: ${node.type?.renderAsHtml()}`;
    }
    newInstanceAsHtml(node) {
      return node.status === 3 /* valid */ ? `${node.type?.renderAsHtml()}(${node.args?.renderAsHtml()})` : node.matchedText;
    }
    addNodesForTypeGeneric(node) {
      node.qualifiedName = new TypeNameUse(node.file, node.tokenTypes);
      const typeConstr = () => new TypeNode(node.file, node.concreteAndAbstract);
      node.genericTypes = new CSV(node.file, typeConstr, 1);
      node.addElement(node.qualifiedName);
      node.addElement(new PunctuationNode(node.file, this.OPEN_SQUARE_BRACKET));
      node.addElement(node.genericTypes);
      node.addElement(new PunctuationNode(node.file, this.CLOSE_SQUARE_BRACKET));
    }
    typeGenericAsHtml(node) {
      return `${node.qualifiedName?.renderAsHtml()}[${node.genericTypes?.renderAsHtml()}]`;
    }
    addNodesForNewInstance(node) {
      this.addCommonElementsForNewInstance(node);
    }
    addNodesForLambda(node) {
      node.addElement(new KeywordNode(node.file, this.LAMBDA));
      node.addElement(new SpaceNode(node.file, 2 /* required */));
      node.params = new CSV(node.file, () => new ParamDefNode(node.file), 0);
      node.addElement(node.params);
      node.addElement(new PunctuationNode(node.file, COLON));
      node.addElement(new SpaceNode(node.file, 1 /* added */));
      node.expr = new ExprNode(node.file);
      node.addElement(node.expr);
    }
    lambdaAsHtml(node) {
      return `<el-kw>${this.LAMBDA}</el-kw> ${node.params.renderAsHtml()}${COLON} ${node.expr.renderAsHtml()}`;
    }
    listNodeAsHtml(node) {
      return `[${node.csv?.renderAsHtml()}]`;
    }
    litStringInterpolatedAsHtml(node) {
      return this.default_litStringInterpolatedAsHtml(node);
    }
    standardiseInterpolatedString(node, text) {
      return this.default_standardiseInterpolatedString(node, text);
    }
    addNodesForTypeTuple(node) {
      node.types = new CSV(
        node.file,
        () => new TypeNode(
          node.file,
          /* @__PURE__ */ new Set([
            6 /* type_concrete */,
            7 /* type_abstract */,
            9 /* type_notInheritable */
          ])
        ),
        2
      );
      node.addElement(new PunctuationNode(node.file, "tuple"));
      node.addElement(new PunctuationNode(node.file, OPEN_SQ_BRACKET));
      node.addElement(node.types);
      node.addElement(new PunctuationNode(node.file, CLOSE_SQ_BRACKET));
    }
    typeTupleAsHtml(node) {
      return `<el-kw>tuple</el-kw>[${node.types?.renderAsHtml()}]`;
    }
    functionFrameFields(frame) {
      return this.default_functionFrameFields(frame);
    }
    assertStatementFields(frame) {
      return this.default_assertStatementFields(frame);
    }
    reservedWords = /* @__PURE__ */ new Set([
      `false`,
      `await`,
      `else`,
      `import`,
      `pass`,
      `none`,
      `break`,
      `except`,
      `in`,
      `raise`,
      `true`,
      `class`,
      `finally`,
      `is`,
      `return`,
      `and`,
      `continue`,
      `for`,
      `lambda`,
      `try`,
      `as`,
      `def`,
      `from`,
      `nonlocal`,
      `while`,
      `assert`,
      `del`,
      `global`,
      `not`,
      `with`,
      `async`,
      `elif`,
      `if`,
      `or`,
      `yield`,
      `str`,
      `int`,
      `float`,
      `complex`,
      `list`,
      `tuple`,
      `range`,
      `dict`,
      `set`,
      `frozenset`,
      `bool`,
      `bytes`,
      `bytearray`,
      `memoryview`,
      `nonetype`
    ]);
  };

  // src/ide/frames/language-vb.ts
  var LanguageVB = class _LanguageVB extends LanguageAbstract {
    constructor() {
      super();
    }
    static Instance = new _LanguageVB();
    commentRegex() {
      return /' [^\r\n]*/;
    }
    languageHtmlClass = "vb";
    languageFullName = "VB.NET";
    defaultFileExtension = "vb";
    defaultMimeType = "text/plain";
    annotation(frame) {
      let annotation = "";
      if (frame instanceof VariableStatement || frame instanceof ProcedureFrame || frame instanceof LetStatement || frame instanceof CallStatement || frame instanceof ReAssignVariable) {
        annotation = frame.frameSpecificAnnotation();
      }
      return annotation;
    }
    renderSingleLineAsHtml(frame) {
      let html = `Html not specified for this frame`;
      if (frame instanceof AssertStatement) {
        html = `<el-type>Assert</el-type>.<el-method>AreEqual</el-method>(${frame.expected.renderAsHtml()}, ${frame.actual.renderAsHtml()})`;
      } else if (frame instanceof CallStatement) {
        html = `${frame.proc.renderAsHtml()}(${frame.args.renderAsHtml()})`;
      } else if (frame instanceof CatchStatement) {
        html = `<el-kw>${this.CATCH}</el-kw> ${frame.variable.renderAsHtml()} <el-kw>${this.AS}</el-kw> ${frame.exceptionType.renderAsHtml()}`;
      } else if (frame instanceof CommentStatement) {
        html = `<el-kw>${this.SINGLE_QUOTE} </el-kw>${frame.text.renderAsHtml()}`;
      } else if (frame instanceof ConstantGlobal) {
        html = `<el-kw>${this.CONST} </el-kw>${frame.name.renderAsHtml()}<el-kw></el-top> = ${frame.value.renderAsHtml()}`;
      } else if (frame instanceof ElseIf) {
        html = `<el-kw>${this.ELSEIF} </el-kw>${frame.condition.renderAsHtml()}<el-kw> ${this.THEN}`;
      } else if (frame instanceof Else) {
        html = `<el-kw>${this.ELSE}`;
      } else if (frame instanceof Enum) {
        html = `<el-kw>${this.ENUM}</el-kw> ${frame.name.renderAsHtml()} ${frame.values.renderAsHtml()}`;
      } else if (frame instanceof GlobalComment) {
        html = `<el-kw>${this.SINGLE_QUOTE} <el-kw>${frame.text.renderAsHtml()}`;
      } else if (frame instanceof LetStatement) {
        html = `<el-kw>${this.DIM} <el-kw>${frame.name.renderAsHtml()} = ${frame.expr.renderAsHtml()}`;
      } else if (frame instanceof Property) {
        html = `${this.modifierAsHtml(frame)}<el-kw>${this.PROPERTY} </el-kw>${frame.name.renderAsHtml()}<el-kw> ${this.AS} </el-kw>${frame.type.renderAsHtml()}`;
      } else if (frame instanceof ReturnStatement) {
        html = `<el-kw>${this.RETURN} </el-kw>${frame.expr.renderAsHtml()}`;
      } else if (frame instanceof ReAssignVariable) {
        html = `${frame.assignable.renderAsHtml()} = ${frame.expr.renderAsHtml()}`;
      } else if (frame instanceof Throw) {
        html = `<el-kw>${this.THROW} ${this.NEW_INSTANCE_PREFIX} </el-kw>${frame.type.renderAsHtml()}(${frame.text.renderAsHtml()})`;
      } else if (frame instanceof VariableStatement) {
        html = `<el-kw>${this.DIM} </el-kw>${frame.name.renderAsHtml()}<el-kw> = </el-kw>${frame.expr.renderAsHtml()}`;
      } else if (frame instanceof AbstractFunction) {
        html = `<el-kw>${this.MUST_OVERRIDE} ${this.FUNCTION} </el-kw><el-method>${frame.name.renderAsHtml()}</el-method>(${frame.params.renderAsHtml()})<el-kw> ${this.AS} </el-kw>${frame.returnType.renderAsHtml()}`;
      } else if (frame instanceof AbstractProcedure) {
        html = `<el-kw>${this.MUST_OVERRIDE} ${this.SUB} </el-kw><el-method>${frame.name.renderAsHtml()}</el-method>(${frame.params.renderAsHtml()})`;
      } else if (frame instanceof AbstractProperty) {
        html = `<el-kw>${this.MUST_OVERRIDE} ${this.PROPERTY} </el-kw>${frame.name.renderAsHtml()}<el-kw> ${this.AS} </el-kw>${frame.type.renderAsHtml()}`;
      }
      return html;
    }
    renderTopAsHtml(frame) {
      let html = `Html not specified for this frame`;
      if (frame instanceof AbstractClass) {
        html = `<el-kw>${this.MUST_INHERIT} ${this.CLASS} </el-kw>${frame.name.renderAsHtml()}${frame.inheritance.renderAsHtml()}`;
      } else if (frame instanceof ConcreteClass) {
        html = `<el-kw>${this.CLASS} </el-kw>${frame.name.renderAsHtml()}${frame.inheritance.renderAsHtml()}`;
      } else if (frame instanceof Constructor) {
        html = `<el-kw>${this.SUB} ${this.NEW_INSTANCE_PREFIX}</el-kw>(${frame.params.renderAsHtml()})`;
      } else if (frame instanceof For) {
        html = `<el-kw>${this.FOR} ${this.EACH} </el-kw>${frame.variable.renderAsHtml()}<el-kw> ${this.IN} </el-kw>${frame.iter.renderAsHtml()}`;
      } else if (frame instanceof GlobalFunction) {
        html = `<el-kw>${this.FUNCTION} </el-kw>${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()})<el-kw> ${this.AS} </el-kw>${frame.returnType.renderAsHtml()}`;
      } else if (frame instanceof GlobalProcedure) {
        html = `<el-kw>${this.SUB} </el-kw>${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()})`;
      } else if (frame instanceof IfStatement) {
        html = `<el-kw>${this.IF} </el-kw>${frame.condition.renderAsHtml()}<el-kw> ${this.THEN}</el-kw>`;
      } else if (frame instanceof InterfaceFrame) {
        html = `<el-kw>${this.INTERFACE} </el-kw>${frame.name.renderAsHtml()}${frame.inheritance.renderAsHtml()}`;
      } else if (frame instanceof MainFrame) {
        html = `<el-kw>${this.SUB}</el-kw> <el-method>main</el-method>()`;
      } else if (frame instanceof FunctionMethod) {
        html = `${this.modifierAsHtml(frame)}${this.overrides(frame)}<el-kw>${this.FUNCTION} </el-kw>${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()})<el-kw> ${this.AS} </el-kw>${frame.returnType.renderAsHtml()}${this.implements(frame)}`;
      } else if (frame instanceof ProcedureMethod) {
        html = `${this.modifierAsHtml(frame)}${this.overrides(frame)}<el-kw>${this.SUB} </el-kw>${frame.name.renderAsHtml()}(${frame.params.renderAsHtml()})${this.implements(frame)}`;
      } else if (frame instanceof TestFrame) {
        html = `&lt;<el-type>TestMethod</el-type>&gt; <el-kw>${this.SUB} </el-kw>${frame.testName.renderAsHtml()}()`;
      } else if (frame instanceof TryStatement) {
        html = `<el-kw>${this.TRY} </el-kw>`;
      } else if (frame instanceof While) {
        html = `<el-kw>${this.WHILE} </el-kw>${frame.condition.renderAsHtml()}`;
      }
      return html;
    }
    modifierAsHtml(member) {
      let modifier = "";
      if (member.isPrivate && member.isOnAbstractClass()) {
        modifier = this.PROTECTED;
      } else if (member.isPrivate) {
        modifier = this.PRIVATE;
      }
      return modifier === "" ? "" : `<el-kw>${modifier} </el-kw>`;
    }
    renderBottomAsHtml(frame) {
      let html = `Html not specified for this frame`;
      if (frame instanceof AbstractClass) {
        html = `<el-kw>${this.END} ${this.CLASS}</el-kw>`;
      } else if (frame instanceof ConcreteClass) {
        html = `<el-kw>${this.END} ${this.CLASS}</el-kw>`;
      } else if (frame instanceof Constructor) {
        html = `<el-kw>${this.END} ${this.SUB}</el-kw>`;
      } else if (frame instanceof For) {
        html = `<el-kw>${this.NEXT}</el-kw> <el-id>${frame.variable.renderAsElanSource()}</el-id>`;
      } else if (frame instanceof GlobalFunction || frame instanceof FunctionMethod) {
        html = `<el-kw>${this.END} ${this.FUNCTION}</el-kw>`;
      } else if (frame instanceof GlobalProcedure || frame instanceof ProcedureMethod) {
        html = `<el-kw>${this.END} ${this.SUB}</el-kw>`;
      } else if (frame instanceof IfStatement) {
        html = `<el-kw>${this.END} ${this.IF}</el-kw>`;
      } else if (frame instanceof InterfaceFrame) {
        html = `<el-kw>${this.END} ${this.INTERFACE}</el-kw>`;
      } else if (frame instanceof MainFrame) {
        html = `<el-kw>${this.END} ${this.SUB}</el-kw>`;
      } else if (frame instanceof TestFrame) {
        html = `<el-kw>${this.END} ${this.SUB}</el-kw>`;
      } else if (frame instanceof TryStatement) {
        html = `<el-kw>${this.END} ${this.TRY}</el-kw>`;
      } else if (frame instanceof While) {
        html = `<el-kw>${this.END} ${this.WHILE}</el-kw>`;
      }
      return html;
    }
    renderFileImportsAsHtml() {
      return "";
    }
    renderFileTrailerAsHtml(_f) {
      return "";
    }
    translateExpression(expr) {
      return expr;
    }
    AS = "As";
    CATCH = "Catch";
    CLASS = "Class";
    CONST = "Const";
    DIM = "Dim";
    EACH = "Each";
    ELSEIF = "ElseIf";
    ELSE = "Else";
    END = "End";
    ENUM = "Enum";
    FOR = "For";
    FUNCTION = "Function";
    IF = "If";
    IN = "In";
    INHERITS = "Inherits";
    INTERFACE = "Interface";
    IS = "Is";
    ME = "Me";
    MUST_INHERIT = "MustInherit";
    MUST_OVERRIDE = "MustOverride";
    NEW = "New";
    NEXT = "Next";
    OF = "Of";
    PRIVATE = "Private";
    PROPERTY = "Property";
    PROTECTED = "Protected";
    PUBLIC = "Public";
    RETURN = "Return";
    STEP = "Step";
    SUB = "Sub";
    THEN = "Then";
    THROW = "Throw";
    TO = "To";
    TRY = "Try";
    WHILE = "While";
    SINGLE_QUOTE = "'";
    EQUAL = "=";
    NOT_EQUAL = "<>";
    MOD = "Mod";
    AND = "And";
    OR = "Or";
    NOT = "Not";
    COMMENT_MARKER = this.SINGLE_QUOTE;
    LIST_START = "{";
    LIST_END = "}";
    INTERPOLATED_STRING_PREFIX = "$";
    INT_NAME = "Integer";
    FLOAT_NAME = "Double";
    BOOL_NAME = "Boolean";
    STRING_NAME = "String";
    LIST_NAME = "List";
    NEW_INSTANCE_PREFIX = this.NEW;
    TRUE = "True";
    FALSE = "False";
    BINARY_PREFIX = "&B";
    HEX_PREFIX = "&H";
    START_OF_GENERIC = `(${this.OF} `;
    END_OF_GENERIC = `)`;
    THIS_INSTANCE = this.ME;
    OVERRIDES = "Overrides";
    IMPLEMENTS = "Implements";
    EXPRESSION_KEYWORDS = [this.NEW, this.IF, this.FUNCTION, this.ME, this.NOT];
    addNodesForParamDef(node) {
      node.name = new IdentifierDef(node.file);
      node.addElement(node.name);
      node.addElement(new SpaceNode(node.file, 2 /* required */));
      node.addElement(new PunctuationNode(node.file, this.AS));
      node.addElement(new SpaceNode(node.file, 2 /* required */));
      node.type = new TypeNode(
        node.file,
        /* @__PURE__ */ new Set([
          6 /* type_concrete */,
          7 /* type_abstract */,
          9 /* type_notInheritable */
        ])
      );
      node.addElement(node.type);
    }
    paramDefAsHtml(node) {
      return `${node.name?.renderAsHtml()}<el-kw> ${this.AS} </el-kw>${node.type?.renderAsHtml()}`;
    }
    addNodesForNewInstance(node) {
      node.addElement(new KeywordNode(node.file, this.NEW_INSTANCE_PREFIX));
      node.addElement(new SpaceNode(node.file, 2 /* required */));
      this.addCommonElementsForNewInstance(node);
    }
    addNodesForTypeGeneric(node) {
      node.qualifiedName = new TypeNameUse(node.file, node.tokenTypes);
      const typeConstr = () => new TypeNode(node.file, node.concreteAndAbstract);
      node.genericTypes = new CSV(node.file, typeConstr, 1);
      node.addElement(node.qualifiedName);
      node.addElement(new PunctuationNode(node.file, OPEN_BRACKET));
      node.addElement(new KeywordNode(node.file, this.OF));
      node.addElement(new SpaceNode(node.file, 2 /* required */));
      node.addElement(node.genericTypes);
      node.addElement(new PunctuationNode(node.file, CLOSE_BRACKET));
    }
    addNodesForLambda(node) {
      node.addElement(new KeywordNode(node.file, this.FUNCTION));
      node.addElement(new SpaceNode(node.file, 2 /* required */));
      node.addElement(new PunctuationNode(node.file, OPEN_BRACKET));
      node.params = new CSV(node.file, () => new ParamDefNode(node.file), 0);
      node.addElement(node.params);
      node.addElement(new PunctuationNode(node.file, CLOSE_BRACKET));
      node.addElement(new SpaceNode(node.file, 1 /* added */));
      node.expr = new ExprNode(node.file);
      node.addElement(node.expr);
    }
    lambdaAsHtml(node) {
      return `<el-kw>${this.FUNCTION}</el-kw> (${node.params.renderAsHtml()}) ${node.expr.renderAsHtml()}`;
    }
    typeGenericAsHtml(node) {
      return `${node.qualifiedName?.renderAsHtml()}(<el-kw>${this.OF}</el-kw> ${node.genericTypes?.renderAsHtml()})`;
    }
    newInstanceAsHtml(node) {
      return `<el-kw>${this.NEW_INSTANCE_PREFIX}</el-kw> ${node.type?.renderAsHtml()}(${node.args?.renderAsHtml()})`;
    }
    litStringInterpolatedAsHtml(node) {
      return this.default_litStringInterpolatedAsHtml(node);
    }
    standardiseInterpolatedString(node, text) {
      return this.default_standardiseInterpolatedString(node, text);
    }
    addNodesForTypeTuple(node) {
      this.addCommonElementsForTypeTuple(node);
    }
    typeTupleAsHtml(node) {
      return this.default_typeTupleAsHtml(node);
    }
    enumValuesListAsHtml(field) {
      return languageHelper_enumValuesList(
        field,
        1 /* multiline */,
        0,
        `<br><el-kw>${this.END} ${this.ENUM}</el-kw>`
      );
    }
    inheritsFromTextAsHtml(field) {
      const frame = field.getHolder();
      const node = field.getRootNode();
      let result = ``;
      if (frame.doesInherit() && field.readParseStatus() === 3 /* valid */) {
        const inheritsKw = `<el-kw>${this.INHERITS}</el-kw>`;
        const implementsKw = `<el-kw>${this.IMPLEMENTS}</el-kw>`;
        const abstractClasses = node.getAbstractClassNames();
        if (abstractClasses.length > 0) {
          const typesAsHtml = abstractClasses.map((t) => `<el-type>${t}</el-type>`);
          const csvTypes = typesAsHtml.join(", ");
          result += `<br>&nbsp;&nbsp;${inheritsKw} ${csvTypes}`;
        }
        const interfaces = node.getInterfaceNames();
        if (interfaces.length > 0) {
          const typesAsHtml = interfaces.map((t) => `<el-type>${t}</el-type>`);
          const csvTypes = typesAsHtml.join(", ");
          const keyWord = frame.isInterface ? inheritsKw : implementsKw;
          result += `<br>&nbsp;&nbsp;${keyWord} ${csvTypes}`;
        }
        result += `<br>`;
      } else {
        result = field.default_renderasHtml();
      }
      return result;
    }
    functionFrameFields(frame) {
      return this.default_functionFrameFields(frame);
    }
    assertStatementFields(frame) {
      return [frame.expected, frame.actual];
    }
    reservedWords = /* @__PURE__ */ new Set([
      `addhandler`,
      `addressof`,
      `alias`,
      `and`,
      `andalso`,
      `as`,
      `boolean`,
      `byref`,
      `byte`,
      `byval`,
      `call`,
      `case`,
      `catch`,
      `cbool`,
      `cbyte`,
      `cchar`,
      `cdate`,
      `cdbl`,
      `cdec`,
      `char`,
      `cint`,
      `class`,
      `class`,
      `clng`,
      `cobj`,
      `const`,
      `constraint`,
      `continue`,
      `csbyte`,
      `cshort`,
      `csng`,
      `cstr`,
      `ctype`,
      `cuint`,
      `culng`,
      `cushort`,
      `date`,
      `decimal`,
      `declare`,
      `default`,
      `delegate`,
      `dim`,
      `directcast`,
      `do`,
      `double`,
      `each`,
      `else`,
      `elseif`,
      `end`,
      `endif`,
      `enum`,
      `erase`,
      `error`,
      `event`,
      `exit`,
      `false`,
      `finally`,
      `for`,
      `for`,
      `friend`,
      `function`,
      `get`,
      `gettype`,
      `getxmlnamespace`,
      `global`,
      `gosub`,
      `goto`,
      `handles`,
      `if`,
      `implements`,
      `imports`,
      `in`,
      `inherits`,
      `integer`,
      `interface`,
      `is`,
      `isnot`,
      `let`,
      `lib`,
      `like`,
      `long`,
      `loop`,
      `me`,
      `mod`,
      `module`,
      `mustinherit`,
      `mustoverride`,
      `mybase`,
      `myclass`,
      `nameof`,
      `namespace`,
      `narrowing`,
      `new`,
      `next`,
      `not`,
      `nothing`,
      `notinheritable`,
      `notoverridable`,
      `object`,
      `of`,
      `on`,
      `operator`,
      `option`,
      `optional`,
      `or`,
      `orelse`,
      `out`,
      `overloads`,
      `overridable`,
      `overrides`,
      `paramarray`,
      `partial`,
      `private`,
      `property`,
      `protected`,
      `public`,
      `raiseevent`,
      `readonly`,
      `redim`,
      `rem`,
      `removehandler`,
      `resume`,
      `return`,
      `sbyte`,
      `select`,
      `set`,
      `shadows`,
      `shared`,
      `short`,
      `single`,
      `static`,
      `step`,
      `stop`,
      `string`,
      `structure`,
      `sub`,
      `synclock`,
      `then`,
      `throw`,
      `to`,
      `true`,
      `try`,
      `trycast`,
      `typeof`,
      `uinteger`,
      `ulong`,
      `ushort`,
      `using`,
      `variant`,
      `wend`,
      `when`,
      `while`,
      `widening`,
      `with`,
      `withevents`,
      `writeonly`,
      `xor`
    ]);
  };

  // src/compiler/reserved-words.ts
  var ReservedWords = class _ReservedWords {
    // Singleton
    static Instance = new _ReservedWords();
    constructor() {
      this._set = LanguageElan.Instance.reservedWords.union(LanguagePython.Instance.reservedWords).union(LanguageVB.Instance.reservedWords).union(LanguageCS.Instance.reservedWords).union(LanguageJava.Instance.reservedWords);
    }
    _set;
    matchesIgnoringCase(target) {
      return this._set.has(target.toLowerCase());
    }
  };

  // src/ide/frames/parse-nodes/identifier-use.ts
  var IdentifierUse = class extends AbstractParseNode {
    tokenTypes;
    contextGenerator;
    constructor(file, tokenTypes = /* @__PURE__ */ new Set(), contextGenerator = () => "") {
      super(file);
      this.tokenTypes = tokenTypes;
      this.contextGenerator = contextGenerator;
      this.completionWhenEmpty = "<i>name</i>";
    }
    parseText(text) {
      this.remainingText = text;
      if (text.length > 0) {
        [this.status, this.matchedText, this.remainingText] = matchRegEx(
          text.trimStart(),
          Regexes.identifier
        );
      }
      if (this.isValid() && this.remainingText.length > 0) {
        if (ReservedWords.Instance.matchesIgnoringCase(this.matchedText)) {
          this.status = 0 /* invalid */;
          this.matchedText = "";
          this.remainingText = text;
        } else {
          this._done = true;
        }
      }
    }
    symbolCompletion_tokenTypes() {
      return this.tokenTypes;
    }
    symbolCompletion_context() {
      return this.contextGenerator();
    }
    renderAsHtml() {
      return this.isValid() ? `<el-id>${this.matchedText.trim()}</el-id>` : this.matchedText;
    }
  };

  // src/ide/frames/fields/identifier-field.ts
  var IdentifierField = class extends AbstractField {
    isParseByNodes = true;
    constructor(holder) {
      super(holder);
      this.setPlaceholder("<i>name</i>");
    }
    helpId() {
      return "IdentifierField";
    }
    initialiseRoot() {
      this.rootNode = new IdentifierUse(this.getFile());
      return this.rootNode;
    }
    readToDelimiter = (source) => source.readUntil(/[^a-zA-Z0-9_]/);
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_ident`;
    }
    isEndMarker(key) {
      return key === " " || key === "(";
    }
    symbolCompletion() {
      return this.symbolCompletionAsHtml();
    }
  };

  // src/ide/frames/class-members/abstract-property.ts
  var AbstractProperty = class extends SingleLineFrame {
    isAbstract = true;
    isMember = true;
    name;
    type;
    private = false;
    constructor(parent) {
      super(parent);
      this.name = new IdentifierField(this);
      this.type = new TypeField(this);
      this.canHaveBreakPoint = false;
    }
    isPrivate = false;
    isOnAbstractClass() {
      return true;
    }
    getClass() {
      return this.getParent();
    }
    initialKeywords() {
      return abstractPropertyKeywords;
    }
    getFields() {
      return [this.name, this.type];
    }
    getIdPrefix() {
      return `${this.language().languageHtmlClass}_prop`;
    }
    frameSpecificAnnotation() {
      return "abstract property";
    }
    outerHtmlTag = "el-prop";
    renderAsElanSource() {
      return `${this.indent()}${this.sourceAnnotations()}${abstractKeyword} ${propertyKeyword} ${this.name.renderAsElanSource()} ${asKeyword} ${this.type.renderAsElanSource()}\r
`;
    }
    parseFrom(source) {
      source.remove("abstract property ");
      this.name.parseFrom(source);
      source.remove(" as ");
      this.type.parseFrom(source);
    }
    renderAsExport() {
      return `${super.renderAsExport()}\r
`;
    }
  };

  // src/ide/frames/language-cs.ts
  var LanguageCS = class _LanguageCS extends LanguageCfamily {
    constructor() {
      super();
    }
    static Instance = new _LanguageCS();
    languageHtmlClass = "cs";
    languageFullName = "C#";
    defaultFileExtension = "cs";
    defaultMimeType = "text/plain";
    annotation(frame) {
      let annotation = "";
      if (frame instanceof Property) {
        annotation = frame.frameSpecificAnnotation();
      } else {
        annotation = this.common_Annotation(frame);
      }
      return annotation;
    }
    renderSingleLineAsHtml(frame) {
      let html = "";
      if (frame instanceof AssertStatement) {
        html = `<el-type>Assert</el-type>.<el-method>AreEqual</el-method>(${frame.expected.renderAsHtml()}, ${frame.actual.renderAsHtml()})`;
      } else if (frame instanceof ConstantGlobal) {
        html = `<el-kw>${this.CONST} </el-kw><el-type>${frame.value.getElanType()} </el-type>${frame.name.renderAsHtml()}</el-top> = ${frame.value.renderAsHtml()}`;
      } else if (frame instanceof Property) {
        html = `${this.modifierAsHtml(frame)}${frame.type.renderAsHtml()} ${frame.name.renderAsHtml()} {<el-kw>${this.GET}</el-kw>; <el-kw>${this.PRIVATE} ${this.SET}</el-kw>;}`;
      } else if (frame instanceof AbstractProperty) {
        html = `<el-kw>${this.ABSTRACT}</el-kw> ${frame.type.renderAsHtml()} ${frame.name.renderAsHtml()} {<el-kw>${this.GET}</el-kw>; <el-kw>${this.PRIVATE} ${this.SET}</el-kw>;}`;
      } else {
        html = this.common_renderSingleLineAsHtml(frame);
      }
      return html;
    }
    OVERRIDES = "override";
    IMPLEMENTS = "";
    INTERPOLATED_STRING_PREFIX = "$";
    renderTopAsHtml(frame) {
      let html = "";
      if (frame instanceof TestFrame) {
        html = `[<el-type>TestMethod</el-type>] <el-kw>${this.STATIC} ${this.VOID} </el-kw>${frame.testName.renderAsHtml()}() {`;
      } else {
        html = this.common_renderTopAsHtml(frame);
      }
      return html;
    }
    inheritsFromTextAsHtml(field) {
      const frame = field.getHolder();
      return frame.doesInherit() ? `: ${field.default_renderasHtml()}` : ``;
    }
    renderBottomAsHtml(frame) {
      return this.common_renderBottomAsHtml(frame);
    }
    renderFileImportsAsHtml() {
      return "";
    }
    renderFileTrailerAsHtml(_f) {
      return "";
    }
    translateExpression(expr) {
      return expr;
    }
    addNodesForParamDef(node) {
      this.c_langs_addNodesForParamDef(node);
    }
    paramDefAsHtml(node) {
      return this.c_langs_paramDefAsHtml(node);
    }
    addNodesForTypeGeneric(node) {
      this.c_langs_addNodesForTypeGeneric(node);
    }
    addNodesForTypeTuple(node) {
      this.addCommonElementsForTypeTuple(node);
    }
    typeGenericAsHtml(node) {
      return this.c_langs_typeGenericAsHtml(node);
    }
    addNodesForNewInstance(node) {
      node.addElement(new KeywordNode(node.file, this.NEW_INSTANCE_PREFIX));
      node.addElement(new SpaceNode(node.file, 2 /* required */));
      this.addCommonElementsForNewInstance(node);
    }
    addNodesForLambda(node) {
      node.params = new CSV(node.file, () => new ParamDefNode(node.file), 0);
      node.addElement(node.params);
      node.addElement(new SpaceNode(node.file, 1 /* added */));
      node.addElement(new PunctuationNode(node.file, ARROW));
      node.addElement(new SpaceNode(node.file, 1 /* added */));
      node.expr = new ExprNode(node.file);
      node.addElement(node.expr);
    }
    lambdaAsHtml(node) {
      return `${node.params.renderAsHtml()} ${ARROW} ${node.expr.renderAsHtml()}`;
    }
    newInstanceAsHtml(node) {
      return this.c_langs_newInstanceAsHtml(node);
    }
    litStringInterpolatedAsHtml(node) {
      return this.default_litStringInterpolatedAsHtml(node);
    }
    standardiseInterpolatedString(node, text) {
      return this.default_standardiseInterpolatedString(node, text);
    }
    typeTupleAsHtml(node) {
      return this.default_typeTupleAsHtml(node);
    }
    enumValuesListAsHtml(field) {
      return this.c_langs_enumValuesListAsHtml(field);
    }
    functionFrameFields(frame) {
      return this.common_functionFrameFields(frame);
    }
    assertStatementFields(frame) {
      return this.common_assertStatementFields(frame);
    }
    GET = "get";
    SET = "set";
    reservedWords = /* @__PURE__ */ new Set([
      `abstract`,
      `as`,
      `base`,
      `bool`,
      `break`,
      `byte`,
      `case`,
      `catch`,
      `char`,
      `checked`,
      `class`,
      `const`,
      `continue`,
      `decimal`,
      `default`,
      `delegate`,
      `do`,
      `double`,
      `else`,
      `enum`,
      ``,
      `event`,
      `explicit`,
      `extern`,
      `false`,
      `finally`,
      `fixed`,
      `float`,
      `for`,
      `foreach`,
      `get`,
      `goto`,
      `if`,
      `implicit`,
      `in`,
      `int`,
      `interface`,
      `internal`,
      `is`,
      `lock`,
      `long`,
      `namespace`,
      `new`,
      `null`,
      `object`,
      `operator`,
      `out`,
      `override`,
      `params`,
      `private`,
      `protected`,
      `public`,
      `readonly`,
      `ref`,
      `return`,
      `sbyte`,
      `sealed`,
      `set`,
      `short`,
      `sizeof`,
      `stackalloc`,
      `static`,
      `string`,
      `struct`,
      `switch`,
      `this`,
      `throw`,
      `true`,
      `try`,
      `typeof`,
      `uint`,
      `ulong`,
      `unchecked`,
      `unsafe`,
      `ushort`,
      `using`,
      `virtual`,
      `void`,
      `volatile`,
      `while`
    ]);
  };

  // src/ide/web/ui-helpers.ts
  function checkIsChrome() {
    const isChromium = window.chrome;
    const winNav = window.navigator;
    const vendorName = winNav.vendor;
    const isOpera = typeof window.opr !== "undefined";
    const _isFirefox = winNav.userAgent.indexOf("Firefox") > -1;
    const isIEedge = winNav.userAgent.indexOf("Edg") > -1;
    const isIOSChrome = winNav.userAgent.match("CriOS");
    const isGoogleChrome = typeof winNav.userAgentData !== "undefined" ? winNav.userAgentData.brands.some((b) => b.brand === "Google Chrome") : vendorName === "Google Inc.";
    const isChrome2 = isChromium !== null && typeof isChromium !== "undefined" && vendorName === "Google Inc." && isOpera === false && isIEedge === false && isGoogleChrome;
    if (isIOSChrome) {
      return true;
    } else if (isChrome2 || isIEedge) {
      return true;
    } else {
      return false;
    }
  }
  function confirmContinueOnNonChromeBrowser() {
    return confirm(
      `Elan is compatible with the Chrome or Edge browser. It does not work correctly in Firefox or Safari.`
    );
  }
  function readMsg(value) {
    return { type: "read", value };
  }
  function errorMsg(value) {
    return { type: "status", status: "error", error: value };
  }

  // src/compiler/symbols/any-enum-type.ts
  var AnyEnumType = class _AnyEnumType {
    constructor() {
    }
    languageSpecificName(_language) {
      return this.name;
    }
    initialValue = "";
    typeOptions = immutableTypeOptions;
    static Instance = new _AnyEnumType();
    name = AnyEnumName;
    toString() {
      return this.name;
    }
    isAssignableFrom(otherType) {
      if (otherType instanceof EnumType) {
        return true;
      }
      return false;
    }
  };

  // src/compiler/symbols/any-except-enum-type.ts
  var AnyExceptEnumType = class _AnyExceptEnumType {
    constructor() {
    }
    languageSpecificName(_language) {
      return this.name;
    }
    initialValue = "";
    typeOptions = immutableTypeOptions;
    static Instance = new _AnyExceptEnumType();
    name = AnyExceptEnumName;
    toString() {
      return this.name;
    }
    isAssignableFrom(otherType) {
      if (otherType instanceof EnumType) {
        return false;
      }
      return true;
    }
  };

  // src/compiler/elan-type-annotations.ts
  var ElanClassDescriptor = class {
    constructor(typeOptions = noTypeOptions, ofTypes = [], parameterNames2 = [], parameterTypes = [], inherits = [], alias) {
      this.typeOptions = typeOptions;
      this.ofTypes = ofTypes;
      this.parameterNames = parameterNames2;
      this.parameterTypes = parameterTypes;
      this.inherits = inherits;
      this.alias = alias;
    }
    deprecated;
    mapType(scope) {
      const parameterTypes = this.parameterTypes;
      return new ProcedureType(
        this.parameterNames,
        parameterTypes.map((t) => t.mapType(scope)),
        false,
        false
      );
    }
  };
  var ElanValueTypeDescriptor = class {
    constructor(name, ofType, valueType) {
      this.name = name;
      this.ofType = ofType;
      this.valueType = valueType;
    }
    isGlobalConstant = true;
    mapType(_scope) {
      switch (this.name) {
        case FloatName:
          return FloatType.Instance;
        case StringName:
          return StringType.Instance;
        case IntName:
          return IntType.Instance;
        case BooleanName:
          return BooleanType.Instance;
        case RegExpName:
          return RegExpType.Instance;
        case AnyExceptEnumName:
          return AnyExceptEnumType.Instance;
        case AnyEnumName:
          return AnyEnumType.Instance;
      }
      throw new Error("NotImplemented: " + this.name);
    }
  };
  var ElanGenericTypeDescriptor = class {
    constructor(name, constraint) {
      this.name = name;
      this.constraint = constraint;
    }
    isGlobalConstant = true;
    mapType(scope) {
      return new GenericParameterType(this.name, this.constraint?.mapType(scope));
    }
  };
  function elanClass(option, ofTypes, names, params, inherits, alias) {
    const typeOptions = mapClassOption(option ?? 0 /* concrete */);
    const classDesc = new ElanClassDescriptor(
      typeOptions,
      ofTypes ?? [],
      names ?? [],
      params ?? [],
      inherits ?? [],
      alias
    );
    return function(target) {
      if (Reflect.defineMetadata) {
        Reflect.defineMetadata(elanMetadataKey, classDesc, target);
      }
    };
  }
  var ElanAny = new ElanValueTypeDescriptor(AnyExceptEnumName);
  var ElanAnyEnum = new ElanValueTypeDescriptor(AnyEnumName);
  var ElanInt = new ElanValueTypeDescriptor(IntName);
  var ElanFloat = new ElanValueTypeDescriptor(FloatName);
  var ElanString = new ElanValueTypeDescriptor(StringName);
  var ElanBoolean = new ElanValueTypeDescriptor(BooleanName);
  var ElanRegExp = new ElanValueTypeDescriptor(RegExpName);
  var ElanT1 = new ElanGenericTypeDescriptor("T1");
  var ElanT2 = new ElanGenericTypeDescriptor("T2");
  function mapClassOption(options) {
    const opt = getTypeOptions();
    switch (options) {
      case 0 /* concrete */:
        return opt;
      case 1 /* abstract */:
        opt.isAbstract = true;
        return opt;
      case 2 /* record */:
        opt.isImmutable = true;
        return opt;
      case 3 /* list */:
        opt.isIndexable = opt.isIterable = true;
        return opt;
      case 4 /* dictionary */:
        opt.isIndexable = true;
        return opt;
    }
  }

  // src/compiler/standard-library/elan-runtime-error.ts
  var ElanRuntimeError = class extends Error {
    constructor(err) {
      super(err instanceof Error ? err.message : err);
      this.err = err;
    }
    static emptyInstance() {
      return new ElanRuntimeError("");
    }
    async _initialise(message) {
      this.message = message;
      return this;
    }
    system;
    toString() {
      return this.message ?? "a ElanRuntimeError";
    }
    useLine(token) {
      return !(token.startsWith("data") || token.startsWith("http") || token.startsWith("async") || token.startsWith("Array") || token.startsWith("System") || token.startsWith("onmessage"));
    }
    updateLine0(l0) {
      if (l0.startsWith("RangeError")) {
        return "Error: Stack Overflow";
      }
      return l0;
    }
    get elanStack() {
      const jsStack = this.err instanceof Error ? this.err.stack : this.stack;
      const elanStack = [];
      if (jsStack) {
        let lines = jsStack.split("\n").map((l) => l.trim());
        if (lines.length > 0) {
          elanStack.push(this.updateLine0(lines[0]));
          lines = lines.slice(1);
          for (const l of lines) {
            const line = l.split(" ");
            if (line.length > 1) {
              let fn = line[1];
              fn = fn === "runTests" ? "test" : fn;
              fn = fn === "System.print" ? "print" : fn;
              if (this.useLine(fn)) {
                elanStack.push(`at ${fn}`);
              }
            }
          }
        }
      }
      if (elanStack.length > 0) {
        return elanStack.join("\n");
      }
      return "";
    }
  };
  ElanRuntimeError = __decorateClass([
    elanClass(0 /* concrete */, [], ["message"], [ElanString])
  ], ElanRuntimeError);

  // src/ide/frames/file-impl.ts
  var fileErrorPrefix = `Cannot load file:`;
  var cannotLoadInvalidHashFile = `${fileErrorPrefix} Elan header does not match the code below. The file might have been created or modified outside Elan IDE.`;
  var cannotLoadInvalidFile = `${fileErrorPrefix} code does not begin with a valid Elan header, so cannot be loaded.`;
  var cannotLoadEmptyFile = `${fileErrorPrefix} no code found to load.`;
  var cannotLoadFile = `${fileErrorPrefix} it has been created or modified outside Elan IDE`;
  var cannotLoadUnparseableFile = `${fileErrorPrefix} cannot parse code`;

  // src/ide/web/web-helpers.ts
  function checkForUnclosedHtmlTag(text) {
    if (/<[A-Za-z!\/?][^>]*$/.test(text)) {
      throw new ElanRuntimeError(
        "Unclosed HTML tag in printed text '" + text.replace(/</g, "&lt;") + "'"
      );
    }
  }
  function sanitiseHtml(text) {
    return text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
  }

  // src/ide/web/web-input-output.ts
  var WebInputOutput = class {
    keyBuffer = [];
    display;
    lastDataDirId = "elan-data";
    constructor() {
      this.display = document.getElementById("display");
      this.display.addEventListener("keydown", (k) => {
        if (k.key === "Shift" || k.key === "Control" || k.key === "Alt") {
          return;
        }
        this.keyBuffer.push(k);
      });
      this.display.focus();
    }
    breakPoint(_allScopedSymbols, _id, _singlestep) {
      throw new Error("Method not implemented.");
    }
    useChromeFileAPI() {
      return "showOpenFilePicker" in self;
    }
    chooser() {
      const f = document.createElement("input");
      const g = this.display;
      f.style.display = "none";
      f.type = "file";
      f.name = "file";
      g.appendChild(f);
      return f;
    }
    chromeChooser() {
      const f = document.createElement("input");
      const g = this.display;
      f.style.display = "none";
      g.appendChild(f);
      return f;
    }
    readFileChrome() {
      let fileHandle;
      const chooser = this.chromeChooser();
      return new Promise((rs, rj) => {
        chooser.addEventListener("click", async () => {
          try {
            [fileHandle] = await window.showOpenFilePicker({
              startIn: "documents",
              id: this.lastDataDirId
            });
            const file = await fileHandle.getFile();
            if (file.type !== "text/plain") {
              rj(`cannot load non text file ${file.name} of type ${file.type}`);
            } else {
              const contents = await file.text();
              rs(contents);
            }
          } catch (_e) {
            rj("read cancelled");
          }
        });
        chooser.click();
        this.display?.removeChild(chooser);
      });
    }
    readFile() {
      if (this.useChromeFileAPI()) {
        return this.readFileChrome();
      }
      const inp = this.chooser();
      return new Promise((rs, rj) => {
        inp.addEventListener("change", (event) => {
          const elanFile = event.target.files?.[0];
          if (elanFile) {
            if (elanFile.type !== "text/plain") {
              rj(`cannot load non text file ${elanFile.name} of type ${elanFile.type}`);
            } else {
              const reader = new FileReader();
              reader.addEventListener("load", (event2) => {
                const content = event2.target.result;
                rs(content);
              });
              reader.readAsText(elanFile);
            }
          }
          event.preventDefault();
        });
        inp.addEventListener("cancel", (event) => {
          rj("read cancelled");
          event.preventDefault();
        });
        inp.click();
      });
    }
    async writeFileChrome(fileName, data) {
      try {
        const fh = await self.showSaveFilePicker({
          suggestedName: fileName,
          startIn: "documents",
          id: this.lastDataDirId
        });
        const writeable = await fh.createWritable();
        await writeable.write(data);
        return await writeable.close();
      } catch (_e) {
        throw new Error("write cancelled");
      }
    }
    writeFile(fileName, data) {
      if (!fileName) {
        fileName = "untitled.txt";
      }
      if (!fileName.endsWith(".txt")) {
        fileName = `${fileName}.txt`;
      }
      if (this.useChromeFileAPI()) {
        return this.writeFileChrome(fileName, data);
      }
      return new Promise((rs, rj) => {
        try {
          const blob = new Blob([data], { type: "text/plain" });
          const aElement = document.createElement("a");
          aElement.setAttribute("download", fileName);
          const href = URL.createObjectURL(blob);
          aElement.href = href;
          aElement.setAttribute("target", "_blank");
          aElement.click();
          URL.revokeObjectURL(href);
          rs();
        } catch (_e) {
          rj("write cancelled");
        }
      });
    }
    drawBlockGraphics(html) {
      document.getElementById("block-graphics").innerHTML = html;
      this.display.focus();
      return Promise.resolve();
    }
    clearBlockGraphics() {
      this.clearKeyBuffer();
      return this.drawBlockGraphics("");
    }
    drawVectorGraphics(html) {
      document.getElementById("vector-graphics").innerHTML = html;
      this.display.focus();
      return Promise.resolve();
    }
    clearVectorGraphics() {
      this.clearKeyBuffer();
      return this.drawVectorGraphics("");
    }
    async clearDisplay() {
      this.clearKeyBuffer();
      await this.clearPrintedText();
      await this.clearHtml();
      await this.clearBlockGraphics();
      return this.clearVectorGraphics();
    }
    finished() {
      this.cancelWaits = true;
    }
    cancelWaits = false;
    printedText = "";
    currentInterval;
    async print(text) {
      this.printedText = `${this.printedText}${sanitiseHtml(text)}`;
      await this.renderPrintedText();
      return Promise.resolve();
    }
    async printTab(position, text) {
      const lastNl = this.printedText.lastIndexOf("\n");
      const spaces = "                                                                                ";
      const charsSinceNl = this.printedText.length - lastNl;
      const tab = spaces.substring(0, position - charsSinceNl + 1);
      this.printedText = `${this.printedText}${tab}${sanitiseHtml(text)}`;
      await this.renderPrintedText();
      return Promise.resolve();
    }
    async stopReading() {
      clearInterval(this.currentInterval);
      await this.clearKeyBuffer();
      this.display.focus();
      return Promise.resolve();
    }
    async readLine() {
      await this.renderPrintedText();
      const div = document.getElementById("printed-text");
      const inp = document.createElement("input");
      inp.id = "inp";
      inp.type = "text";
      inp.autofocus = true;
      inp.tabIndex = 2;
      div.appendChild(inp);
      inp.focus();
      this.cancelWaits = false;
      return new Promise((rs) => {
        let entered = false;
        inp.addEventListener("keydown", (k) => {
          entered = k.key === "Enter";
        });
        this.currentInterval = setInterval(async () => {
          if (this.cancelWaits) {
            clearInterval(this.currentInterval);
            rs("");
          } else if (entered) {
            rs(inp.value);
            await this.stopReading();
            const v = inp.value.replace(/</g, "&lt;");
            div.removeChild(inp);
            await this.print(v + "\n");
          }
        }, 250);
      });
    }
    waitForAnyKey() {
      this.cancelWaits = false;
      return new Promise((rs) => {
        const timeOut = setInterval(async () => {
          if (this.cancelWaits || await this.getKey() !== "") {
            clearInterval(timeOut);
            rs();
          }
        }, 250);
      });
    }
    waitForKey() {
      this.cancelWaits = false;
      return new Promise((rs) => {
        const timeOut = setInterval(async () => {
          const key = await this.getKey();
          if (this.cancelWaits || key !== "") {
            clearInterval(timeOut);
            rs(key);
          }
        }, 250);
      });
    }
    getKey() {
      this.display.focus();
      const evt = this.keyBuffer[0];
      this.keyBuffer = this.keyBuffer.slice(1);
      const ks = evt ? evt.key : "";
      return Promise.resolve(ks);
    }
    getModKey(e) {
      return e.ctrlKey ? "Control" : e.shiftKey ? "Shift" : e.altKey ? "Alt" : "";
    }
    getKeyWithModifier() {
      this.display.focus();
      const evt = this.keyBuffer.pop();
      const ks = evt ? [evt.key, this.getModKey(evt)] : ["", ""];
      return Promise.resolve(ks);
    }
    clearKeyBuffer() {
      this.keyBuffer = [];
      return Promise.resolve();
    }
    clearSystemInfo() {
      document.getElementById("system-info").innerHTML = "";
      return Promise.resolve();
    }
    async renderPrintedText() {
      const div = document.getElementById("printed-text");
      div.innerHTML = this.printedText;
      return Promise.resolve();
    }
    async clearPrintedText() {
      this.printedText = "";
      await this.renderPrintedText();
      return Promise.resolve();
    }
    wrapHtmlInSrcdoc(s) {
      return `<head><link href='styles/ide.css' rel='stylesheet'/></head><body><div id='display-html'>${s}</div></body>`;
    }
    wrapHtmlInIframe(s) {
      return `<iframe id="display-html-sandbox" sandbox seamless srcdoc="${this.wrapHtmlInSrcdoc(s)}"</iframe>`;
    }
    drawHtml(html) {
      checkForUnclosedHtmlTag(html);
      const div = document.getElementById("display-html");
      const iframe = document.getElementById("display-html-sandbox");
      if (!iframe) {
        div.innerHTML = this.wrapHtmlInIframe(html);
      } else {
        iframe.srcdoc = this.wrapHtmlInSrcdoc(html);
      }
      return new Promise((rs) => setTimeout(() => rs(), 50));
    }
    clearHtml() {
      document.getElementById("display-html").innerHTML = "";
      return Promise.resolve();
    }
    _audioCtx;
    get audioCtx() {
      if (!this._audioCtx) {
        this._audioCtx = new AudioContext();
      }
      return this._audioCtx;
    }
    tone(duration, frequency, volume) {
      return new Promise((rs) => {
        const ac = this.audioCtx;
        const oscillator = ac.createOscillator();
        const gainNode = ac.createGain();
        oscillator.connect(gainNode);
        gainNode.connect(ac.destination);
        gainNode.gain.value = volume;
        oscillator.frequency.value = frequency;
        oscillator.type = "sine";
        oscillator.onended = (_e) => rs();
        oscillator.start(ac.currentTime);
        oscillator.stop(ac.currentTime + duration / 1e3);
      });
    }
  };

  // src/ide/web/standalone.ts
  var displayDiv = document.getElementById("display");
  var elanInputOutput = new WebInputOutput();
  var runWorker;
  var jsCode = `injected_code`;
  displayDiv.addEventListener("click", () => {
    displayDiv.getElementsByTagName("input")?.[0]?.focus();
  });
  function runProgram() {
    try {
      runWorker = new Worker(jsCode, { type: "module" });
      runWorker.onmessage = async (e) => {
        const data = e.data;
        switch (data.type) {
          case "write":
            await handleWorkerIO(data);
            break;
          case "status":
            switch (data.status) {
              case "finished":
                handleRunWorkerFinished();
                break;
              case "error":
                await handleRunWorkerError(data);
                break;
            }
        }
      };
      runWorker.onerror = async (ev) => {
        console.warn(ev.message);
      };
      runWorker.postMessage({ type: "start" });
    } catch (e) {
      console.warn(e);
    }
  }
  var isChrome = checkIsChrome();
  var okToContinue = isChrome || confirmContinueOnNonChromeBrowser();
  if (okToContinue) {
    runProgram();
  }
  async function handleWorkerIO(data) {
    switch (data.function) {
      case "readLine":
        const line = await elanInputOutput.readLine();
        runWorker?.postMessage(readMsg(line));
        break;
      case "waitForAnyKey":
        await elanInputOutput.waitForAnyKey();
        runWorker?.postMessage(readMsg(""));
        break;
      case "waitForKey":
        const wkey = await elanInputOutput.waitForKey();
        runWorker?.postMessage(readMsg(wkey));
        break;
      case "getKey":
        const key = await elanInputOutput.getKey();
        runWorker?.postMessage(readMsg(key));
        break;
      case "getKeyWithModifier":
        const keyWithMod = await elanInputOutput.getKeyWithModifier();
        runWorker?.postMessage(readMsg(keyWithMod));
        break;
      case "readFile":
        try {
          const file = await elanInputOutput.readFile();
          runWorker?.postMessage(readMsg(file));
        } catch (e) {
          runWorker?.postMessage(errorMsg(e));
        }
        break;
      case "writeFile":
        try {
          await elanInputOutput.writeFile(data.parameters[0], data.parameters[1]);
          runWorker?.postMessage(readMsg(""));
        } catch (e) {
          runWorker?.postMessage(errorMsg(e));
        }
        break;
      default:
        try {
          await elanInputOutput[data.function](...data.parameters);
          runWorker?.postMessage(readMsg(""));
        } catch (e) {
          runWorker?.postMessage(errorMsg(e));
        }
        break;
    }
  }
  function handleRunWorkerFinished() {
    runWorker?.terminate();
    runWorker = void 0;
    console.info("elan program completed OK");
  }
  async function handleRunWorkerError(data) {
    runWorker?.terminate();
    runWorker = void 0;
    console.warn(data.error);
  }
})();
