var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
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;
};
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);

// node_modules/reflect-metadata/Reflect.js
var require_Reflect = __commonJS({
  "node_modules/reflect-metadata/Reflect.js"() {
    var Reflect2;
    (function(Reflect3) {
      (function(factory) {
        var root = typeof globalThis === "object" ? globalThis : typeof global === "object" ? global : typeof self === "object" ? self : typeof this === "object" ? this : sloppyModeThis();
        var exporter = makeExporter(Reflect3);
        if (typeof root.Reflect !== "undefined") {
          exporter = makeExporter(root.Reflect, exporter);
        }
        factory(exporter, root);
        if (typeof root.Reflect === "undefined") {
          root.Reflect = Reflect3;
        }
        function makeExporter(target, previous) {
          return function(key, value) {
            Object.defineProperty(target, key, { configurable: true, writable: true, value });
            if (previous)
              previous(key, value);
          };
        }
        function functionThis() {
          try {
            return Function("return this;")();
          } catch (_) {
          }
        }
        function indirectEvalThis() {
          try {
            return (void 0, eval)("(function() { return this; })()");
          } catch (_) {
          }
        }
        function sloppyModeThis() {
          return functionThis() || indirectEvalThis();
        }
      })(function(exporter, root) {
        var hasOwn = Object.prototype.hasOwnProperty;
        var supportsSymbol = typeof Symbol === "function";
        var toPrimitiveSymbol = supportsSymbol && typeof Symbol.toPrimitive !== "undefined" ? Symbol.toPrimitive : "@@toPrimitive";
        var iteratorSymbol = supportsSymbol && typeof Symbol.iterator !== "undefined" ? Symbol.iterator : "@@iterator";
        var supportsCreate = typeof Object.create === "function";
        var supportsProto = { __proto__: [] } instanceof Array;
        var downLevel = !supportsCreate && !supportsProto;
        var HashMap = {
          // create an object in dictionary mode (a.k.a. "slow" mode in v8)
          create: supportsCreate ? function() {
            return MakeDictionary(/* @__PURE__ */ Object.create(null));
          } : supportsProto ? function() {
            return MakeDictionary({ __proto__: null });
          } : function() {
            return MakeDictionary({});
          },
          has: downLevel ? function(map, key) {
            return hasOwn.call(map, key);
          } : function(map, key) {
            return key in map;
          },
          get: downLevel ? function(map, key) {
            return hasOwn.call(map, key) ? map[key] : void 0;
          } : function(map, key) {
            return map[key];
          }
        };
        var functionPrototype = Object.getPrototypeOf(Function);
        var _Map = typeof Map === "function" && typeof Map.prototype.entries === "function" ? Map : CreateMapPolyfill();
        var _Set = typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : CreateSetPolyfill();
        var _WeakMap = typeof WeakMap === "function" ? WeakMap : CreateWeakMapPolyfill();
        var registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : void 0;
        var metadataRegistry = GetOrCreateMetadataRegistry();
        var metadataProvider = CreateMetadataProvider(metadataRegistry);
        function decorate(decorators, target, propertyKey, attributes) {
          if (!IsUndefined(propertyKey)) {
            if (!IsArray(decorators))
              throw new TypeError();
            if (!IsObject(target))
              throw new TypeError();
            if (!IsObject(attributes) && !IsUndefined(attributes) && !IsNull(attributes))
              throw new TypeError();
            if (IsNull(attributes))
              attributes = void 0;
            propertyKey = ToPropertyKey(propertyKey);
            return DecorateProperty(decorators, target, propertyKey, attributes);
          } else {
            if (!IsArray(decorators))
              throw new TypeError();
            if (!IsConstructor(target))
              throw new TypeError();
            return DecorateConstructor(decorators, target);
          }
        }
        exporter("decorate", decorate);
        function metadata(metadataKey, metadataValue) {
          function decorator(target, propertyKey) {
            if (!IsObject(target))
              throw new TypeError();
            if (!IsUndefined(propertyKey) && !IsPropertyKey(propertyKey))
              throw new TypeError();
            OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey);
          }
          return decorator;
        }
        exporter("metadata", metadata);
        function defineMetadata(metadataKey, metadataValue, target, propertyKey) {
          if (!IsObject(target))
            throw new TypeError();
          if (!IsUndefined(propertyKey))
            propertyKey = ToPropertyKey(propertyKey);
          return OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey);
        }
        exporter("defineMetadata", defineMetadata);
        function hasMetadata(metadataKey, target, propertyKey) {
          if (!IsObject(target))
            throw new TypeError();
          if (!IsUndefined(propertyKey))
            propertyKey = ToPropertyKey(propertyKey);
          return OrdinaryHasMetadata(metadataKey, target, propertyKey);
        }
        exporter("hasMetadata", hasMetadata);
        function hasOwnMetadata(metadataKey, target, propertyKey) {
          if (!IsObject(target))
            throw new TypeError();
          if (!IsUndefined(propertyKey))
            propertyKey = ToPropertyKey(propertyKey);
          return OrdinaryHasOwnMetadata(metadataKey, target, propertyKey);
        }
        exporter("hasOwnMetadata", hasOwnMetadata);
        function getMetadata(metadataKey, target, propertyKey) {
          if (!IsObject(target))
            throw new TypeError();
          if (!IsUndefined(propertyKey))
            propertyKey = ToPropertyKey(propertyKey);
          return OrdinaryGetMetadata(metadataKey, target, propertyKey);
        }
        exporter("getMetadata", getMetadata);
        function getOwnMetadata(metadataKey, target, propertyKey) {
          if (!IsObject(target))
            throw new TypeError();
          if (!IsUndefined(propertyKey))
            propertyKey = ToPropertyKey(propertyKey);
          return OrdinaryGetOwnMetadata(metadataKey, target, propertyKey);
        }
        exporter("getOwnMetadata", getOwnMetadata);
        function getMetadataKeys(target, propertyKey) {
          if (!IsObject(target))
            throw new TypeError();
          if (!IsUndefined(propertyKey))
            propertyKey = ToPropertyKey(propertyKey);
          return OrdinaryMetadataKeys(target, propertyKey);
        }
        exporter("getMetadataKeys", getMetadataKeys);
        function getOwnMetadataKeys(target, propertyKey) {
          if (!IsObject(target))
            throw new TypeError();
          if (!IsUndefined(propertyKey))
            propertyKey = ToPropertyKey(propertyKey);
          return OrdinaryOwnMetadataKeys(target, propertyKey);
        }
        exporter("getOwnMetadataKeys", getOwnMetadataKeys);
        function deleteMetadata(metadataKey, target, propertyKey) {
          if (!IsObject(target))
            throw new TypeError();
          if (!IsUndefined(propertyKey))
            propertyKey = ToPropertyKey(propertyKey);
          if (!IsObject(target))
            throw new TypeError();
          if (!IsUndefined(propertyKey))
            propertyKey = ToPropertyKey(propertyKey);
          var provider = GetMetadataProvider(
            target,
            propertyKey,
            /*Create*/
            false
          );
          if (IsUndefined(provider))
            return false;
          return provider.OrdinaryDeleteMetadata(metadataKey, target, propertyKey);
        }
        exporter("deleteMetadata", deleteMetadata);
        function DecorateConstructor(decorators, target) {
          for (var i = decorators.length - 1; i >= 0; --i) {
            var decorator = decorators[i];
            var decorated = decorator(target);
            if (!IsUndefined(decorated) && !IsNull(decorated)) {
              if (!IsConstructor(decorated))
                throw new TypeError();
              target = decorated;
            }
          }
          return target;
        }
        function DecorateProperty(decorators, target, propertyKey, descriptor) {
          for (var i = decorators.length - 1; i >= 0; --i) {
            var decorator = decorators[i];
            var decorated = decorator(target, propertyKey, descriptor);
            if (!IsUndefined(decorated) && !IsNull(decorated)) {
              if (!IsObject(decorated))
                throw new TypeError();
              descriptor = decorated;
            }
          }
          return descriptor;
        }
        function OrdinaryHasMetadata(MetadataKey, O, P) {
          var hasOwn2 = OrdinaryHasOwnMetadata(MetadataKey, O, P);
          if (hasOwn2)
            return true;
          var parent = OrdinaryGetPrototypeOf(O);
          if (!IsNull(parent))
            return OrdinaryHasMetadata(MetadataKey, parent, P);
          return false;
        }
        function OrdinaryHasOwnMetadata(MetadataKey, O, P) {
          var provider = GetMetadataProvider(
            O,
            P,
            /*Create*/
            false
          );
          if (IsUndefined(provider))
            return false;
          return ToBoolean(provider.OrdinaryHasOwnMetadata(MetadataKey, O, P));
        }
        function OrdinaryGetMetadata(MetadataKey, O, P) {
          var hasOwn2 = OrdinaryHasOwnMetadata(MetadataKey, O, P);
          if (hasOwn2)
            return OrdinaryGetOwnMetadata(MetadataKey, O, P);
          var parent = OrdinaryGetPrototypeOf(O);
          if (!IsNull(parent))
            return OrdinaryGetMetadata(MetadataKey, parent, P);
          return void 0;
        }
        function OrdinaryGetOwnMetadata(MetadataKey, O, P) {
          var provider = GetMetadataProvider(
            O,
            P,
            /*Create*/
            false
          );
          if (IsUndefined(provider))
            return;
          return provider.OrdinaryGetOwnMetadata(MetadataKey, O, P);
        }
        function OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P) {
          var provider = GetMetadataProvider(
            O,
            P,
            /*Create*/
            true
          );
          provider.OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P);
        }
        function OrdinaryMetadataKeys(O, P) {
          var ownKeys = OrdinaryOwnMetadataKeys(O, P);
          var parent = OrdinaryGetPrototypeOf(O);
          if (parent === null)
            return ownKeys;
          var parentKeys = OrdinaryMetadataKeys(parent, P);
          if (parentKeys.length <= 0)
            return ownKeys;
          if (ownKeys.length <= 0)
            return parentKeys;
          var set = new _Set();
          var keys = [];
          for (var _i = 0, ownKeys_1 = ownKeys; _i < ownKeys_1.length; _i++) {
            var key = ownKeys_1[_i];
            var hasKey = set.has(key);
            if (!hasKey) {
              set.add(key);
              keys.push(key);
            }
          }
          for (var _a = 0, parentKeys_1 = parentKeys; _a < parentKeys_1.length; _a++) {
            var key = parentKeys_1[_a];
            var hasKey = set.has(key);
            if (!hasKey) {
              set.add(key);
              keys.push(key);
            }
          }
          return keys;
        }
        function OrdinaryOwnMetadataKeys(O, P) {
          var provider = GetMetadataProvider(
            O,
            P,
            /*create*/
            false
          );
          if (!provider) {
            return [];
          }
          return provider.OrdinaryOwnMetadataKeys(O, P);
        }
        function Type(x) {
          if (x === null)
            return 1;
          switch (typeof x) {
            case "undefined":
              return 0;
            case "boolean":
              return 2;
            case "string":
              return 3;
            case "symbol":
              return 4;
            case "number":
              return 5;
            case "object":
              return x === null ? 1 : 6;
            default:
              return 6;
          }
        }
        function IsUndefined(x) {
          return x === void 0;
        }
        function IsNull(x) {
          return x === null;
        }
        function IsSymbol(x) {
          return typeof x === "symbol";
        }
        function IsObject(x) {
          return typeof x === "object" ? x !== null : typeof x === "function";
        }
        function ToPrimitive(input, PreferredType) {
          switch (Type(input)) {
            case 0:
              return input;
            case 1:
              return input;
            case 2:
              return input;
            case 3:
              return input;
            case 4:
              return input;
            case 5:
              return input;
          }
          var hint = PreferredType === 3 ? "string" : PreferredType === 5 ? "number" : "default";
          var exoticToPrim = GetMethod(input, toPrimitiveSymbol);
          if (exoticToPrim !== void 0) {
            var result = exoticToPrim.call(input, hint);
            if (IsObject(result))
              throw new TypeError();
            return result;
          }
          return OrdinaryToPrimitive(input, hint === "default" ? "number" : hint);
        }
        function OrdinaryToPrimitive(O, hint) {
          if (hint === "string") {
            var toString_1 = O.toString;
            if (IsCallable(toString_1)) {
              var result = toString_1.call(O);
              if (!IsObject(result))
                return result;
            }
            var valueOf = O.valueOf;
            if (IsCallable(valueOf)) {
              var result = valueOf.call(O);
              if (!IsObject(result))
                return result;
            }
          } else {
            var valueOf = O.valueOf;
            if (IsCallable(valueOf)) {
              var result = valueOf.call(O);
              if (!IsObject(result))
                return result;
            }
            var toString_2 = O.toString;
            if (IsCallable(toString_2)) {
              var result = toString_2.call(O);
              if (!IsObject(result))
                return result;
            }
          }
          throw new TypeError();
        }
        function ToBoolean(argument) {
          return !!argument;
        }
        function ToString(argument) {
          return "" + argument;
        }
        function ToPropertyKey(argument) {
          var key = ToPrimitive(
            argument,
            3
            /* String */
          );
          if (IsSymbol(key))
            return key;
          return ToString(key);
        }
        function IsArray(argument) {
          return Array.isArray ? Array.isArray(argument) : argument instanceof Object ? argument instanceof Array : Object.prototype.toString.call(argument) === "[object Array]";
        }
        function IsCallable(argument) {
          return typeof argument === "function";
        }
        function IsConstructor(argument) {
          return typeof argument === "function";
        }
        function IsPropertyKey(argument) {
          switch (Type(argument)) {
            case 3:
              return true;
            case 4:
              return true;
            default:
              return false;
          }
        }
        function SameValueZero(x, y) {
          return x === y || x !== x && y !== y;
        }
        function GetMethod(V, P) {
          var func = V[P];
          if (func === void 0 || func === null)
            return void 0;
          if (!IsCallable(func))
            throw new TypeError();
          return func;
        }
        function GetIterator(obj) {
          var method = GetMethod(obj, iteratorSymbol);
          if (!IsCallable(method))
            throw new TypeError();
          var iterator = method.call(obj);
          if (!IsObject(iterator))
            throw new TypeError();
          return iterator;
        }
        function IteratorValue(iterResult) {
          return iterResult.value;
        }
        function IteratorStep(iterator) {
          var result = iterator.next();
          return result.done ? false : result;
        }
        function IteratorClose(iterator) {
          var f = iterator["return"];
          if (f)
            f.call(iterator);
        }
        function OrdinaryGetPrototypeOf(O) {
          var proto = Object.getPrototypeOf(O);
          if (typeof O !== "function" || O === functionPrototype)
            return proto;
          if (proto !== functionPrototype)
            return proto;
          var prototype = O.prototype;
          var prototypeProto = prototype && Object.getPrototypeOf(prototype);
          if (prototypeProto == null || prototypeProto === Object.prototype)
            return proto;
          var constructor = prototypeProto.constructor;
          if (typeof constructor !== "function")
            return proto;
          if (constructor === O)
            return proto;
          return constructor;
        }
        function CreateMetadataRegistry() {
          var fallback;
          if (!IsUndefined(registrySymbol) && typeof root.Reflect !== "undefined" && !(registrySymbol in root.Reflect) && typeof root.Reflect.defineMetadata === "function") {
            fallback = CreateFallbackProvider(root.Reflect);
          }
          var first;
          var second;
          var rest;
          var targetProviderMap = new _WeakMap();
          var registry = {
            registerProvider,
            getProvider,
            setProvider
          };
          return registry;
          function registerProvider(provider) {
            if (!Object.isExtensible(registry)) {
              throw new Error("Cannot add provider to a frozen registry.");
            }
            switch (true) {
              case fallback === provider:
                break;
              case IsUndefined(first):
                first = provider;
                break;
              case first === provider:
                break;
              case IsUndefined(second):
                second = provider;
                break;
              case second === provider:
                break;
              default:
                if (rest === void 0)
                  rest = new _Set();
                rest.add(provider);
                break;
            }
          }
          function getProviderNoCache(O, P) {
            if (!IsUndefined(first)) {
              if (first.isProviderFor(O, P))
                return first;
              if (!IsUndefined(second)) {
                if (second.isProviderFor(O, P))
                  return first;
                if (!IsUndefined(rest)) {
                  var iterator = GetIterator(rest);
                  while (true) {
                    var next = IteratorStep(iterator);
                    if (!next) {
                      return void 0;
                    }
                    var provider = IteratorValue(next);
                    if (provider.isProviderFor(O, P)) {
                      IteratorClose(iterator);
                      return provider;
                    }
                  }
                }
              }
            }
            if (!IsUndefined(fallback) && fallback.isProviderFor(O, P)) {
              return fallback;
            }
            return void 0;
          }
          function getProvider(O, P) {
            var providerMap = targetProviderMap.get(O);
            var provider;
            if (!IsUndefined(providerMap)) {
              provider = providerMap.get(P);
            }
            if (!IsUndefined(provider)) {
              return provider;
            }
            provider = getProviderNoCache(O, P);
            if (!IsUndefined(provider)) {
              if (IsUndefined(providerMap)) {
                providerMap = new _Map();
                targetProviderMap.set(O, providerMap);
              }
              providerMap.set(P, provider);
            }
            return provider;
          }
          function hasProvider(provider) {
            if (IsUndefined(provider))
              throw new TypeError();
            return first === provider || second === provider || !IsUndefined(rest) && rest.has(provider);
          }
          function setProvider(O, P, provider) {
            if (!hasProvider(provider)) {
              throw new Error("Metadata provider not registered.");
            }
            var existingProvider = getProvider(O, P);
            if (existingProvider !== provider) {
              if (!IsUndefined(existingProvider)) {
                return false;
              }
              var providerMap = targetProviderMap.get(O);
              if (IsUndefined(providerMap)) {
                providerMap = new _Map();
                targetProviderMap.set(O, providerMap);
              }
              providerMap.set(P, provider);
            }
            return true;
          }
        }
        function GetOrCreateMetadataRegistry() {
          var metadataRegistry2;
          if (!IsUndefined(registrySymbol) && IsObject(root.Reflect) && Object.isExtensible(root.Reflect)) {
            metadataRegistry2 = root.Reflect[registrySymbol];
          }
          if (IsUndefined(metadataRegistry2)) {
            metadataRegistry2 = CreateMetadataRegistry();
          }
          if (!IsUndefined(registrySymbol) && IsObject(root.Reflect) && Object.isExtensible(root.Reflect)) {
            Object.defineProperty(root.Reflect, registrySymbol, {
              enumerable: false,
              configurable: false,
              writable: false,
              value: metadataRegistry2
            });
          }
          return metadataRegistry2;
        }
        function CreateMetadataProvider(registry) {
          var metadata2 = new _WeakMap();
          var provider = {
            isProviderFor: function(O, P) {
              var targetMetadata = metadata2.get(O);
              if (IsUndefined(targetMetadata))
                return false;
              return targetMetadata.has(P);
            },
            OrdinaryDefineOwnMetadata: OrdinaryDefineOwnMetadata2,
            OrdinaryHasOwnMetadata: OrdinaryHasOwnMetadata2,
            OrdinaryGetOwnMetadata: OrdinaryGetOwnMetadata2,
            OrdinaryOwnMetadataKeys: OrdinaryOwnMetadataKeys2,
            OrdinaryDeleteMetadata
          };
          metadataRegistry.registerProvider(provider);
          return provider;
          function GetOrCreateMetadataMap(O, P, Create) {
            var targetMetadata = metadata2.get(O);
            var createdTargetMetadata = false;
            if (IsUndefined(targetMetadata)) {
              if (!Create)
                return void 0;
              targetMetadata = new _Map();
              metadata2.set(O, targetMetadata);
              createdTargetMetadata = true;
            }
            var metadataMap = targetMetadata.get(P);
            if (IsUndefined(metadataMap)) {
              if (!Create)
                return void 0;
              metadataMap = new _Map();
              targetMetadata.set(P, metadataMap);
              if (!registry.setProvider(O, P, provider)) {
                targetMetadata.delete(P);
                if (createdTargetMetadata) {
                  metadata2.delete(O);
                }
                throw new Error("Wrong provider for target.");
              }
            }
            return metadataMap;
          }
          function OrdinaryHasOwnMetadata2(MetadataKey, O, P) {
            var metadataMap = GetOrCreateMetadataMap(
              O,
              P,
              /*Create*/
              false
            );
            if (IsUndefined(metadataMap))
              return false;
            return ToBoolean(metadataMap.has(MetadataKey));
          }
          function OrdinaryGetOwnMetadata2(MetadataKey, O, P) {
            var metadataMap = GetOrCreateMetadataMap(
              O,
              P,
              /*Create*/
              false
            );
            if (IsUndefined(metadataMap))
              return void 0;
            return metadataMap.get(MetadataKey);
          }
          function OrdinaryDefineOwnMetadata2(MetadataKey, MetadataValue, O, P) {
            var metadataMap = GetOrCreateMetadataMap(
              O,
              P,
              /*Create*/
              true
            );
            metadataMap.set(MetadataKey, MetadataValue);
          }
          function OrdinaryOwnMetadataKeys2(O, P) {
            var keys = [];
            var metadataMap = GetOrCreateMetadataMap(
              O,
              P,
              /*Create*/
              false
            );
            if (IsUndefined(metadataMap))
              return keys;
            var keysObj = metadataMap.keys();
            var iterator = GetIterator(keysObj);
            var k = 0;
            while (true) {
              var next = IteratorStep(iterator);
              if (!next) {
                keys.length = k;
                return keys;
              }
              var nextValue = IteratorValue(next);
              try {
                keys[k] = nextValue;
              } catch (e) {
                try {
                  IteratorClose(iterator);
                } finally {
                  throw e;
                }
              }
              k++;
            }
          }
          function OrdinaryDeleteMetadata(MetadataKey, O, P) {
            var metadataMap = GetOrCreateMetadataMap(
              O,
              P,
              /*Create*/
              false
            );
            if (IsUndefined(metadataMap))
              return false;
            if (!metadataMap.delete(MetadataKey))
              return false;
            if (metadataMap.size === 0) {
              var targetMetadata = metadata2.get(O);
              if (!IsUndefined(targetMetadata)) {
                targetMetadata.delete(P);
                if (targetMetadata.size === 0) {
                  metadata2.delete(targetMetadata);
                }
              }
            }
            return true;
          }
        }
        function CreateFallbackProvider(reflect) {
          var defineMetadata2 = reflect.defineMetadata, hasOwnMetadata2 = reflect.hasOwnMetadata, getOwnMetadata2 = reflect.getOwnMetadata, getOwnMetadataKeys2 = reflect.getOwnMetadataKeys, deleteMetadata2 = reflect.deleteMetadata;
          var metadataOwner = new _WeakMap();
          var provider = {
            isProviderFor: function(O, P) {
              var metadataPropertySet = metadataOwner.get(O);
              if (!IsUndefined(metadataPropertySet) && metadataPropertySet.has(P)) {
                return true;
              }
              if (getOwnMetadataKeys2(O, P).length) {
                if (IsUndefined(metadataPropertySet)) {
                  metadataPropertySet = new _Set();
                  metadataOwner.set(O, metadataPropertySet);
                }
                metadataPropertySet.add(P);
                return true;
              }
              return false;
            },
            OrdinaryDefineOwnMetadata: defineMetadata2,
            OrdinaryHasOwnMetadata: hasOwnMetadata2,
            OrdinaryGetOwnMetadata: getOwnMetadata2,
            OrdinaryOwnMetadataKeys: getOwnMetadataKeys2,
            OrdinaryDeleteMetadata: deleteMetadata2
          };
          return provider;
        }
        function GetMetadataProvider(O, P, Create) {
          var registeredProvider = metadataRegistry.getProvider(O, P);
          if (!IsUndefined(registeredProvider)) {
            return registeredProvider;
          }
          if (Create) {
            if (metadataRegistry.setProvider(O, P, metadataProvider)) {
              return metadataProvider;
            }
            throw new Error("Illegal state.");
          }
          return void 0;
        }
        function CreateMapPolyfill() {
          var cacheSentinel = {};
          var arraySentinel = [];
          var MapIterator = (
            /** @class */
            function() {
              function MapIterator2(keys, values, selector) {
                this._index = 0;
                this._keys = keys;
                this._values = values;
                this._selector = selector;
              }
              MapIterator2.prototype["@@iterator"] = function() {
                return this;
              };
              MapIterator2.prototype[iteratorSymbol] = function() {
                return this;
              };
              MapIterator2.prototype.next = function() {
                var index = this._index;
                if (index >= 0 && index < this._keys.length) {
                  var result = this._selector(this._keys[index], this._values[index]);
                  if (index + 1 >= this._keys.length) {
                    this._index = -1;
                    this._keys = arraySentinel;
                    this._values = arraySentinel;
                  } else {
                    this._index++;
                  }
                  return { value: result, done: false };
                }
                return { value: void 0, done: true };
              };
              MapIterator2.prototype.throw = function(error) {
                if (this._index >= 0) {
                  this._index = -1;
                  this._keys = arraySentinel;
                  this._values = arraySentinel;
                }
                throw error;
              };
              MapIterator2.prototype.return = function(value) {
                if (this._index >= 0) {
                  this._index = -1;
                  this._keys = arraySentinel;
                  this._values = arraySentinel;
                }
                return { value, done: true };
              };
              return MapIterator2;
            }()
          );
          var Map2 = (
            /** @class */
            function() {
              function Map3() {
                this._keys = [];
                this._values = [];
                this._cacheKey = cacheSentinel;
                this._cacheIndex = -2;
              }
              Object.defineProperty(Map3.prototype, "size", {
                get: function() {
                  return this._keys.length;
                },
                enumerable: true,
                configurable: true
              });
              Map3.prototype.has = function(key) {
                return this._find(
                  key,
                  /*insert*/
                  false
                ) >= 0;
              };
              Map3.prototype.get = function(key) {
                var index = this._find(
                  key,
                  /*insert*/
                  false
                );
                return index >= 0 ? this._values[index] : void 0;
              };
              Map3.prototype.set = function(key, value) {
                var index = this._find(
                  key,
                  /*insert*/
                  true
                );
                this._values[index] = value;
                return this;
              };
              Map3.prototype.delete = function(key) {
                var index = this._find(
                  key,
                  /*insert*/
                  false
                );
                if (index >= 0) {
                  var size = this._keys.length;
                  for (var i = index + 1; i < size; i++) {
                    this._keys[i - 1] = this._keys[i];
                    this._values[i - 1] = this._values[i];
                  }
                  this._keys.length--;
                  this._values.length--;
                  if (SameValueZero(key, this._cacheKey)) {
                    this._cacheKey = cacheSentinel;
                    this._cacheIndex = -2;
                  }
                  return true;
                }
                return false;
              };
              Map3.prototype.clear = function() {
                this._keys.length = 0;
                this._values.length = 0;
                this._cacheKey = cacheSentinel;
                this._cacheIndex = -2;
              };
              Map3.prototype.keys = function() {
                return new MapIterator(this._keys, this._values, getKey);
              };
              Map3.prototype.values = function() {
                return new MapIterator(this._keys, this._values, getValue);
              };
              Map3.prototype.entries = function() {
                return new MapIterator(this._keys, this._values, getEntry);
              };
              Map3.prototype["@@iterator"] = function() {
                return this.entries();
              };
              Map3.prototype[iteratorSymbol] = function() {
                return this.entries();
              };
              Map3.prototype._find = function(key, insert) {
                if (!SameValueZero(this._cacheKey, key)) {
                  this._cacheIndex = -1;
                  for (var i = 0; i < this._keys.length; i++) {
                    if (SameValueZero(this._keys[i], key)) {
                      this._cacheIndex = i;
                      break;
                    }
                  }
                }
                if (this._cacheIndex < 0 && insert) {
                  this._cacheIndex = this._keys.length;
                  this._keys.push(key);
                  this._values.push(void 0);
                }
                return this._cacheIndex;
              };
              return Map3;
            }()
          );
          return Map2;
          function getKey(key, _) {
            return key;
          }
          function getValue(_, value) {
            return value;
          }
          function getEntry(key, value) {
            return [key, value];
          }
        }
        function CreateSetPolyfill() {
          var Set2 = (
            /** @class */
            function() {
              function Set3() {
                this._map = new _Map();
              }
              Object.defineProperty(Set3.prototype, "size", {
                get: function() {
                  return this._map.size;
                },
                enumerable: true,
                configurable: true
              });
              Set3.prototype.has = function(value) {
                return this._map.has(value);
              };
              Set3.prototype.add = function(value) {
                return this._map.set(value, value), this;
              };
              Set3.prototype.delete = function(value) {
                return this._map.delete(value);
              };
              Set3.prototype.clear = function() {
                this._map.clear();
              };
              Set3.prototype.keys = function() {
                return this._map.keys();
              };
              Set3.prototype.values = function() {
                return this._map.keys();
              };
              Set3.prototype.entries = function() {
                return this._map.entries();
              };
              Set3.prototype["@@iterator"] = function() {
                return this.keys();
              };
              Set3.prototype[iteratorSymbol] = function() {
                return this.keys();
              };
              return Set3;
            }()
          );
          return Set2;
        }
        function CreateWeakMapPolyfill() {
          var UUID_SIZE = 16;
          var keys = HashMap.create();
          var rootKey = CreateUniqueKey();
          return (
            /** @class */
            function() {
              function WeakMap2() {
                this._key = CreateUniqueKey();
              }
              WeakMap2.prototype.has = function(target) {
                var table = GetOrCreateWeakMapTable(
                  target,
                  /*create*/
                  false
                );
                return table !== void 0 ? HashMap.has(table, this._key) : false;
              };
              WeakMap2.prototype.get = function(target) {
                var table = GetOrCreateWeakMapTable(
                  target,
                  /*create*/
                  false
                );
                return table !== void 0 ? HashMap.get(table, this._key) : void 0;
              };
              WeakMap2.prototype.set = function(target, value) {
                var table = GetOrCreateWeakMapTable(
                  target,
                  /*create*/
                  true
                );
                table[this._key] = value;
                return this;
              };
              WeakMap2.prototype.delete = function(target) {
                var table = GetOrCreateWeakMapTable(
                  target,
                  /*create*/
                  false
                );
                return table !== void 0 ? delete table[this._key] : false;
              };
              WeakMap2.prototype.clear = function() {
                this._key = CreateUniqueKey();
              };
              return WeakMap2;
            }()
          );
          function CreateUniqueKey() {
            var key;
            do
              key = "@@WeakMap@@" + CreateUUID();
            while (HashMap.has(keys, key));
            keys[key] = true;
            return key;
          }
          function GetOrCreateWeakMapTable(target, create) {
            if (!hasOwn.call(target, rootKey)) {
              if (!create)
                return void 0;
              Object.defineProperty(target, rootKey, { value: HashMap.create() });
            }
            return target[rootKey];
          }
          function FillRandomBytes(buffer, size) {
            for (var i = 0; i < size; ++i)
              buffer[i] = Math.random() * 255 | 0;
            return buffer;
          }
          function GenRandomBytes(size) {
            if (typeof Uint8Array === "function") {
              var array = new Uint8Array(size);
              if (typeof crypto !== "undefined") {
                crypto.getRandomValues(array);
              } else if (typeof msCrypto !== "undefined") {
                msCrypto.getRandomValues(array);
              } else {
                FillRandomBytes(array, size);
              }
              return array;
            }
            return FillRandomBytes(new Array(size), size);
          }
          function CreateUUID() {
            var data = GenRandomBytes(UUID_SIZE);
            data[6] = data[6] & 79 | 64;
            data[8] = data[8] & 191 | 128;
            var result = "";
            for (var offset = 0; offset < UUID_SIZE; ++offset) {
              var byte = data[offset];
              if (offset === 4 || offset === 6 || offset === 8)
                result += "-";
              if (byte < 16)
                result += "0";
              result += byte.toString(16).toLowerCase();
            }
            return result;
          }
        }
        function MakeDictionary(obj) {
          obj.__ = void 0;
          delete obj.__;
          return obj;
        }
      });
    })(Reflect2 || (Reflect2 = {}));
  }
});

// src/compiler/standard-library/std-lib.ts
var import_reflect_metadata = __toESM(require_Reflect());

// src/compiler/compiler-interfaces/elan-type-interfaces.ts
var elanMetadataKey = Symbol("elan-metadata");
function isFunctionDescriptor(d) {
  return !!d && "isFunction" in d;
}
function isProcedureDescriptor(d) {
  return !!d && "isProcedure" in d;
}
function isConstantDescriptor(d) {
  return !!d && "isConstant" in d;
}

// 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/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/keywords.ts
var abstractKeyword = "abstract";
var classKeyword = "class";
var constructorKeyword = "constructor";
var functionKeyword = "function";
var privateKeyword = "private";
var procedureKeyword = "procedure";
var propertyKeyword = "property";
var thisKeyword = "this";
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;

// 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 ClassName = "Class";

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

// src/compiler/symbols/int-type.ts
var IntType = class _IntType {
  constructor() {
  }
  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() {
  }
  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/function-type.ts
var FunctionType = class _FunctionType {
  constructor(parameterNames, parameterTypes, returnType, isExtension, isPure, isAsync, deprecated) {
    this.parameterNames = parameterNames;
    this.parameterTypes = parameterTypes;
    this.returnType = returnType;
    this.isExtension = isExtension;
    this.isPure = isPure;
    this.isAsync = isAsync;
    this.deprecated = deprecated;
  }
  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/generic-parameter-type.ts
var GenericParameterType = class _GenericParameterType {
  constructor(id, constraint) {
    this.id = id;
    this.constraint = constraint;
  }
  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/procedure-type.ts
var ProcedureType = class {
  constructor(parameterNames, parameterTypes, isExtension, isAsync, deprecated) {
    this.parameterNames = parameterNames;
    this.parameterTypes = parameterTypes;
    this.isExtension = isExtension;
    this.isAsync = isAsync;
    this.deprecated = deprecated;
  }
  typeOptions = immutableTypeOptions;
  initialValue = "";
  get name() {
    return `Procedure (${this.parameterTypes.map((p) => p.name).join(", ")})`;
  }
  toString() {
    return `Procedure`;
  }
  isAssignableFrom(_otherType) {
    return true;
  }
};

// src/compiler/symbols/string-type.ts
var StringType = class _StringType {
  constructor() {
  }
  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;
  }
  typeOptions = immutableTypeOptions;
  get initialValue() {
    const init = this.ofTypes.map((t) => t.initialValue).join(", ");
    return `system.emptyTuple([${init}])`;
  }
  get name() {
    return `tuple(${this.ofTypes.map((t) => t.name).join(", ")})`;
  }
  toString() {
    return `tuple(${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/symbols/unknown-type.ts
var UnknownType = class _UnknownType {
  constructor() {
  }
  initialValue = "";
  typeOptions = immutableTypeOptions;
  static Instance = new _UnknownType();
  name = "Unknown";
  toString() {
    return this.name;
  }
  isAssignableFrom(_otherType) {
    return true;
  }
};

// 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";
};

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

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

// src/compiler/symbols/regexp-type.ts
var RegExpType = class _RegExpType {
  constructor() {
  }
  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 */
};
var floatSymbol = {
  symbolId: FloatType.Instance.name,
  symbolType: function() {
    return FloatType.Instance;
  },
  symbolScope: 3 /* program */
};
var stringSymbol = {
  symbolId: StringType.Instance.name,
  symbolType: function() {
    return StringType.Instance;
  },
  symbolScope: 3 /* program */
};
var booleanSymbol = {
  symbolId: BooleanType.Instance.name,
  symbolType: function() {
    return BooleanType.Instance;
  },
  symbolScope: 3 /* program */
};
var regExpSymbol = {
  symbolId: RegExpType.Instance.name,
  symbolType: function() {
    return RegExpType.Instance;
  },
  symbolScope: 3 /* program */
};
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")]
};
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")]
};

// src/compiler/symbols/null-scope.ts
var NullScope = class _NullScope {
  resolveSymbol(_id, _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 = 9 /* unknown */;
  static Instance = new _NullScope();
};

// src/compiler/syntax-nodes/ast-helpers.ts
var TypeHolder = class {
  constructor(symbolType, ofTypes) {
    this.symbolType = symbolType;
    this.ofTypes = ofTypes;
  }
  isAssignableFrom(otherType) {
    return this.symbolType.isAssignableFrom(otherType);
  }
  typeOptions = noTypeOptions;
  name = "TypeHolder";
  initialValue = "";
  toString() {
    return this.name;
  }
};
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 match = matches.get(type.id);
    if (match instanceof TypeHolder) {
      match = generateType(match.symbolType, matches, depth);
    }
    match = match ?? type;
    if (match instanceof GenericParameterType) {
      let newConstraint = void 0;
      if (match.constraint) {
        newConstraint = generateType(match.constraint, matches, depth);
      }
      if (newConstraint) {
        match = new GenericParameterType(match.id, newConstraint);
      }
    }
    return match;
  }
  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
    );
  }
  return type;
}
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 /* Pow */, "^"],
  [15 /* Or */, "or"]
]);

// src/compiler/symbols/symbol-helpers.ts
function isClass(s) {
  return !!s && "isClass" in s;
}
function isSymbol(s) {
  return !!s && "symbolId" in s && "symbolType" in s;
}
function isReifyableSymbolType(s) {
  return !!s && "reify" in s;
}
function isProperty(s) {
  return !!s && "isProperty" in s;
}
function isMember(s) {
  return !!s && "isMember" in s;
}
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);
}

// 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;
  }
  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, scope) {
    return this.scope.resolveSymbol(id, scope);
  }
  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/stdlib-class.ts
var StdLibClass = class _StdLibClass {
  constructor(name, isNotInheritable, typeOptions, children, ofTypes, inheritTypes, scope, deprecated) {
    this.name = name;
    this.isNotInheritable = isNotInheritable;
    this.typeOptions = typeOptions;
    this.children = children;
    this.ofTypes = ofTypes;
    this.inheritTypes = inheritTypes;
    this.scope = scope;
    this.deprecated = deprecated;
    this.symbolId = this.name;
  }
  get isAbstract() {
    return this.typeOptions.isAbstract;
  }
  updateOfTypes(ofTypes) {
    const newOfTypes = [...this.ofTypes];
    const lessOf = newOfTypes.length > ofTypes.length ? ofTypes.length : newOfTypes.length;
    for (let i = 0; i < lessOf; i++) {
      newOfTypes[i] = ofTypes[i];
    }
    return new _StdLibClass(
      this.name,
      this.isNotInheritable,
      this.typeOptions,
      this.children,
      newOfTypes,
      this.inheritTypes,
      this.scope,
      this.deprecated
    );
  }
  getDirectSuperClassesTypeAndName() {
    if (this.inheritTypes.length > 0) {
      const typeAndName = this.inheritTypes.filter((c) => c instanceof ClassType).map((c) => [c, c.className]);
      return typeAndName;
    }
    return [];
  }
  isClass = true;
  symbolId;
  symbolType() {
    return new ClassType(
      this.name,
      this.typeOptions.isAbstract ? 1 /* abstract */ : 0 /* concrete */,
      this.isNotInheritable,
      this.typeOptions,
      this.inheritTypes,
      this
    );
  }
  symbolScope = 2 /* stdlib */;
  getChildren() {
    return this.children;
  }
  resolveOwnSymbol(id) {
    if (id === thisKeyword) {
      return this;
    }
    const matches = this.getChildren().filter((f) => isSymbol(f) && f.symbolId === id);
    if (matches.length === 1) {
      return matches[0];
    }
    if (matches.length > 1) {
      return new DuplicateSymbol(matches);
    }
    const types = this.inheritTypes.filter((t) => t instanceof ClassType);
    for (const ct of types) {
      const s = ct.scope.resolveOwnSymbol(id);
      if (isMember(s)) {
        matches.push(s);
      }
    }
    if (matches.length === 1) {
      return matches[0];
    }
    if (matches.length > 1) {
      return new DuplicateSymbol(matches);
    }
    return new UnknownSymbol(id);
  }
  resolveSymbol(id, _scope) {
    const symbol = this.resolveOwnSymbol(id);
    if (symbol instanceof UnknownSymbol) {
      return this.getParentScope().resolveSymbol(id, this);
    }
    if (!isProperty(symbol)) {
      const st = symbol.symbolType();
      const matches = /* @__PURE__ */ new Map();
      this.ofTypes.forEach((t, i) => matches.set(`T${i + 1}`, t));
      const st1 = generateType(st, matches);
      let reifiedSymbol;
      if (isMember(symbol)) {
        reifiedSymbol = {
          symbolId: symbol.symbolId,
          symbolType: () => st1,
          symbolScope: symbol.symbolScope,
          isMember: symbol.isMember,
          private: symbol.private,
          isAbstract: symbol.isAbstract,
          getClass: symbol.getClass
        };
      } else {
        reifiedSymbol = {
          symbolId: symbol.symbolId,
          symbolType: () => st1,
          symbolScope: symbol.symbolScope
        };
      }
      return reifiedSymbol;
    }
    return symbol;
  }
  getParentScope() {
    return this.scope;
  }
  symbolMatches(id, all, _initialScope) {
    let otherMatches = this.getParentScope().symbolMatches(id, all, this);
    for (const inherited of this.inheritTypes) {
      if (inherited instanceof ClassType) {
        const m = inherited.symbolMatches(id, all);
        otherMatches = otherMatches.concat(m);
      }
    }
    const symbols = this.getChildren().filter((f) => isSymbol(f));
    const matches = symbolMatches(id, all, symbols);
    return matches.concat(otherMatches);
  }
};

// src/compiler/elan-type-annotations.ts
var nameToTypeMap = /* @__PURE__ */ new Map();
var StdLibClassCache = /* @__PURE__ */ new Map();
function stdlibClassUniqueId(name, ofTypes) {
  const fullName = [name];
  for (const st of ofTypes ?? []) {
    fullName.push(st.name);
  }
  return fullName.join("_");
}
var ElanProcedureDescriptor = class {
  constructor(isExtension = false, isAsync = false) {
    this.isExtension = isExtension;
    this.isAsync = isAsync;
  }
  isProcedure = true;
  isPure = false;
  parameterTypes = [];
  parameterNames = [];
  deprecated;
  mapType(scope) {
    const parameterTypes = this.parameterTypes;
    return new ProcedureType(
      this.parameterNames,
      parameterTypes.map((t) => t.mapType(scope)),
      this.isExtension,
      this.isAsync,
      this.deprecated
    );
  }
};
var ElanClassDescriptor = class {
  constructor(typeOptions = noTypeOptions, ofTypes = [], parameterNames = [], parameterTypes = [], inherits = [], alias) {
    this.typeOptions = typeOptions;
    this.ofTypes = ofTypes;
    this.parameterNames = parameterNames;
    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 ElanFunctionDescriptor = class {
  constructor(isExtension = false, isPure = true, isAsync = false, returnType) {
    this.isExtension = isExtension;
    this.isPure = isPure;
    this.isAsync = isAsync;
    this.returnType = returnType;
  }
  isFunction = true;
  parameterTypes = [];
  parameterNames = [];
  deprecated;
  mapType(scope) {
    const retType = this.returnType;
    const parameterTypes = this.parameterTypes;
    return new FunctionType(
      this.parameterNames,
      parameterTypes.map((t) => t.mapType(scope)),
      retType.mapType(scope),
      this.isExtension,
      this.isPure,
      this.isAsync,
      this.deprecated
    );
  }
};
var ElanSignatureDescriptor = class {
  isPure = false;
  isExtension = false;
  isAsync = false;
  parameterNames = [];
  parameterTypes = [];
  returnType;
};
var ElanValueTypeDescriptor = class {
  constructor(name, ofType, valueType) {
    this.name = name;
    this.ofType = ofType;
    this.valueType = valueType;
  }
  isConstant = 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;
    }
    throw new Error("NotImplemented: " + this.name);
  }
};
var ElanGenericTypeDescriptor = class {
  constructor(name, constraint) {
    this.name = name;
    this.constraint = constraint;
  }
  isConstant = true;
  mapType(scope) {
    return new GenericParameterType(this.name, this.constraint?.mapType(scope));
  }
};
var ElanFuncTypeDescriptor = class {
  constructor(parameters, returnType) {
    this.parameters = parameters;
    this.returnType = returnType;
  }
  isConstant = true;
  name = FuncName;
  mapType(scope) {
    return new FunctionType(
      this.parameters.map((t) => t.name),
      this.parameters.map((p) => p.mapType(scope)),
      this.returnType.mapType(scope),
      false,
      true,
      false,
      void 0
    );
  }
};
var ElanTupleTypeDescriptor = class {
  constructor(parameters) {
    this.parameters = parameters;
  }
  name = TupleName;
  isConstant = true;
  mapType(scope) {
    return new TupleType(this.parameters.map((p) => p.mapType(scope)));
  }
};
var tempMap = /* @__PURE__ */ new Map();
function removeUnderscore(name) {
  return name.startsWith("_") ? name.slice(1) : name;
}
var ElanClassTypeDescriptor = class {
  constructor(cls, ofTypes) {
    this.cls = cls;
    this.ofTypes = ofTypes;
  }
  isClass = true;
  name = ClassName;
  deprecated;
  classId(className, classMetadata) {
    const ofTypeNames = (this.ofTypes ?? classMetadata.ofTypes).map((td) => td.name).join("_");
    return `${className}_${ofTypeNames}`;
  }
  getNewClassTypeDef(classMetadata, className, scope) {
    const names = Object.getOwnPropertyNames(this.cls.prototype).concat(
      Object.getOwnPropertyNames(this.cls.emptyInstance())
    );
    const children = [];
    for (let i = 0; i < names.length; i++) {
      const name = names[i];
      const metadata = Reflect.getMetadata(elanMetadataKey, this.cls.prototype, name);
      if (name === "constructor") {
        children.push([
          `__${constructorKeyword}`,
          classMetadata.mapType(scope),
          2 /* procedure */
        ]);
      }
      if (isFunctionDescriptor(metadata)) {
        children.push([name, metadata.mapType(scope), 1 /* function */]);
      }
      if (isProcedureDescriptor(metadata)) {
        children.push([name, metadata.mapType(scope), 2 /* procedure */]);
      }
      if (isConstantDescriptor(metadata)) {
        children.push([name, metadata.mapType(scope), 0 /* property */]);
      }
    }
    const classTypeDef = new StdLibClass(
      className,
      classMetadata.typeOptions.isAbstract,
      classMetadata.typeOptions,
      [],
      [],
      [],
      scope,
      this.deprecated
    );
    for (const c of children) {
      classTypeDef.children.push(getSymbol(c[0], c[1], 6 /* member */, c[2], classTypeDef));
    }
    const actualOfTypes = this.ofTypes ?? classMetadata.ofTypes;
    for (const ot of actualOfTypes) {
      classTypeDef.ofTypes.push(ot.mapType(scope));
    }
    for (const inherits of classMetadata.inherits) {
      classTypeDef.inheritTypes.push(inherits.mapType(scope));
    }
    StdLibClassCache.set(stdlibClassUniqueId(className, this.ofTypes), classTypeDef);
    return classTypeDef;
  }
  mapType(scope) {
    const classMetadata = Reflect.getMetadata(elanMetadataKey, this.cls) ?? new ElanClassDescriptor();
    const className = classMetadata.alias ?? removeUnderscore(this.cls.name);
    const classId = this.classId(className, classMetadata);
    if (tempMap.has(classId)) {
      return tempMap.get(classId);
    }
    tempMap.set(
      classId,
      new ClassType(className, 0 /* concrete */, false, noTypeOptions, [], void 0)
    );
    const classTypeDef = StdLibClassCache.get(stdlibClassUniqueId(className, this.ofTypes)) ?? this.getNewClassTypeDef(classMetadata, className, scope);
    const classType = tempMap.get(classId);
    tempMap.delete(classId);
    return classType.updateFrom(classTypeDef.symbolType());
  }
};
var ElanClassNameTypeDescriptor = class {
  constructor(className, ofTypes) {
    this.className = className;
    this.ofTypes = ofTypes;
  }
  isClass = true;
  name = ClassName;
  mapType(scope) {
    const cls = nameToTypeMap.get(this.className);
    if (cls) {
      const td = new ElanClassTypeDescriptor(cls, this.ofTypes);
      return td.mapType(scope);
    }
    return UnknownType.Instance;
  }
};
var TypescriptTypeDescriptor = class {
  constructor(name) {
    this.name = name;
  }
  isConstant = true;
  mapType(_scope) {
    switch (this.name) {
      case "Number":
        return FloatType.Instance;
      case "String":
        return StringType.Instance;
      case "Boolean":
        return BooleanType.Instance;
      case "RegExp":
        return RegExpType.Instance;
      case "Function":
        throw new ElanCompilerError("Typescript 'Function' must be mapped into Elan types");
      case "Array":
        throw new ElanCompilerError("Typescript 'Array' must be mapped into Elan types");
    }
    throw new ElanCompilerError("Missing type annotation in stdlib class");
  }
};
function mapTypescriptType(t) {
  return new TypescriptTypeDescriptor(t.name);
}
function elanFunction(parameterNames, options, retType) {
  const flags = mapFunctionOptions(options ?? 0 /* pure */, retType);
  return elanMethod(parameterNames, new ElanFunctionDescriptor(...flags));
}
function elanProcedure(parameterNames, options) {
  const flags = mapProcedureOptions(options ?? 0 /* default */);
  return elanMethod(parameterNames, new ElanProcedureDescriptor(...flags));
}
function elanMethod(parameterNames, elanDesc) {
  return function(target, propertyKey, _descriptor) {
    const paramTypesMetadata = Reflect.getMetadata("design:paramtypes", target, propertyKey);
    const retTypeMetadata = Reflect.getMetadata("design:returntype", target, propertyKey);
    if (Array.isArray(paramTypesMetadata)) {
      elanDesc.parameterTypes = paramTypesMetadata.map((t) => mapTypescriptType(t));
    }
    if (isFunctionDescriptor(elanDesc) && !elanDesc.returnType && retTypeMetadata && retTypeMetadata.name) {
      elanDesc.returnType = new TypescriptTypeDescriptor(retTypeMetadata.name);
    }
    const metaData = Reflect.getOwnMetadata(elanMetadataKey, target, propertyKey) ?? new ElanSignatureDescriptor();
    for (let i = 0; i < elanDesc.parameterTypes.length; i++) {
      const updatedParam = metaData.parameterTypes[i];
      if (updatedParam) {
        elanDesc.parameterTypes[i] = updatedParam;
      }
    }
    for (let i = 0; i < elanDesc.parameterTypes.length; i++) {
      if (i < parameterNames.length) {
        elanDesc.parameterNames[i] = parameterNames[i];
      } else {
        elanDesc.parameterNames[i] = `parameter${i}`;
      }
    }
    Reflect.defineMetadata(elanMetadataKey, elanDesc, target, propertyKey);
  };
}
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) {
    Reflect.defineMetadata(elanMetadataKey, classDesc, target);
  };
}
function elanConstant(elanDesc) {
  return function(target, propertyKey) {
    const typeMetadata = Reflect.getMetadata("design:type", target, propertyKey);
    if (!elanDesc && typeMetadata && typeMetadata.name) {
      elanDesc = new TypescriptTypeDescriptor(typeMetadata.name);
    }
    Reflect.defineMetadata(elanMetadataKey, elanDesc, target, propertyKey);
  };
}
function elanProperty(elanDesc) {
  return function(target, propertyKey) {
    const typeMetadata = Reflect.getMetadata("design:type", target, propertyKey);
    if (!elanDesc && typeMetadata && typeMetadata.name) {
      elanDesc = new TypescriptTypeDescriptor(typeMetadata.name);
    }
    Reflect.defineMetadata(elanMetadataKey, elanDesc, target, propertyKey);
  };
}
function elanClassExport(cls) {
  nameToTypeMap.set(cls.name, cls);
  let elanDesc = ElanClass(cls);
  return function(target, propertyKey) {
    const typeMetadata = Reflect.getMetadata("design:type", target, propertyKey);
    if (!elanDesc && typeMetadata && typeMetadata.name) {
      elanDesc = new TypescriptTypeDescriptor(typeMetadata.name);
    }
    Reflect.defineMetadata(elanMetadataKey, elanDesc, target, propertyKey);
  };
}
function elanType(eType) {
  return function(target, propertyKey, parameterIndex) {
    const metaData = Reflect.getOwnMetadata(elanMetadataKey, target, propertyKey) ?? new ElanSignatureDescriptor();
    metaData.parameterTypes[parameterIndex] = eType;
    Reflect.defineMetadata(elanMetadataKey, metaData, target, propertyKey);
  };
}
function getDeprecated(reason, fromMajor, fromMinor, message) {
  return {
    reason,
    fromMajor,
    fromMinor,
    message
  };
}
function elanDeprecated(reason, fromMajor, fromMinor, message) {
  return function(target, propertyKey, propertyDescriptor) {
    if (propertyDescriptor) {
      const metaData = Reflect.getOwnMetadata(elanMetadataKey, target, propertyKey) ?? new ElanSignatureDescriptor();
      metaData.deprecated = getDeprecated(reason, fromMajor, fromMinor, message);
      Reflect.defineMetadata(elanMetadataKey, metaData, target, propertyKey);
    } else {
      const typeMetadata = Reflect.getMetadata(elanMetadataKey, target, propertyKey);
      if (typeMetadata) {
        typeMetadata.deprecated = getDeprecated(reason, fromMajor, fromMinor, message);
        Reflect.defineMetadata(elanMetadataKey, typeMetadata, target, propertyKey);
      }
    }
  };
}
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 ElanT1Constrained(constraint) {
  return new ElanGenericTypeDescriptor("T1", constraint);
}
function ElanT2Constrained(constraint) {
  return new ElanGenericTypeDescriptor("T2", constraint);
}
function ElanClass(cls, ofTypes) {
  return new ElanClassTypeDescriptor(cls, ofTypes);
}
function ElanClassName(className, _ofTypes) {
  return new ElanClassNameTypeDescriptor(className);
}
function ElanTuple(ofTypes) {
  return new ElanTupleTypeDescriptor(ofTypes);
}
function ElanFunc(parameters, returnType) {
  return new ElanFuncTypeDescriptor(parameters, returnType);
}
function elanIntType() {
  return elanType(ElanInt);
}
function elanFloatType() {
  return elanType(ElanFloat);
}
function elanStringType() {
  return elanType(ElanString);
}
function elanGenericParamT1Type(constraint) {
  return elanType(constraint ? ElanT1Constrained(constraint) : ElanT1);
}
function elanGenericParamT2Type(constraint) {
  return elanType(constraint ? ElanT2Constrained(constraint) : ElanT2);
}
function elanFuncType(parameters, returnType) {
  return elanType(ElanFunc(parameters, returnType));
}
function elanClassType(cls, ofTypes) {
  return elanType(ElanClass(cls, ofTypes));
}
function mapFunctionOptions(options, retType) {
  switch (options) {
    case 0 /* pure */:
      return [false, true, false, retType];
    case 1 /* pureExtension */:
      return [true, true, false, retType];
    case 2 /* pureAsync */:
      return [false, true, true, retType];
    case 3 /* pureAsyncExtension */:
      return [true, true, true, retType];
    case 4 /* impure */:
      return [false, false, false, retType];
    case 5 /* impureExtension */:
      return [true, false, false, retType];
    case 6 /* impureAsync */:
      return [false, false, true, retType];
    case 7 /* impureAsyncExtension */:
      return [true, false, true, retType];
  }
}
function mapProcedureOptions(options) {
  switch (options) {
    case 0 /* default */:
      return [false, false];
    case 1 /* extension */:
      return [true, false];
    case 2 /* async */:
      return [false, true];
    case 3 /* asyncExtension */:
      return [true, true];
  }
}
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 /* array */:
      opt.isIndexable = opt.isIterable = true;
      return opt;
    case 5 /* array2D */:
      opt.isDoubleIndexable = true;
      return opt;
    case 6 /* listImmutable */:
      opt.isImmutable = opt.isIndexable = opt.isIterable = true;
      return opt;
    case 7 /* dictionary */:
      opt.isIndexable = true;
      return opt;
    case 8 /* dictionaryImmutable */:
      opt.isImmutable = opt.isIndexable = true;
      return opt;
  }
}
function getSymbol(id, st, ss, mt, cls) {
  if (st instanceof ClassType) {
    return st.scope;
  }
  let symbol;
  if (ss === 6 /* member */) {
    symbol = {
      symbolId: id,
      symbolType: () => st,
      symbolScope: ss,
      isMember: true,
      private: false,
      isAbstract: false,
      getClass: () => cls
    };
  } else {
    symbol = {
      symbolId: id,
      symbolType: () => st,
      symbolScope: ss
    };
  }
  if (mt === 0 /* property */) {
    symbol["isProperty"] = true;
  }
  return symbol;
}

// src/compiler/assert-outcome.ts
var AssertOutcome = class {
  constructor(status, actual, expected, htmlId, error) {
    this.status = status;
    this.actual = actual;
    this.expected = expected;
    this.htmlId = htmlId;
    this.error = error;
  }
};

// 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;
  }
  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.printLine" ? "print" : fn;
            if (this.useLine(fn)) {
              elanStack.push(`at ${fn}`);
            }
          }
        }
      }
    }
    if (elanStack.length > 0) {
      return elanStack.join("\n");
    }
    return "";
  }
};

// src/compiler/standard-library/data-structure-helpers.ts
function checkIndex(contents, index) {
  const size = contents.length;
  if (index >= size || index < 0) {
    throw new ElanRuntimeError(`Out of range index: ${index} size: ${size}`);
  }
}
function withAppendHelper(contents, value) {
  const newList = [...contents];
  newList.push(value);
  return newList;
}
function withAppendListHelper(contents, listB) {
  const newList = [...contents];
  newList.push(...listB);
  return newList;
}
function withPutHelper(contents, index, value) {
  checkIndex(contents, index);
  const newList = [...contents];
  newList[index] = value;
  return newList;
}
function withInsertHelper(contents, index, value) {
  return contents.toSpliced(index, 0, value);
}
function withRemoveAtHelper(contents, index) {
  checkIndex(contents, index);
  return contents.toSpliced(index, 1);
}
function withRemoveFirstHelper(contents, value, system) {
  let newList = [...contents];
  const index = system.elanIndexOf(newList, value);
  if (index > -1) {
    newList = newList.toSpliced(index, 1);
  }
  return newList;
}
function withRemoveAllHelper(contents, value, system) {
  let newList = [...contents];
  let index = system.elanIndexOf(newList, value);
  while (index > -1) {
    newList = newList.toSpliced(index, 1);
    index = system.elanIndexOf(newList, value);
  }
  return newList;
}
async function filterHelper(contents, predicate) {
  const list = [...contents];
  const asyncFilter = async (list2, predicate2) => {
    const results = await Promise.all(list2.map(predicate2));
    return list2.filter((_v, index) => results[index]);
  };
  return await asyncFilter(list, predicate);
}
async function mapHelper(contents, predicate) {
  const list = [...contents];
  return await Promise.all(list.map(predicate));
}
async function reduceHelper(contents, initValue, predicate) {
  const list = [...contents];
  let acc = initValue;
  for (const i of list) {
    acc = await predicate(acc, i);
  }
  return acc;
}
async function maxByHelper(contents, predicate, system) {
  const mm = await mapHelper(contents, predicate);
  const max = Math.max(...mm);
  const i = system.elanIndexOf(mm, max);
  return contents[i];
}
async function minByHelper(contents, predicate, system) {
  const mm = await mapHelper(contents, predicate);
  const min = Math.min(...mm);
  const i = system.elanIndexOf(mm, min);
  return contents[i];
}
async function sortByHelper(contents, predicate, system) {
  const clone = [...contents];
  return await system.quickSort(clone, predicate);
}

// src/compiler/standard-library/list.ts
var List = class {
  // this must be implemented by hand on all stdlib classes
  static emptyInstance() {
    return new List();
  }
  async _initialise() {
    return this;
  }
  constructor(arr) {
    this.contents = arr ? [...arr] : [];
  }
  contents;
  system;
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.contents.length) {
          return { value: this.contents[index++], done: false };
        } else {
          return { done: true };
        }
      }
    };
  }
  read(index) {
    return this.contents[index];
  }
  put(index, value) {
    this.system.safeListSet(this.contents, index, value);
  }
  insert(index, value) {
    this.contents.splice(index, 0, value);
  }
  removeAt(index) {
    this.contents.splice(index, 1);
  }
  removeFirst(value) {
    const index = this.system.elanIndexOf(this.contents, value);
    if (index > -1) {
      this.contents.splice(index, 1);
    }
  }
  removeAll(value) {
    let index = this.system.elanIndexOf(this.contents, value);
    while (index > -1) {
      this.contents.splice(index, 1);
      index = this.system.elanIndexOf(this.contents, value);
    }
  }
  append(value) {
    this.contents.push(value);
  }
  appendList(listB) {
    this.contents.push(...listB.contents);
  }
  prepend(value) {
    this.contents.unshift(value);
  }
  prependList(listB) {
    this.contents.unshift(...listB.contents);
  }
  length() {
    return this.contents.length;
  }
  indexOf(item) {
    return this.system.elanIndexOf(this.contents, item);
  }
  contains(item) {
    return this.indexOf(item) !== -1;
  }
  newList(newContents) {
    return this.system.initialise(new List(newContents));
  }
  async filter(predicate) {
    return this.newList(await filterHelper(this.contents, predicate));
  }
  async map(predicate) {
    return this.newList(await mapHelper(this.contents, predicate));
  }
  async reduce(initValue, predicate) {
    return reduceHelper(this.contents, initValue, predicate);
  }
  async maxBy(predicate) {
    return maxByHelper(this.contents, predicate, this.system);
  }
  async minBy(predicate) {
    return minByHelper(this.contents, predicate, this.system);
  }
  async sortBy(predicate) {
    return this.newList(await sortByHelper(this.contents, predicate, this.system));
  }
  head() {
    return this.safeIndex(0);
  }
  tail() {
    const [_, ...tl] = this.contents;
    return this.system.initialise(new List(tl));
  }
  async asString() {
    const items = [];
    for (const i of this.contents) {
      const s = await this.system.asString(i);
      items.push(s);
    }
    return `[${items.join(", ")}]`;
  }
  safeIndex(index) {
    const r = this.contents[index];
    if (r === void 0) {
      this.system.throwRangeError(this.contents, index);
    }
    return r;
  }
  safeSlice(index1, index2) {
    if (index1 && index1 < 0) {
      this.system.throwRangeError(this.contents, index1);
    }
    if (index2 && index2 < 0) {
      this.system.throwRangeError(this.contents, index2);
    }
    const r = this.contents.slice(index1, index2);
    return this.system.initialise(new List(r));
  }
  deconstructList() {
    const [hd, ...tl] = this.contents;
    return [hd, this.system.initialise(new List(tl))];
  }
  equals(other) {
    if (other instanceof List) {
      if (this.contents.length === other.contents.length) {
        return this.contents.every((c, i) => this.system.equals(c, other.contents[i]));
      }
    }
    return false;
  }
  withAppend(value) {
    return this.newList(withAppendHelper(this.contents, value));
  }
  withAppendList(toAppend) {
    return this.newList(withAppendListHelper(this.contents, toAppend.contents));
  }
  withPrepend(value) {
    return this.withInsert(0, value);
  }
  withPrependList(toPrepend) {
    return toPrepend.withAppendList(this);
  }
  withPut(index, value) {
    return this.newList(withPutHelper(this.contents, index, value));
  }
  withInsert(index, value) {
    return this.newList(withInsertHelper(this.contents, index, value));
  }
  withRemoveAt(index) {
    return this.newList(withRemoveAtHelper(this.contents, index));
  }
  withRemoveFirst(value) {
    return this.newList(withRemoveFirstHelper(this.contents, value, this.system));
  }
  withRemoveAll(value) {
    return this.newList(withRemoveAllHelper(this.contents, value, this.system));
  }
  async join(separator) {
    const asStrings = await mapHelper(
      this.contents,
      async (i) => await this.system.asString(i)
    );
    return asStrings.join(separator);
  }
  asListImmutable() {
    return this.system.listAsListImmutable(this);
  }
  asSet() {
    return this.system.listAsSet(this);
  }
  asArray() {
    return this.system.listAsArray(this);
  }
};
__decorateClass([
  elanProcedure(["index", "value"]),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanGenericParamT1Type())
], List.prototype, "put", 1);
__decorateClass([
  elanProcedure(["index", "value"]),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanGenericParamT1Type())
], List.prototype, "insert", 1);
__decorateClass([
  elanProcedure(["index"]),
  __decorateParam(0, elanIntType())
], List.prototype, "removeAt", 1);
__decorateClass([
  elanProcedure(["value"]),
  __decorateParam(0, elanGenericParamT1Type())
], List.prototype, "removeFirst", 1);
__decorateClass([
  elanProcedure(["value"]),
  __decorateParam(0, elanGenericParamT1Type())
], List.prototype, "removeAll", 1);
__decorateClass([
  elanProcedure(["value"]),
  __decorateParam(0, elanGenericParamT1Type())
], List.prototype, "append", 1);
__decorateClass([
  elanProcedure(["other"]),
  __decorateParam(0, elanClassType(List, [ElanT2Constrained(ElanT1)]))
], List.prototype, "appendList", 1);
__decorateClass([
  elanProcedure(["other"]),
  __decorateParam(0, elanGenericParamT1Type())
], List.prototype, "prepend", 1);
__decorateClass([
  elanProcedure(["other"]),
  __decorateParam(0, elanClassType(List))
], List.prototype, "prependList", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanInt)
], List.prototype, "length", 1);
__decorateClass([
  elanFunction(["item"], 0 /* pure */, ElanInt),
  __decorateParam(0, elanGenericParamT1Type())
], List.prototype, "indexOf", 1);
__decorateClass([
  elanFunction(["item"], 0 /* pure */),
  __decorateParam(0, elanGenericParamT1Type())
], List.prototype, "contains", 1);
__decorateClass([
  elanFunction(["lambdaOrFunctionRef"], 2 /* pureAsync */, ElanClass(List)),
  __decorateParam(0, elanFuncType([ElanT1], ElanBoolean))
], List.prototype, "filter", 1);
__decorateClass([
  elanFunction(["lambdaOrFunctionRef"], 2 /* pureAsync */, ElanClass(List, [ElanT2])),
  __decorateParam(0, elanFuncType([ElanT1], ElanT2))
], List.prototype, "map", 1);
__decorateClass([
  elanFunction(["initialValue", "lambdaOrFunctionRef"], 2 /* pureAsync */, ElanT2),
  __decorateParam(0, elanGenericParamT2Type()),
  __decorateParam(1, elanFuncType([ElanT2, ElanT1], ElanT2))
], List.prototype, "reduce", 1);
__decorateClass([
  elanFunction(["lambdaOrFunctionRef"], 2 /* pureAsync */, ElanT1),
  __decorateParam(0, elanFuncType([ElanT1], ElanFloat))
], List.prototype, "maxBy", 1);
__decorateClass([
  elanFunction(["lambdaOrFunctionRef"], 2 /* pureAsync */, ElanT1),
  __decorateParam(0, elanFuncType([ElanT1], ElanFloat))
], List.prototype, "minBy", 1);
__decorateClass([
  elanFunction(["lambdaOrFunctionRef"], 2 /* pureAsync */, ElanClass(List)),
  __decorateParam(0, elanFuncType([ElanT1, ElanT1], ElanInt))
], List.prototype, "sortBy", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanT1)
], List.prototype, "head", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClass(List))
], List.prototype, "tail", 1);
__decorateClass([
  elanFunction(["value"], 0 /* pure */, ElanClass(List)),
  __decorateParam(0, elanGenericParamT1Type())
], List.prototype, "withAppend", 1);
__decorateClass([
  elanFunction(["toAppend"], 0 /* pure */, ElanClass(List)),
  __decorateParam(0, elanClassType(List))
], List.prototype, "withAppendList", 1);
__decorateClass([
  elanFunction(["value"], 0 /* pure */, ElanClass(List)),
  __decorateParam(0, elanGenericParamT1Type())
], List.prototype, "withPrepend", 1);
__decorateClass([
  elanFunction(["toPrepend"], 0 /* pure */, ElanClass(List)),
  __decorateParam(0, elanClassType(List))
], List.prototype, "withPrependList", 1);
__decorateClass([
  elanFunction(["index", "value"], 0 /* pure */, ElanClass(List)),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanGenericParamT1Type())
], List.prototype, "withPut", 1);
__decorateClass([
  elanFunction(["index", "value"], 0 /* pure */, ElanClass(List)),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanGenericParamT1Type())
], List.prototype, "withInsert", 1);
__decorateClass([
  elanFunction(["index"], 0 /* pure */, ElanClass(List)),
  __decorateParam(0, elanIntType())
], List.prototype, "withRemoveAt", 1);
__decorateClass([
  elanFunction(["value"], 0 /* pure */, ElanClass(List)),
  __decorateParam(0, elanGenericParamT1Type())
], List.prototype, "withRemoveFirst", 1);
__decorateClass([
  elanFunction(["value"], 0 /* pure */, ElanClass(List)),
  __decorateParam(0, elanGenericParamT1Type())
], List.prototype, "withRemoveAll", 1);
__decorateClass([
  elanFunction(["separator"], 2 /* pureAsync */, ElanString)
], List.prototype, "join", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClassName("ListImmutable"))
], List.prototype, "asListImmutable", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClassName("ElanSet"))
], List.prototype, "asSet", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClassName("ElanArray"))
], List.prototype, "asArray", 1);
List = __decorateClass([
  elanClass(3 /* list */, [ElanT1], [], [], [])
], List);

// src/compiler/standard-library/dictionary.ts
var Dictionary = class {
  // this must be implemented by hand on all stdlib classes
  static emptyInstance() {
    return new Dictionary();
  }
  async _initialise() {
    return this;
  }
  constructor(dict) {
    this.contents = dict ? new Map(dict) : /* @__PURE__ */ new Map();
  }
  contents;
  system;
  findRealKey(key) {
    for (const rk of this.contents.keys()) {
      if (this.system.equals(key, rk)) {
        return rk;
      }
    }
    return key;
  }
  removeAt(key) {
    const rk = this.findRealKey(key);
    this.contents.delete(rk);
  }
  put(key, value) {
    const rk = this.findRealKey(key);
    this.contents.set(rk, value);
  }
  keys() {
    const lst = [...this.contents.keys()];
    return this.system.initialise(new List(lst));
  }
  values() {
    const lst = [...this.contents.values()];
    return this.system.initialise(new List(lst));
  }
  hasKey(key) {
    const rk = this.findRealKey(key);
    return this.contents.has(rk);
  }
  async asString() {
    const items = [];
    for (const k of this.contents.keys()) {
      const kStr = await this.system.asString(k);
      const vStr = await this.system.asString(this.contents.get(k));
      items.push(`${kStr}:${vStr}`);
    }
    return `[${items.join(", ")}]`;
  }
  async asCloneableObject() {
    const dict = {};
    for (const k of this.contents.keys()) {
      const kStr = await this.system.asString(k);
      const v = await this.system?.asCloneableObject(this.contents.get(k));
      dict[kStr] = v;
    }
    return dict;
  }
  safeIndex(key) {
    const rk = this.findRealKey(key);
    if (!this.contents.has(rk)) {
      this.system.throwKeyError(key);
    }
    return this.contents.get(rk);
  }
  equals(other) {
    if (other instanceof Dictionary) {
      if (this.contents.size === other.contents.size) {
        return this.contents.keys().every((k) => this.system.equals(this.contents.get(k), other.contents.get(k)));
      }
    }
    return false;
  }
  withRemoveAt(key) {
    const rk = this.findRealKey(key);
    const newDict = new Map(this.contents);
    newDict.delete(rk);
    return this.system.initialise(new Dictionary([...newDict.entries()]));
  }
  withPut(key, value) {
    const rk = this.findRealKey(key);
    const newDict = new Map(this.contents);
    newDict.set(rk, value);
    return this.system.initialise(new Dictionary([...newDict.entries()]));
  }
  asDictionaryImmutable() {
    return this.system.dictionaryAsDictionaryImmutable(this);
  }
};
__decorateClass([
  elanProcedure(["key"]),
  __decorateParam(0, elanGenericParamT1Type())
], Dictionary.prototype, "removeAt", 1);
__decorateClass([
  elanProcedure(["key", "value"]),
  __decorateParam(0, elanGenericParamT1Type()),
  __decorateParam(1, elanGenericParamT2Type())
], Dictionary.prototype, "put", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClass(List, [ElanT1]))
], Dictionary.prototype, "keys", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClass(List, [ElanT2]))
], Dictionary.prototype, "values", 1);
__decorateClass([
  elanFunction(["key"], 0 /* pure */, ElanBoolean),
  __decorateParam(0, elanGenericParamT1Type())
], Dictionary.prototype, "hasKey", 1);
__decorateClass([
  elanFunction(["key"], 0 /* pure */, ElanClass(Dictionary)),
  __decorateParam(0, elanGenericParamT1Type())
], Dictionary.prototype, "withRemoveAt", 1);
__decorateClass([
  elanFunction(["key", "value"], 0 /* pure */, ElanClass(Dictionary)),
  __decorateParam(0, elanGenericParamT1Type()),
  __decorateParam(1, elanGenericParamT2Type())
], Dictionary.prototype, "withPut", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClassName("DictionaryImmutable"))
], Dictionary.prototype, "asDictionaryImmutable", 1);
Dictionary = __decorateClass([
  elanClass(7 /* dictionary */, [ElanT1, ElanT2])
], Dictionary);

// src/compiler/standard-library/list-immutable.ts
var ListImmutable = class {
  // this must be implemented by hand on all stdlib classes
  static emptyInstance() {
    return new ListImmutable();
  }
  async _initialise() {
    return this;
  }
  constructor(arr) {
    this.contents = arr ? [...arr] : [];
  }
  contents;
  system;
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.contents.length) {
          return { value: this.contents[index++], done: false };
        } else {
          return { done: true };
        }
      }
    };
  }
  newList(newContents) {
    return this.system.initialise(new ListImmutable(newContents));
  }
  withAppend(value) {
    return this.newList(withAppendHelper(this.contents, value));
  }
  withAppendList(toAppend) {
    return this.newList(withAppendListHelper(this.contents, toAppend.contents));
  }
  withPrepend(value) {
    return this.withInsert(0, value);
  }
  withPrependList(toPrepend) {
    return toPrepend.withAppendList(this);
  }
  withPut(index, value) {
    return this.newList(withPutHelper(this.contents, index, value));
  }
  withInsert(index, value) {
    return this.newList(withInsertHelper(this.contents, index, value));
  }
  withRemoveAt(index) {
    return this.newList(withRemoveAtHelper(this.contents, index));
  }
  withRemoveFirst(value) {
    return this.newList(withRemoveFirstHelper(this.contents, value, this.system));
  }
  withRemoveAll(value) {
    return this.newList(withRemoveAllHelper(this.contents, value, this.system));
  }
  length() {
    return this.contents.length;
  }
  indexOf(item) {
    return this.system.elanIndexOf(this.contents, item);
  }
  contains(item) {
    return this.indexOf(item) !== -1;
  }
  async filter(predicate) {
    return this.newList(await filterHelper(this.contents, predicate));
  }
  async map(predicate) {
    return this.newList(await mapHelper(this.contents, predicate));
  }
  async reduce(initValue, predicate) {
    return reduceHelper(this.contents, initValue, predicate);
  }
  async maxBy(predicate) {
    return maxByHelper(this.contents, predicate, this.system);
  }
  async minBy(predicate) {
    return minByHelper(this.contents, predicate, this.system);
  }
  async sortBy(predicate) {
    const arr = await sortByHelper(this.contents, predicate, this.system);
    return this.newList(arr);
  }
  head() {
    return this.safeIndex(0);
  }
  tail() {
    const [_, ...tl] = this.contents;
    return this.system.initialise(new ListImmutable(tl));
  }
  async asString() {
    const items = [];
    for (const i of this.contents) {
      const s = await this.system.asString(i);
      items.push(s);
    }
    return `{${items.join(", ")}}`;
  }
  safeIndex(index) {
    const r = this.contents[index];
    if (r === void 0) {
      this.system.throwRangeError(this.contents, index);
    }
    return r;
  }
  safeSlice(index1, index2) {
    if (index1 && index1 < 0) {
      this.system.throwRangeError(this.contents, index1);
    }
    if (index2 && index2 < 0) {
      this.system.throwRangeError(this.contents, index2);
    }
    const r = this.contents.slice(index1, index2);
    return this.system.initialise(new ListImmutable(r));
  }
  deconstructList() {
    const [hd, ...tl] = this.contents;
    return [hd, this.system.initialise(new ListImmutable(tl))];
  }
  equals(other) {
    if (other instanceof ListImmutable) {
      if (this.contents.length === other.contents.length) {
        return this.contents.every((c, i) => this.system.equals(c, other.contents[i]));
      }
    }
    return false;
  }
  async join(separator) {
    const asStrings = await mapHelper(
      this.contents,
      async (i) => await this.system.asString(i)
    );
    return asStrings.join(separator);
  }
  asList() {
    return this.system.listImmutableAsList(this);
  }
  asSet() {
    return this.system.listImmutableAsSet(this);
  }
  asArray() {
    return this.system.listImmutableAsArray(this);
  }
};
__decorateClass([
  elanFunction(["value"], 0 /* pure */, ElanClass(ListImmutable)),
  __decorateParam(0, elanGenericParamT1Type())
], ListImmutable.prototype, "withAppend", 1);
__decorateClass([
  elanFunction(["toAppend"], 0 /* pure */, ElanClass(ListImmutable)),
  __decorateParam(0, elanClassType(ListImmutable))
], ListImmutable.prototype, "withAppendList", 1);
__decorateClass([
  elanFunction(["value"], 0 /* pure */, ElanClass(ListImmutable)),
  __decorateParam(0, elanGenericParamT1Type())
], ListImmutable.prototype, "withPrepend", 1);
__decorateClass([
  elanFunction(["toPrepend"], 0 /* pure */, ElanClass(ListImmutable)),
  __decorateParam(0, elanClassType(ListImmutable))
], ListImmutable.prototype, "withPrependList", 1);
__decorateClass([
  elanFunction(["index", "value"], 0 /* pure */, ElanClass(ListImmutable)),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanGenericParamT1Type())
], ListImmutable.prototype, "withPut", 1);
__decorateClass([
  elanFunction(["index", "value"], 0 /* pure */, ElanClass(ListImmutable)),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanGenericParamT1Type())
], ListImmutable.prototype, "withInsert", 1);
__decorateClass([
  elanFunction(["index"], 0 /* pure */, ElanClass(ListImmutable)),
  __decorateParam(0, elanIntType())
], ListImmutable.prototype, "withRemoveAt", 1);
__decorateClass([
  elanFunction(["value"], 0 /* pure */, ElanClass(ListImmutable)),
  __decorateParam(0, elanGenericParamT1Type())
], ListImmutable.prototype, "withRemoveFirst", 1);
__decorateClass([
  elanFunction(["value"], 0 /* pure */, ElanClass(ListImmutable)),
  __decorateParam(0, elanGenericParamT1Type())
], ListImmutable.prototype, "withRemoveAll", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanInt)
], ListImmutable.prototype, "length", 1);
__decorateClass([
  elanFunction(["item"], 0 /* pure */, ElanInt),
  __decorateParam(0, elanGenericParamT1Type())
], ListImmutable.prototype, "indexOf", 1);
__decorateClass([
  elanFunction(["item"], 0 /* pure */),
  __decorateParam(0, elanGenericParamT1Type())
], ListImmutable.prototype, "contains", 1);
__decorateClass([
  elanFunction(["lambdaOrFunctionRef"], 2 /* pureAsync */, ElanClass(ListImmutable)),
  __decorateParam(0, elanFuncType([ElanT1], ElanBoolean))
], ListImmutable.prototype, "filter", 1);
__decorateClass([
  elanFunction(
    ["lambdaOrFunctionRef"],
    2 /* pureAsync */,
    ElanClass(ListImmutable, [ElanT2])
  ),
  __decorateParam(0, elanFuncType([ElanT1], ElanT2))
], ListImmutable.prototype, "map", 1);
__decorateClass([
  elanFunction(["initialValue", "lambdaOrFunctionRef"], 2 /* pureAsync */, ElanT2),
  __decorateParam(0, elanGenericParamT2Type()),
  __decorateParam(1, elanFuncType([ElanT2, ElanT1], ElanT2))
], ListImmutable.prototype, "reduce", 1);
__decorateClass([
  elanFunction(["lambdaOrFunctionRef"], 2 /* pureAsync */, ElanT1),
  __decorateParam(0, elanFuncType([ElanT1], ElanFloat))
], ListImmutable.prototype, "maxBy", 1);
__decorateClass([
  elanFunction(["lambdaOrFunctionRef"], 2 /* pureAsync */, ElanT1),
  __decorateParam(0, elanFuncType([ElanT1], ElanFloat))
], ListImmutable.prototype, "minBy", 1);
__decorateClass([
  elanFunction(["lambdaOrFunctionRef"], 2 /* pureAsync */, ElanClass(ListImmutable)),
  __decorateParam(0, elanFuncType([ElanT1, ElanT1], ElanInt))
], ListImmutable.prototype, "sortBy", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanT1)
], ListImmutable.prototype, "head", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClass(ListImmutable))
], ListImmutable.prototype, "tail", 1);
__decorateClass([
  elanFunction(["separator"], 2 /* pureAsync */, ElanString)
], ListImmutable.prototype, "join", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClassName("List"))
], ListImmutable.prototype, "asList", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClassName("ElanSet"))
], ListImmutable.prototype, "asSet", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClassName("ElanArray"))
], ListImmutable.prototype, "asArray", 1);
ListImmutable = __decorateClass([
  elanClass(6 /* listImmutable */, [ElanT1], [], [], [])
], ListImmutable);

// src/compiler/standard-library/dictionary-immutable.ts
var DictionaryImmutable = class {
  // this must be implemented by hand on all stdlib classes
  static emptyInstance() {
    return new DictionaryImmutable();
  }
  async _initialise() {
    return this;
  }
  constructor(dict) {
    this.contents = dict ? new Map(dict) : /* @__PURE__ */ new Map();
  }
  contents;
  system;
  findRealKey(key) {
    for (const rk of this.contents.keys()) {
      if (this.system.equals(key, rk)) {
        return rk;
      }
    }
    return key;
  }
  withRemoveAt(key) {
    const rk = this.findRealKey(key);
    const newDict = new Map(this.contents);
    newDict.delete(rk);
    return this.system.initialise(new DictionaryImmutable([...newDict.entries()]));
  }
  withPut(key, value) {
    const rk = this.findRealKey(key);
    const newDict = new Map(this.contents);
    newDict.set(rk, value);
    return this.system.initialise(new DictionaryImmutable([...newDict.entries()]));
  }
  keys() {
    const lst = [...this.contents.keys()];
    return this.system.initialise(new ListImmutable(lst));
  }
  values() {
    const lst = [...this.contents.values()];
    return this.system.initialise(new ListImmutable(lst));
  }
  hasKey(key) {
    const rk = this.findRealKey(key);
    return this.contents.has(rk);
  }
  asDictionary() {
    return this.system.dictionaryImmutableAsDictionary(this);
  }
  async asString() {
    const items = [];
    for (const k of this.contents.keys()) {
      const kStr = await this.system.asString(k);
      const vStr = await this.system.asString(this.contents.get(k));
      items.push(`${kStr}:${vStr}`);
    }
    return `{${items.join(", ")}}`;
  }
  async asCloneableObject() {
    const dict = {};
    for (const k of this.contents.keys()) {
      const kStr = await this.system.asString(k);
      const v = await this.system?.asCloneableObject(this.contents.get(k));
      dict[kStr] = v;
    }
    return dict;
  }
  safeIndex(key) {
    const rk = this.findRealKey(key);
    if (!this.contents.has(rk)) {
      this.system.throwKeyError(key);
    }
    return this.contents.get(rk);
  }
  equals(other) {
    if (other instanceof DictionaryImmutable) {
      if (this.contents.size === other.contents.size) {
        return this.contents.keys().every((k) => this.system.equals(this.contents.get(k), other.contents.get(k)));
      }
    }
    return false;
  }
};
__decorateClass([
  elanFunction(["key"], 0 /* pure */, ElanClass(DictionaryImmutable)),
  __decorateParam(0, elanGenericParamT1Type())
], DictionaryImmutable.prototype, "withRemoveAt", 1);
__decorateClass([
  elanFunction(["key", "value"], 0 /* pure */, ElanClass(DictionaryImmutable)),
  __decorateParam(0, elanGenericParamT1Type()),
  __decorateParam(1, elanGenericParamT2Type())
], DictionaryImmutable.prototype, "withPut", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClass(ListImmutable, [ElanT1]))
], DictionaryImmutable.prototype, "keys", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClass(ListImmutable, [ElanT2]))
], DictionaryImmutable.prototype, "values", 1);
__decorateClass([
  elanFunction(["key"], 0 /* pure */, ElanBoolean),
  __decorateParam(0, elanGenericParamT1Type())
], DictionaryImmutable.prototype, "hasKey", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClassName("Dictionary"))
], DictionaryImmutable.prototype, "asDictionary", 1);
DictionaryImmutable = __decorateClass([
  elanClass(8 /* dictionaryImmutable */, [ElanT1, ElanT2])
], DictionaryImmutable);

// src/compiler/standard-library/elan-array.ts
var ElanArray = class {
  // this must be implemented by hand on all stdlib classes
  static emptyInstance() {
    return new ElanArray();
  }
  async _initialise(size, value) {
    if (size <= 0) {
      throw new ElanRuntimeError(`Size of Array must be non zero, positive value`);
    }
    if (!(typeof value === "boolean" || typeof value === "string" || typeof value === "number")) {
      throw new ElanRuntimeError(
        `Array must be of Type: Int, Float, String, or Boolean, with matching initial value`
      );
    }
    const toInit = [];
    toInit.length = size;
    for (let i = 0; i < size; i++) {
      toInit[i] = value;
    }
    this.contents = toInit;
    return this;
  }
  constructor(arr) {
    this.contents = arr ? [...arr] : [];
  }
  contents;
  system;
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.contents.length) {
          return { value: this.contents[index++], done: false };
        } else {
          return { done: true };
        }
      }
    };
  }
  newArray(newContents) {
    return this.system.initialise(new ElanArray(newContents));
  }
  put(index, value) {
    this.system.safeListSet(this.contents, index, value);
  }
  withPut(index, value) {
    return this.newArray(withPutHelper(this.contents, index, value));
  }
  length() {
    return this.contents.length;
  }
  indexOf(item) {
    return this.system.elanIndexOf(this.contents, item);
  }
  contains(item) {
    return this.indexOf(item) !== -1;
  }
  async asString() {
    const items = [];
    for (const i of this.contents) {
      const s = await this.system.asString(i);
      items.push(s);
    }
    return `[${items.join(", ")}]`;
  }
  safeIndex(index) {
    const r = this.contents[index];
    if (r === void 0) {
      this.system.throwRangeError(this.contents, index);
    }
    return r;
  }
  safeSlice(index1, index2) {
    if (index1 && index1 < 0) {
      this.system.throwRangeError(this.contents, index1);
    }
    if (index2 && index2 < 0) {
      this.system.throwRangeError(this.contents, index2);
    }
    const r = this.contents.slice(index1, index2);
    return this.system.initialise(new ElanArray(r));
  }
  equals(other) {
    if (other instanceof ElanArray) {
      if (this.contents.length === other.contents.length) {
        return this.contents.every((c, i) => this.system.equals(c, other.contents[i]));
      }
    }
    return false;
  }
  asSet() {
    return this.system.arrayAsSet(this);
  }
  asList() {
    return this.system.arrayAsList(this);
  }
};
__decorateClass([
  elanProcedure(["index", "value"]),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanGenericParamT1Type())
], ElanArray.prototype, "put", 1);
__decorateClass([
  elanFunction(["index", "value"], 0 /* pure */, ElanClass(ElanArray)),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanGenericParamT1Type())
], ElanArray.prototype, "withPut", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanInt)
], ElanArray.prototype, "length", 1);
__decorateClass([
  elanFunction(["item"], 0 /* pure */, ElanInt),
  __decorateParam(0, elanGenericParamT1Type())
], ElanArray.prototype, "indexOf", 1);
__decorateClass([
  elanFunction(["item"], 0 /* pure */),
  __decorateParam(0, elanGenericParamT1Type())
], ElanArray.prototype, "contains", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClassName("ElanSet"))
], ElanArray.prototype, "asSet", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClassName("List"))
], ElanArray.prototype, "asList", 1);
ElanArray = __decorateClass([
  elanClass(4 /* array */, [ElanT1], ["size", "initialValue"], [ElanInt, ElanT1], [], "Array")
], ElanArray);

// src/compiler/standard-library/elan-set.ts
var ElanSet = class {
  // this must be implemented by hand on all stdlib classes
  static emptyInstance() {
    return new ElanSet();
  }
  async _initialise() {
    return this;
  }
  _system;
  set system(value) {
    this._system = value;
  }
  get system() {
    return this._system;
  }
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  stdlib;
  // injected
  constructor(arr) {
    this.contents = arr ? new Set(arr) : /* @__PURE__ */ new Set();
  }
  contents;
  copyOfThis() {
    const copy = this.system.initialise(new ElanSet());
    copy.contents = new Set(this.contents);
    return copy;
  }
  length() {
    return this.contents.size;
  }
  contains(item) {
    return this.contents.has(item);
  }
  add(item) {
    const copy = this.copyOfThis();
    copy.contents.add(item);
    return copy;
  }
  addFromList(list) {
    const copy = this.copyOfThis();
    for (const item of list) {
      copy.contents.add(item);
    }
    return copy;
  }
  remove(item) {
    const copy = this.copyOfThis();
    copy.contents.delete(item);
    return copy;
  }
  union(other) {
    const copy = this.copyOfThis();
    copy.contents = this.contents.union(other.contents);
    return copy;
  }
  difference(other) {
    const copy = this.copyOfThis();
    copy.contents = this.contents.difference(other.contents);
    return copy;
  }
  intersection(other) {
    const copy = this.copyOfThis();
    copy.contents = this.contents.intersection(other.contents);
    return copy;
  }
  isDisjointFrom(other) {
    return this.contents.isDisjointFrom(other.contents);
  }
  isSubsetOf(other) {
    return this.contents.isSubsetOf(other.contents);
  }
  isSupersetOf(other) {
    return this.contents.isSupersetOf(other.contents);
  }
  asList() {
    return this.system.initialise(new List(Array.from(this.contents)));
  }
  async asString() {
    const listImm = this.system.initialise(new ListImmutable(Array.from(this.contents)));
    return await this.stdlib.asString(listImm);
  }
};
__decorateClass([
  elanFunction([], 0 /* pure */, ElanInt)
], ElanSet.prototype, "length", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanBoolean),
  __decorateParam(0, elanGenericParamT1Type())
], ElanSet.prototype, "contains", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClass(ElanSet)),
  __decorateParam(0, elanGenericParamT1Type())
], ElanSet.prototype, "add", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClass(ElanSet)),
  __decorateParam(0, elanClassType(List))
], ElanSet.prototype, "addFromList", 1);
__decorateClass([
  elanFunction([], 4 /* impure */, ElanClass(ElanSet)),
  __decorateParam(0, elanGenericParamT1Type())
], ElanSet.prototype, "remove", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClass(ElanSet)),
  __decorateParam(0, elanClassType(ElanSet))
], ElanSet.prototype, "union", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClass(ElanSet)),
  __decorateParam(0, elanClassType(ElanSet))
], ElanSet.prototype, "difference", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClass(ElanSet)),
  __decorateParam(0, elanClassType(ElanSet))
], ElanSet.prototype, "intersection", 1);
__decorateClass([
  elanFunction([], 0 /* pure */),
  __decorateParam(0, elanClassType(ElanSet))
], ElanSet.prototype, "isDisjointFrom", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanBoolean),
  __decorateParam(0, elanClassType(ElanSet))
], ElanSet.prototype, "isSubsetOf", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanBoolean),
  __decorateParam(0, elanClassType(ElanSet))
], ElanSet.prototype, "isSupersetOf", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClass(List))
], ElanSet.prototype, "asList", 1);
__decorateClass([
  elanFunction([], 2 /* pureAsync */, ElanString)
], ElanSet.prototype, "asString", 1);
ElanSet = __decorateClass([
  elanClass(2 /* record */, [ElanT1], [], [], [], "Set")
], ElanSet);

// src/compiler/system.ts
var System = class {
  constructor(elanInputOutput) {
    this.elanInputOutput = elanInputOutput;
  }
  _stdlib;
  set stdlib(stdlib) {
    this._stdlib = stdlib;
  }
  // constant immutables
  emptyImmutableListSingleton = this.initialise(new ListImmutable([]));
  emptyDictionaryImmutableSingleton = this.dictionaryImmutable([]);
  emptyRegExpSingleton = /(?:)/;
  emptyRegExp() {
    return this.emptyRegExpSingleton;
  }
  emptyTuple(toInit) {
    const t = [...toInit];
    return this.tuple(t);
  }
  emptyFunc(rt) {
    return () => rt;
  }
  tuple(t) {
    return t;
  }
  listImmutable(t) {
    return this.initialise(new ListImmutable(t));
  }
  dictionary(t) {
    return this.initialise(new Dictionary(t));
  }
  dictionaryImmutable(t) {
    return this.initialise(new DictionaryImmutable(t));
  }
  list(t) {
    return this.initialise(new List(t));
  }
  initialise(toInit) {
    if ("system" in toInit) {
      toInit.system = this;
    }
    if ("stdlib" in toInit) {
      toInit.stdlib = this._stdlib;
    }
    return toInit;
  }
  emptyClass(type, properties) {
    const t = Object.create(type.prototype);
    for (const p of properties) {
      t[p[0]] = p[1];
    }
    return t;
  }
  safeIndex(indexable, index1, index2) {
    if (typeof indexable !== "string" && "safeIndex" in indexable) {
      return indexable.safeIndex(index1, index2);
    }
    if (indexable === void 0) {
      throw new ElanRuntimeError(`Out of range index`);
    }
    const r = indexable[index1];
    if (r === void 0) {
      this.throwRangeError(indexable, index1);
    }
    return r;
  }
  safeSlice(indexable, index1, index2) {
    if (indexable === void 0) {
      throw new ElanRuntimeError(`Out of range index`);
    }
    if (typeof indexable !== "string" && "safeSlice" in indexable) {
      return indexable.safeSlice(index1, index2);
    }
    if (typeof indexable !== "string") {
      throw new ElanRuntimeError(`Out of range index`);
    }
    if (index1 && index1 < 0) {
      this.throwRangeError(indexable, index1);
    }
    if (index2 && index2 < 0) {
      this.throwRangeError(indexable, index2);
    }
    return indexable.slice(index1, index2);
  }
  throwRangeError(toIndex, index) {
    const size = toIndex.length;
    if (size !== void 0) {
      throw new ElanRuntimeError(`Out of range index: ${index} size: ${size}`);
    }
    throw new ElanRuntimeError(`No such key: ${index}`);
  }
  throwKeyError(index) {
    throw new ElanRuntimeError(`No such key: ${index}`);
  }
  safeListSet(toIndex, index, value) {
    const size = toIndex.length;
    if (index >= size) {
      throw new ElanRuntimeError(`Out of range index: ${index} size: ${size}`);
    }
    toIndex[index] = value;
  }
  safeArray2DSet(toIndex, col, row, value) {
    const size = toIndex.length;
    if (col >= size) {
      throw new ElanRuntimeError(`Out of range index: ${col} size: ${size}`);
    }
    this.safeListSet(toIndex[col], row, value);
  }
  async printLine(s) {
    const ss = await this._stdlib.asString(s);
    await this.elanInputOutput.printLine(ss);
  }
  async input() {
    return await this.elanInputOutput.readLine();
  }
  equals(i1, i2) {
    const t = typeof i1;
    if (t === "boolean" || t === "string" || t === "number") {
      return i1 === i2;
    }
    return this.objectEquals(i1, i2);
  }
  objectEquals(o1, o2) {
    if (o1 === o2) {
      return true;
    }
    if (o1?.constructor?.name !== o2?.constructor?.name) {
      return false;
    }
    if (o1?.constructor?.name === o2?.constructor?.name && o2?.constructor?.name === "Function") {
      return false;
    }
    if ("equals" in o1) {
      return o1.equals(o2);
    }
    const o1items = Object.getOwnPropertyNames(o1);
    const o2items = Object.getOwnPropertyNames(o2);
    if (o1items.length !== o2items.length) {
      return false;
    }
    if (o1items.join() !== o2items.join()) {
      return false;
    }
    for (const i of o1items.filter((i2) => !i2.startsWith("_"))) {
      if (!this.equals(o1[i], o2[i])) {
        return false;
      }
    }
    if (o1 instanceof Set) {
      return o1.size === o2.size && o1.isSubsetOf(o2);
    }
    return true;
  }
  async assert(actual, expected, htmlId, stdlib, ignored) {
    if (ignored) {
      return new AssertOutcome(2 /* ignored */, "", "", htmlId);
    }
    try {
      const actualValue = await actual[0]();
      return await this.doAssert(actualValue, expected[0], actual[1], expected[1], htmlId, stdlib);
    } catch (err) {
      return await this.doAssert(
        err.message,
        expected[0],
        "String",
        "String",
        htmlId,
        stdlib
      );
    }
  }
  async doAssert(actual, expected, actualSt, expectedSt, htmlId, stdlib) {
    let testStatus = 4 /* pass */;
    const expectedValue = `${await stdlib.asString(expected)}`;
    let actualValue = `${await stdlib.asString(actual)}`;
    if (!this.equals(actual, expected)) {
      testStatus = 1 /* fail */;
      if (actualSt !== expectedSt) {
        actualValue = `${actualSt} expected: ${expectedSt}`;
      }
    }
    return new AssertOutcome(testStatus, actualValue, expectedValue, htmlId);
  }
  deconstructList(list) {
    return list.deconstructList();
  }
  unhandledExpression(v) {
    const s = this._stdlib.asString(v);
    throw new ElanRuntimeError(`'${s}' not covered in switch statement`);
  }
  async runTests(tests) {
    const allOutcomes = [];
    for (const t of tests) {
      const outcomes = [];
      const testId = t[0];
      try {
        await t[1](outcomes);
      } catch (e) {
        const msg = e.message || "Test threw error";
        outcomes.push(new AssertOutcome(0 /* error */, msg, "", "", e));
      }
      allOutcomes.push([testId, outcomes]);
    }
    tests.length = 0;
    return allOutcomes;
  }
  ignoredProperty(s) {
    return s === "system" || s === "stdlib" || s.startsWith("_");
  }
  async asCloneableObject(v) {
    if (typeof v === "boolean" || typeof v === "string" || typeof v === "number") {
      return v;
    }
    if (v instanceof RegExp) {
      return `/${v.source}/`;
    }
    if ("asCloneableObject" in v) {
      return await v.asCloneableObject();
    }
    if (typeof v[Symbol.iterator] === "function") {
      const arr = [];
      for (const o of v) {
        arr.push(await this.asCloneableObject(o));
      }
      return arr;
    }
    const getters = [];
    const proto = Object.getPrototypeOf(v);
    const descriptors = Object.getOwnPropertyDescriptors(proto);
    const dKeys = Object.keys(descriptors);
    for (const d of dKeys) {
      const dd = descriptors[d];
      const isGet = dd.get;
      if (isGet) {
        getters.push(d);
      }
    }
    const clone = {};
    const keys = Object.keys(v).filter((k) => !this.ignoredProperty(k));
    const keySet = new Set(keys.concat(getters));
    for (const k of keySet) {
      clone[k] = await this.asCloneableObject(v[k]);
    }
    return clone;
  }
  async debugSymbol(id, symbol, typeMap) {
    const asCloneable = await this.asCloneableObject(symbol);
    try {
      return {
        name: id,
        value: asCloneable,
        typeMap
      };
    } catch (_e) {
      return "error resolving";
    }
  }
  elanIndexOf(list, elem) {
    for (let i = 0; i < list.length; i++) {
      const item = list[i];
      if (this.equals(item, elem)) {
        return i;
      }
    }
    return -1;
  }
  elan2DIndexOf(list, elem) {
    for (let i = 0; i < list.length; i++) {
      const subArr = list[i];
      for (let j = 0; j < subArr.length; j++) {
        const item = subArr[j];
        if (this.equals(item, elem)) {
          return [i, j];
        }
      }
    }
    return [-1, -1];
  }
  async asString(a) {
    return await this._stdlib.asString(a);
  }
  async breakPoint(allScopedSymbols2, id, singlestep, pause) {
    if (singlestep && !pause) {
      return false;
    }
    return await this.elanInputOutput.breakPoint(allScopedSymbols2, id, singlestep);
  }
  async getPivot(x, y, z, compare) {
    if (await compare(x, y) < 0) {
      if (await compare(y, z) < 0) {
        return y;
      } else if (await compare(z, x) < 0) {
        return x;
      } else {
        return z;
      }
    } else if (await compare(y, z) > 0) {
      return y;
    } else if (await compare(z, x) > 0) {
      return x;
    } else {
      return z;
    }
  }
  // from github https://gist.github.com/kimamula/fa34190db624239111bbe0deba72a6ab
  async quickSort(arr, compare, left = 0, right = arr.length - 1) {
    if (left < right) {
      let i = left, j = right, tmp;
      const pivot = await this.getPivot(arr[i], arr[i + Math.floor((j - i) / 2)], arr[j], compare);
      while (true) {
        while (await compare(arr[i], pivot) < 0) {
          i++;
        }
        while (await compare(pivot, arr[j]) < 0) {
          j--;
        }
        if (i >= j) {
          break;
        }
        tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
        i++;
        j--;
      }
      await this.quickSort(arr, compare, left, i - 1);
      await this.quickSort(arr, compare, j + 1, right);
    }
    return arr;
  }
  listImmutableAsList(list) {
    const newList = [...list];
    return this.initialise(new List(newList));
  }
  listImmutableAsSet(list) {
    const newList = [...list];
    return this.initialise(new ElanSet(newList));
  }
  listImmutableAsArray(list) {
    const newList = [...list];
    return this.initialise(new ElanArray(newList));
  }
  listAsListImmutable(list) {
    const newList = [...list];
    return this.initialise(new ListImmutable(newList));
  }
  listAsSet(list) {
    const newList = [...list];
    return this.initialise(new ElanSet(newList));
  }
  listAsArray(list) {
    const newList = [...list];
    return this.initialise(new ElanArray(newList));
  }
  arrayAsListImmutable(list) {
    const newList = [...list];
    return this.initialise(new ListImmutable(newList));
  }
  arrayAsSet(list) {
    const newList = [...list];
    return this.initialise(new ElanSet(newList));
  }
  arrayAsList(list) {
    const newList = [...list];
    return this.initialise(new List(newList));
  }
  dictionaryAsDictionaryImmutable(dictionary) {
    return this.initialise(new DictionaryImmutable([...dictionary.contents.entries()]));
  }
  dictionaryImmutableAsDictionary(dictionary) {
    return this.initialise(new Dictionary([...dictionary.contents.entries()]));
  }
};

// src/compiler/standard-library/vector-graphic.ts
var VectorGraphic = class {
  // this must be implemented by hand on all stdlib classes
  static emptyInstance() {
    return new VectorGraphic();
  }
  asSVG() {
    return "";
  }
  asColour(colour) {
    if (colour > 16777215 || colour < 0) {
      throw new ElanRuntimeError(`colour must be in the range 0x0 to 0xffffff (0 to 16777215)`);
    }
    const hex = `000000${colour.toString(16)}`;
    const rgb = hex.substring(hex.length - 6, hex.length);
    return `#${rgb}`;
  }
  strokeColourAsHex(strokeColour) {
    if (strokeColour < 0) {
      throw new ElanRuntimeError(`strokeColour cannot be transparent (negative value)`);
    }
    return this.asColour(strokeColour);
  }
  fillColourAsHex(fillColour) {
    let colour = "";
    if (fillColour < 0) {
      colour = "none";
    } else {
      colour = this.asColour(fillColour);
    }
    return colour;
  }
  strokeAsHtml(strokeWidth, strokeColour) {
    return `stroke="${this.strokeColourAsHex(strokeColour)}" stroke-width="${strokeWidth * 0.3}%"`;
  }
  fillAsHtml(fillColour) {
    return `fill="${this.fillColourAsHex(fillColour)}"`;
  }
};
__decorateClass([
  elanFunction([], 0 /* pure */)
], VectorGraphic.prototype, "asSVG", 1);
VectorGraphic = __decorateClass([
  elanClass(1 /* abstract */)
], VectorGraphic);

// src/compiler/standard-library/circle-vg.ts
var CircleVG = class extends VectorGraphic {
  static emptyInstance() {
    return new CircleVG();
  }
  async _initialise() {
    return this;
  }
  system;
  constructor(copy) {
    super();
    this.centreX = copy ? copy.centreX : 50;
    this.centreY = copy ? copy.centreY : 37.5;
    this.radius = copy ? copy.radius : 10;
    this.fillColour = copy ? copy.fillColour : 16776960;
    this.strokeColour = copy ? copy.strokeColour : 0;
    this.strokeWidth = copy ? copy.strokeWidth : 1;
  }
  centreX = 0;
  setCentreX(centreX) {
    this.centreX = centreX;
  }
  withCentreX(centreX) {
    const copy = this.system.initialise(new CircleVG(this));
    copy.centreX = centreX;
    return copy;
  }
  centreY = 0;
  setCentreY(centreY) {
    this.centreY = centreY;
  }
  withCentreY(centreY) {
    const copy = this.system.initialise(new CircleVG(this));
    copy.centreY = centreY;
    return copy;
  }
  radius = 0;
  setRadius(r) {
    this.radius = r;
  }
  withRadius(r) {
    const copy = this.system.initialise(new CircleVG(this));
    copy.radius = r;
    return copy;
  }
  strokeColour = 0;
  setStrokeColour(strokeColour) {
    this.strokeColour = strokeColour;
  }
  withStrokeColour(strokeColour) {
    const copy = this.system.initialise(new CircleVG(this));
    copy.strokeColour = strokeColour;
    return copy;
  }
  strokeWidth = 0;
  setStrokeWidth(strokeWidth) {
    this.strokeWidth = strokeWidth;
  }
  withStrokeWidth(strokeWidth) {
    const copy = this.system.initialise(new CircleVG(this));
    copy.strokeWidth = strokeWidth;
    return copy;
  }
  fillColour = 0;
  setFillColour(fillColour) {
    this.fillColour = fillColour;
  }
  withFillColour(fillColour) {
    const copy = this.system.initialise(new CircleVG(this));
    copy.fillColour = fillColour;
    return copy;
  }
  asSVG() {
    return `<circle cx="${this.centreX}%" cy="${this.centreY / 0.75}%" r="${this.radius * 1.125}%" ${this.strokeAsHtml(this.strokeWidth, this.strokeColour)} ${this.fillAsHtml(this.fillColour)}/>`;
  }
};
__decorateClass([
  elanProperty()
], CircleVG.prototype, "centreX", 2);
__decorateClass([
  elanProcedure(["centreX"])
], CircleVG.prototype, "setCentreX", 1);
__decorateClass([
  elanFunction(["centreX"], 0 /* pure */, ElanClass(CircleVG))
], CircleVG.prototype, "withCentreX", 1);
__decorateClass([
  elanProperty()
], CircleVG.prototype, "centreY", 2);
__decorateClass([
  elanProcedure(["centreY"])
], CircleVG.prototype, "setCentreY", 1);
__decorateClass([
  elanFunction(["centreY"], 0 /* pure */, ElanClass(CircleVG))
], CircleVG.prototype, "withCentreY", 1);
__decorateClass([
  elanProperty()
], CircleVG.prototype, "radius", 2);
__decorateClass([
  elanProcedure(["radius"])
], CircleVG.prototype, "setRadius", 1);
__decorateClass([
  elanFunction(["radius"], 0 /* pure */, ElanClass(CircleVG))
], CircleVG.prototype, "withRadius", 1);
__decorateClass([
  elanProperty(ElanInt)
], CircleVG.prototype, "strokeColour", 2);
__decorateClass([
  elanProcedure(["colour"])
], CircleVG.prototype, "setStrokeColour", 1);
__decorateClass([
  elanFunction(["colour"], 0 /* pure */, ElanClass(CircleVG))
], CircleVG.prototype, "withStrokeColour", 1);
__decorateClass([
  elanProperty()
], CircleVG.prototype, "strokeWidth", 2);
__decorateClass([
  elanProcedure(["strokeWidth"])
], CircleVG.prototype, "setStrokeWidth", 1);
__decorateClass([
  elanFunction(["width"], 0 /* pure */, ElanClass(CircleVG))
], CircleVG.prototype, "withStrokeWidth", 1);
__decorateClass([
  elanProperty(ElanInt)
], CircleVG.prototype, "fillColour", 2);
__decorateClass([
  elanProcedure(["fillColour"])
], CircleVG.prototype, "setFillColour", 1);
__decorateClass([
  elanFunction(["colour"], 0 /* pure */, ElanClass(CircleVG))
], CircleVG.prototype, "withFillColour", 1);
__decorateClass([
  elanFunction([], 0 /* pure */)
], CircleVG.prototype, "asSVG", 1);
CircleVG = __decorateClass([
  elanClass(0 /* concrete */, [], [], [], [ElanClass(VectorGraphic)])
], CircleVG);

// src/compiler/standard-library/elan-array-2d.ts
var ElanArray2D = class {
  // this must be implemented by hand on all stdlib classes
  static emptyInstance() {
    return new ElanArray2D();
  }
  async _initialise(x, y, value) {
    if (x <= 0 || y <= 0) {
      throw new ElanRuntimeError(`Each dimension of Array2D must be non zero, positive value`);
    }
    if (!(typeof value === "boolean" || typeof value === "string" || typeof value === "number")) {
      throw new ElanRuntimeError(
        `Array2D must be of Type: Int, Float, String, or Boolean, with matching initial value`
      );
    }
    const toInit = [];
    toInit.length = x;
    for (let i = 0; i < x; i++) {
      const subArr = [];
      subArr.length = y;
      for (let j = 0; j < y; j++) {
        subArr[j] = value;
      }
      toInit[i] = subArr;
    }
    this.contents = toInit;
    return this;
  }
  constructor(arr) {
    this.contents = arr ? [...arr] : [];
  }
  contents;
  read(x, y) {
    return this.contents[x][y];
  }
  system;
  put(col, row, value) {
    this.system.safeArray2DSet(this.contents, col, row, value);
  }
  withPut(col, row, value) {
    const newList = [];
    for (const column of this.contents) {
      const newCol = [...column];
      newList.push(newCol);
    }
    this.system.safeArray2DSet(newList, col, row, value);
    return this.system.initialise(new ElanArray2D(newList));
  }
  columns() {
    return this.contents.length;
  }
  rows() {
    return this.contents[0].length;
  }
  indexOf(item) {
    return this.system.tuple(this.system.elan2DIndexOf(this.contents, item));
  }
  contains(item) {
    const [i, _] = this.system.elan2DIndexOf(this.contents, item);
    return i !== -1;
  }
  async asString() {
    const columns = [];
    for (const column of this.contents) {
      const rows = [];
      for (const row of column) {
        const s = await this.system.asString(row);
        rows.push(s);
      }
      columns.push(`[${rows.join(", ")}]`);
    }
    return `[${columns.join(", ")}]`;
  }
  async asCloneableObject() {
    return this.contents;
  }
  safeIndex(index1, index2) {
    if (index2 === void 0) {
      this.system.throwRangeError(this.contents, index2);
      return;
    }
    const r = this.contents[index1];
    if (r === void 0) {
      this.system.throwRangeError(this.contents, index1);
      return;
    }
    const r1 = r[index2];
    if (r1 === void 0) {
      this.system.throwRangeError(r, index2);
      return;
    }
    return r1;
  }
};
__decorateClass([
  elanProcedure(["column", "row", "value"]),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanIntType()),
  __decorateParam(2, elanGenericParamT1Type())
], ElanArray2D.prototype, "put", 1);
__decorateClass([
  elanFunction(["column", "row", "value"], 0 /* pure */, ElanClass(ElanArray2D)),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanIntType()),
  __decorateParam(2, elanGenericParamT1Type())
], ElanArray2D.prototype, "withPut", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanInt)
], ElanArray2D.prototype, "columns", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanInt)
], ElanArray2D.prototype, "rows", 1);
__decorateClass([
  elanFunction(["item"], 0 /* pure */, ElanTuple([ElanInt, ElanInt])),
  __decorateParam(0, elanGenericParamT1Type())
], ElanArray2D.prototype, "indexOf", 1);
__decorateClass([
  elanFunction(["item"], 0 /* pure */),
  __decorateParam(0, elanGenericParamT1Type())
], ElanArray2D.prototype, "contains", 1);
ElanArray2D = __decorateClass([
  elanClass(
    5 /* array2D */,
    [ElanT1],
    ["columns", "rows", "initialValue"],
    [ElanInt, ElanInt, ElanT1],
    [],
    "Array2D"
  )
], ElanArray2D);

// src/compiler/standard-library/image-vg.ts
var ImageVG = class extends VectorGraphic {
  static emptyInstance() {
    return new ImageVG();
  }
  async _initialise(url) {
    this.url = url;
    return this;
  }
  system;
  constructor(copy) {
    super();
    this.x = copy ? copy.x : 0;
    this.y = copy ? copy.y : 0;
    this.width = copy ? copy.width : 13.2;
    this.height = copy ? copy.height : 13.2;
    this.url = copy ? copy.url : "";
    this.alt = copy ? copy.alt : "";
  }
  x = 0;
  setX(x) {
    this.x = x;
  }
  withX(x) {
    const copy = this.system.initialise(new ImageVG(this));
    copy.x = x;
    return copy;
  }
  y = 0;
  setY(y) {
    this.y = y;
  }
  withY(y) {
    const copy = this.system.initialise(new ImageVG(this));
    copy.y = y;
    return copy;
  }
  alt;
  setAlt(alt) {
    this.alt = alt;
  }
  withAlt(alt) {
    const copy = this.system.initialise(new ImageVG(this));
    copy.alt = alt;
    return copy;
  }
  width;
  setWidth(width) {
    this.width = width;
  }
  withWidth(width) {
    const copy = this.system.initialise(new ImageVG(this));
    copy.width = width;
    return copy;
  }
  height = 13.2;
  setHeight(height) {
    this.height = height;
  }
  withHeight(height) {
    const copy = this.system.initialise(new ImageVG(this));
    copy.height = height;
    return copy;
  }
  url = "";
  getUrl() {
    return this.url;
  }
  title = "";
  setTitle(title) {
    this.title = title;
  }
  withTitle(title) {
    const copy = this.system.initialise(new ImageVG(this));
    copy.title = title;
    return copy;
  }
  asSVG() {
    return `<image x="${this.x}%" y="${this.y / 0.75}%" width="${this.width}" height="${this.height / 0.75}" href="${this.url}" title="${this.title}" alt="${this.alt}"/>`;
  }
  asHtml() {
    return `<img src='${this.url}' width='${this.width}' height='${this.height}' title='${this.title}' alt='${this.alt}'>`;
  }
  asString() {
    return `an ImageVG`;
  }
};
__decorateClass([
  elanProperty()
], ImageVG.prototype, "x", 2);
__decorateClass([
  elanProcedure(["x"])
], ImageVG.prototype, "setX", 1);
__decorateClass([
  elanFunction(["x"], 0 /* pure */, ElanClass(ImageVG))
], ImageVG.prototype, "withX", 1);
__decorateClass([
  elanProperty()
], ImageVG.prototype, "y", 2);
__decorateClass([
  elanProcedure(["y"])
], ImageVG.prototype, "setY", 1);
__decorateClass([
  elanFunction(["y"], 0 /* pure */, ElanClass(ImageVG))
], ImageVG.prototype, "withY", 1);
__decorateClass([
  elanProperty()
], ImageVG.prototype, "alt", 2);
__decorateClass([
  elanProcedure(["alt"])
], ImageVG.prototype, "setAlt", 1);
__decorateClass([
  elanFunction(["alt"], 0 /* pure */, ElanClass(ImageVG))
], ImageVG.prototype, "withAlt", 1);
__decorateClass([
  elanProperty()
], ImageVG.prototype, "width", 2);
__decorateClass([
  elanProcedure(["width"])
], ImageVG.prototype, "setWidth", 1);
__decorateClass([
  elanFunction(["width"], 0 /* pure */, ElanClass(ImageVG))
], ImageVG.prototype, "withWidth", 1);
__decorateClass([
  elanProperty()
], ImageVG.prototype, "height", 2);
__decorateClass([
  elanProcedure(["height"])
], ImageVG.prototype, "setHeight", 1);
__decorateClass([
  elanFunction(["height"], 0 /* pure */, ElanClass(ImageVG))
], ImageVG.prototype, "withHeight", 1);
__decorateClass([
  elanProperty()
], ImageVG.prototype, "url", 2);
__decorateClass([
  elanFunction([], 0 /* pure */)
], ImageVG.prototype, "getUrl", 1);
__decorateClass([
  elanProperty()
], ImageVG.prototype, "title", 2);
__decorateClass([
  elanProcedure(["title"])
], ImageVG.prototype, "setTitle", 1);
__decorateClass([
  elanFunction(["title"], 0 /* pure */, ElanClass(ImageVG))
], ImageVG.prototype, "withTitle", 1);
__decorateClass([
  elanFunction([], 0 /* pure */)
], ImageVG.prototype, "asSVG", 1);
__decorateClass([
  elanFunction([], 0 /* pure */)
], ImageVG.prototype, "asHtml", 1);
ImageVG = __decorateClass([
  elanClass(0 /* concrete */, [], [], [ElanString], [ElanClass(VectorGraphic)])
], ImageVG);

// src/compiler/standard-library/line-vg.ts
var LineVG = class extends VectorGraphic {
  static emptyInstance() {
    return new LineVG();
  }
  async _initialise() {
    return this;
  }
  system;
  constructor(copy) {
    super();
    this.x1 = copy ? copy.x1 : 10;
    this.y1 = copy ? copy.y1 : 10;
    this.x2 = copy ? copy.x2 : 70;
    this.y2 = copy ? copy.y2 : 40;
    this.strokeColour = copy ? copy.strokeColour : 0;
    this.strokeWidth = copy ? copy.strokeWidth : 1;
  }
  x1 = 0;
  setX1(x1) {
    this.x1 = x1;
  }
  withX1(x1) {
    const copy = this.system.initialise(new LineVG(this));
    copy.x1 = x1;
    return copy;
  }
  y1 = 0;
  setY1(y1) {
    this.y1 = y1;
  }
  withY1(y1) {
    const copy = this.system.initialise(new LineVG(this));
    copy.y1 = y1;
    return copy;
  }
  x2 = 0;
  setX2(x2) {
    this.x2 = x2;
  }
  withX2(x2) {
    const copy = this.system.initialise(new LineVG(this));
    copy.x2 = x2;
    return copy;
  }
  y2 = 0;
  setY2(y2) {
    this.y2 = y2;
  }
  withY2(y2) {
    const copy = this.system.initialise(new LineVG(this));
    copy.y2 = y2;
    return copy;
  }
  strokeColour = 0;
  setStrokeColour(strokeColour) {
    this.strokeColour = strokeColour;
  }
  withStrokeColour(strokeColour) {
    const copy = this.system.initialise(new LineVG(this));
    copy.strokeColour = strokeColour;
    return copy;
  }
  strokeWidth = 0;
  setStrokeWidth(strokeWidth) {
    this.strokeWidth = strokeWidth;
  }
  withStrokeWidth(strokeWidth) {
    const copy = this.system.initialise(new LineVG(this));
    copy.strokeWidth = strokeWidth;
    return copy;
  }
  asSVG() {
    return `<line x1="${this.x1}%" y1="${this.y1 / 0.75}%" x2="${this.x2}%" y2="${this.y2 / 0.75}%" ${this.strokeAsHtml(this.strokeWidth, this.strokeColour)}/>`;
  }
};
__decorateClass([
  elanProperty()
], LineVG.prototype, "x1", 2);
__decorateClass([
  elanProcedure(["x1"])
], LineVG.prototype, "setX1", 1);
__decorateClass([
  elanFunction(["x1"], 0 /* pure */, ElanClass(LineVG))
], LineVG.prototype, "withX1", 1);
__decorateClass([
  elanProperty()
], LineVG.prototype, "y1", 2);
__decorateClass([
  elanProcedure(["y1"])
], LineVG.prototype, "setY1", 1);
__decorateClass([
  elanFunction(["y1"], 0 /* pure */, ElanClass(LineVG))
], LineVG.prototype, "withY1", 1);
__decorateClass([
  elanProperty()
], LineVG.prototype, "x2", 2);
__decorateClass([
  elanProcedure(["x2"])
], LineVG.prototype, "setX2", 1);
__decorateClass([
  elanFunction(["x2"], 0 /* pure */, ElanClass(LineVG))
], LineVG.prototype, "withX2", 1);
__decorateClass([
  elanProperty()
], LineVG.prototype, "y2", 2);
__decorateClass([
  elanProcedure(["x2"])
], LineVG.prototype, "setY2", 1);
__decorateClass([
  elanFunction(["x2"], 0 /* pure */, ElanClass(LineVG))
], LineVG.prototype, "withY2", 1);
__decorateClass([
  elanProperty(ElanInt)
], LineVG.prototype, "strokeColour", 2);
__decorateClass([
  elanProcedure(["colour"])
], LineVG.prototype, "setStrokeColour", 1);
__decorateClass([
  elanFunction(["colour"], 0 /* pure */, ElanClass(LineVG))
], LineVG.prototype, "withStrokeColour", 1);
__decorateClass([
  elanProperty()
], LineVG.prototype, "strokeWidth", 2);
__decorateClass([
  elanProcedure(["strokeWidth"])
], LineVG.prototype, "setStrokeWidth", 1);
__decorateClass([
  elanFunction(["width"], 0 /* pure */, ElanClass(LineVG))
], LineVG.prototype, "withStrokeWidth", 1);
__decorateClass([
  elanFunction([], 0 /* pure */)
], LineVG.prototype, "asSVG", 1);
LineVG = __decorateClass([
  elanClass(2 /* record */, [], [], [], [ElanClass(VectorGraphic)])
], LineVG);

// src/compiler/standard-library/queue.ts
var Queue = class {
  // this must be implemented by hand on all stdlib classes
  static emptyInstance() {
    return new Queue();
  }
  async _initialise() {
    return this;
  }
  constructor(arr) {
    this.contents = arr ? [...arr] : [];
  }
  contents;
  system;
  peek() {
    if (this.contents.length === 0) {
      throw new ElanRuntimeError(`Cannot peek an empty Queue - check using length()`);
    }
    return this.contents[0];
  }
  length() {
    return this.contents.length;
  }
  enqueue(item) {
    const newContents = [...this.contents];
    newContents.push(item);
    return this.system.initialise(new Queue(newContents));
  }
  dequeue() {
    if (this.contents.length === 0) {
      throw new ElanRuntimeError(`Cannot dequeue an empty Queue - check using length()`);
    }
    const newContents = [...this.contents];
    const item = newContents.shift();
    const newQueue = this.system.initialise(new Queue(newContents));
    return this.system.tuple([item, newQueue]);
  }
  async asString() {
    const items = [];
    for (const i of this.contents) {
      const s = await this.system.asString(i);
      items.push(s);
    }
    return `[${items.join(", ")}]`;
  }
};
__decorateClass([
  elanFunction([], 0 /* pure */, ElanT1)
], Queue.prototype, "peek", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanInt)
], Queue.prototype, "length", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClass(Queue)),
  __decorateParam(0, elanGenericParamT1Type())
], Queue.prototype, "enqueue", 1);
__decorateClass([
  elanFunction([], 4 /* impure */, ElanTuple([ElanT1, ElanClass(Queue)]))
], Queue.prototype, "dequeue", 1);
Queue = __decorateClass([
  elanClass(2 /* record */, [ElanT1])
], Queue);

// src/compiler/standard-library/random.ts
var Random = class {
  // this must be implemented by hand on all stdlib classes
  static emptyInstance() {
    return new Random();
  }
  async _initialise() {
    return this;
  }
  constructor() {
    this.u = 521288629;
    this.v = 362436069;
  }
  system;
  u;
  v;
  next() {
    return this.nextImpl();
  }
  nextImpl() {
    const value = this.lo32(this.lo32(this.u * 65536) + this.v + 1) * 2328306435454494e-25;
    const rnd2 = this.system.initialise(new Random());
    rnd2.u = 36969 * (this.u % 65536) + this.u / 65536;
    rnd2.v = 18e3 * (this.v % 65536) + this.v / 65536;
    return [value, rnd2];
  }
  lo32(n) {
    return n % 4294967296;
  }
  nextInt(min, max) {
    const [float, rnd2] = this.nextImpl();
    const value = Math.floor(float * (max - min + 1) + min);
    return [value, rnd2];
  }
  initialiseFromClock() {
    const c = (/* @__PURE__ */ new Date()).getTime();
    this.u = c % 1e3 * 1e6;
    this.v = 0;
  }
};
__decorateClass([
  elanFunction([], 0 /* pure */, ElanTuple([ElanFloat, ElanClass(Random)]))
], Random.prototype, "next", 1);
__decorateClass([
  elanFunction(["min", "max"], 0 /* pure */, ElanTuple([ElanInt, ElanClass(Random)])),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanIntType())
], Random.prototype, "nextInt", 1);
__decorateClass([
  elanProcedure([])
], Random.prototype, "initialiseFromClock", 1);
Random = __decorateClass([
  elanClass(2 /* record */)
], Random);

// src/compiler/standard-library/raw-vg.ts
var RawVG = class extends VectorGraphic {
  static emptyInstance() {
    return new RawVG();
  }
  async _initialise() {
    return this;
  }
  system;
  constructor(copy) {
    super();
    this.rawSVGcontent = copy ? copy?.rawSVGcontent : "";
  }
  rawSVGcontent = "";
  asSVG() {
    return this.rawSVGcontent;
  }
};
__decorateClass([
  elanProperty()
], RawVG.prototype, "rawSVGcontent", 2);
__decorateClass([
  elanFunction([], 0 /* pure */)
], RawVG.prototype, "asSVG", 1);
RawVG = __decorateClass([
  elanClass(0 /* concrete */, [], [], [], [ElanClass(VectorGraphic)])
], RawVG);

// src/compiler/standard-library/rectangle-vg.ts
var RectangleVG = class extends VectorGraphic {
  static emptyInstance() {
    return new RectangleVG();
  }
  async _initialise() {
    return this;
  }
  system;
  constructor(copy) {
    super();
    this.x = copy ? copy.x : 10;
    this.y = copy ? copy.y : 10;
    this.width = copy ? copy.width : 40;
    this.height = copy ? copy.height : 20;
    this.fillColour = copy ? copy.fillColour : 16776960;
    this.strokeColour = copy ? copy.strokeColour : 0;
    this.strokeWidth = copy ? copy.strokeWidth : 1;
  }
  x = 0;
  setX(x) {
    this.x = x;
  }
  withX(x) {
    const copy = this.system.initialise(new RectangleVG(this));
    copy.x = x;
    return copy;
  }
  y = 0;
  setY(y) {
    this.y = y;
  }
  withY(y) {
    const copy = this.system.initialise(new RectangleVG(this));
    copy.y = y;
    return copy;
  }
  width = 0;
  setWidth(width) {
    this.width = width;
  }
  withWidth(width) {
    const copy = this.system.initialise(new RectangleVG(this));
    copy.width = width;
    return copy;
  }
  height = 0;
  setHeight(height) {
    this.height = height;
  }
  withHeight(height) {
    const copy = this.system.initialise(new RectangleVG(this));
    copy.height = height;
    return copy;
  }
  strokeColour = 0;
  setStrokeColour(strokeColour) {
    this.strokeColour = strokeColour;
  }
  withStrokeColour(strokeColour) {
    const copy = this.system.initialise(new RectangleVG(this));
    copy.strokeColour = strokeColour;
    return copy;
  }
  strokeWidth = 0;
  setStrokeWidth(strokeWidth) {
    this.strokeWidth = strokeWidth;
  }
  withStrokeWidth(strokeWidth) {
    const copy = this.system.initialise(new RectangleVG(this));
    copy.strokeWidth = strokeWidth;
    return copy;
  }
  fillColour = 0;
  setFillColour(fillColour) {
    this.fillColour = fillColour;
  }
  withFillColour(fillColour) {
    const copy = this.system.initialise(new RectangleVG(this));
    copy.fillColour = fillColour;
    return copy;
  }
  asSVG() {
    return `<rect x="${this.x}%" y="${this.y / 0.75}%" width="${this.width}%" height="${this.height / 0.75}%" ${this.strokeAsHtml(this.strokeWidth, this.strokeColour)} ${this.fillAsHtml(this.fillColour)}/>`;
  }
};
__decorateClass([
  elanProperty()
], RectangleVG.prototype, "x", 2);
__decorateClass([
  elanProcedure(["x"])
], RectangleVG.prototype, "setX", 1);
__decorateClass([
  elanFunction(["x"], 0 /* pure */, ElanClass(RectangleVG))
], RectangleVG.prototype, "withX", 1);
__decorateClass([
  elanProperty()
], RectangleVG.prototype, "y", 2);
__decorateClass([
  elanProcedure(["y"])
], RectangleVG.prototype, "setY", 1);
__decorateClass([
  elanFunction(["y"], 0 /* pure */, ElanClass(RectangleVG))
], RectangleVG.prototype, "withY", 1);
__decorateClass([
  elanProperty()
], RectangleVG.prototype, "width", 2);
__decorateClass([
  elanProcedure(["width"])
], RectangleVG.prototype, "setWidth", 1);
__decorateClass([
  elanFunction(["width"], 0 /* pure */, ElanClass(RectangleVG))
], RectangleVG.prototype, "withWidth", 1);
__decorateClass([
  elanProperty()
], RectangleVG.prototype, "height", 2);
__decorateClass([
  elanProcedure(["height"])
], RectangleVG.prototype, "setHeight", 1);
__decorateClass([
  elanFunction(["height"], 0 /* pure */, ElanClass(RectangleVG))
], RectangleVG.prototype, "withHeight", 1);
__decorateClass([
  elanProperty(ElanInt)
], RectangleVG.prototype, "strokeColour", 2);
__decorateClass([
  elanProcedure(["colour"])
], RectangleVG.prototype, "setStrokeColour", 1);
__decorateClass([
  elanFunction(["colour"], 0 /* pure */, ElanClass(RectangleVG))
], RectangleVG.prototype, "withStrokeColour", 1);
__decorateClass([
  elanProperty()
], RectangleVG.prototype, "strokeWidth", 2);
__decorateClass([
  elanProcedure(["strokeWidth"])
], RectangleVG.prototype, "setStrokeWidth", 1);
__decorateClass([
  elanFunction(["width"], 0 /* pure */, ElanClass(RectangleVG))
], RectangleVG.prototype, "withStrokeWidth", 1);
__decorateClass([
  elanProperty(ElanInt)
], RectangleVG.prototype, "fillColour", 2);
__decorateClass([
  elanProcedure(["fillColour"])
], RectangleVG.prototype, "setFillColour", 1);
__decorateClass([
  elanFunction(["colour"], 0 /* pure */, ElanClass(RectangleVG))
], RectangleVG.prototype, "withFillColour", 1);
__decorateClass([
  elanFunction([], 0 /* pure */)
], RectangleVG.prototype, "asSVG", 1);
RectangleVG = __decorateClass([
  elanClass(2 /* record */, [], [], [], [ElanClass(VectorGraphic)])
], RectangleVG);

// src/compiler/standard-library/stack.ts
var Stack = class {
  // this must be implemented by hand on all stdlib classes
  static emptyInstance() {
    return new Stack();
  }
  async _initialise() {
    return this;
  }
  constructor(arr) {
    this.contents = arr ? [...arr] : [];
  }
  contents;
  system;
  peek() {
    if (this.contents.length === 0) {
      throw new ElanRuntimeError(`Cannot peek an empty Stack - check using length()`);
    }
    return this.contents[0];
  }
  length() {
    return this.contents.length;
  }
  push(item) {
    const newContents = [...this.contents];
    newContents.unshift(item);
    return this.system.initialise(new Stack(newContents));
  }
  pop() {
    if (this.contents.length === 0) {
      throw new ElanRuntimeError(`Cannot pop an empty Stack - check using length()`);
    }
    const newContents = [...this.contents];
    const item = newContents.shift();
    const newStack = this.system.initialise(new Stack(newContents));
    return this.system.tuple([item, newStack]);
  }
  async asString() {
    const items = [];
    for (const i of this.contents) {
      const s = await this.system.asString(i);
      items.push(s);
    }
    return `[${items.join(", ")}]`;
  }
};
__decorateClass([
  elanFunction([], 0 /* pure */, ElanT1)
], Stack.prototype, "peek", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanInt)
], Stack.prototype, "length", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanClass(Stack)),
  __decorateParam(0, elanGenericParamT1Type())
], Stack.prototype, "push", 1);
__decorateClass([
  elanFunction([], 4 /* impure */, ElanTuple([ElanT1, ElanClass(Stack)]))
], Stack.prototype, "pop", 1);
Stack = __decorateClass([
  elanClass(2 /* record */, [ElanT1])
], Stack);

// src/compiler/standard-library/text-file-reader.ts
var _TextFileReader = class _TextFileReader {
  // this must be implemented by hand on all stdlib classes
  static emptyInstance() {
    return new _TextFileReader();
  }
  async _initialise() {
    return this;
  }
  constructor() {
  }
  system;
  status = 0;
  //0 = Closed, 1 = Open
  content = [];
  currentLine = 0;
  readLine() {
    if (this.status === 0) {
      throw new ElanRuntimeError(this.cannotUseOnClosed);
    }
    let line = "";
    if (this.currentLine < this.content.length) {
      line = this.content[this.currentLine].trim();
      this.currentLine++;
    }
    return line;
  }
  cannotUseOnClosed = "Cannot use any method on a closed file";
  readWholeFile() {
    if (this.status === 0) {
      throw new ElanRuntimeError(this.cannotUseOnClosed);
    }
    this.status = 0;
    return this.content.join("\n");
  }
  close() {
    if (this.status === 0) {
      throw new ElanRuntimeError(this.cannotUseOnClosed);
    }
    this.status = 0;
  }
  endOfFile() {
    if (this.status === 0) {
      throw new ElanRuntimeError(this.cannotUseOnClosed);
    }
    return this.currentLine >= this.content.length;
  }
};
__decorateClass([
  elanFunction([], 4 /* impure */, ElanString)
], _TextFileReader.prototype, "readLine", 1);
__decorateClass([
  elanFunction([], 4 /* impure */, ElanString)
], _TextFileReader.prototype, "readWholeFile", 1);
__decorateClass([
  elanProcedure([])
], _TextFileReader.prototype, "close", 1);
__decorateClass([
  elanFunction([], 0 /* pure */, ElanBoolean)
], _TextFileReader.prototype, "endOfFile", 1);
var TextFileReader = _TextFileReader;

// src/compiler/standard-library/text-file-writer.ts
var _TextFileWriter = class _TextFileWriter {
  // this must be implemented by hand on all stdlib classes
  static emptyInstance() {
    return new _TextFileWriter();
  }
  async _initialise() {
    return this;
  }
  constructor() {
  }
  system;
  status = 0;
  //0 = Closed, 1 = Open
  fileName = "";
  content = [];
  currentLine = 0;
  cannotUseOnClosed = "Cannot use any method on a closed file";
  writeLine(data) {
    if (this.status === 0) {
      throw new ElanRuntimeError(this.cannotUseOnClosed);
    }
    this.content.push(data);
  }
  async writeWholeFile(data) {
    if (this.status === 0) {
      throw new ElanRuntimeError(this.cannotUseOnClosed);
    }
    if (this.content.length > 0) {
      throw new ElanRuntimeError(
        "Cannot call 'writeWholeFile' if content has already been written using 'writeLine'"
      );
    }
    this.status = 0;
    try {
      await this.system.elanInputOutput.writeFile(this.fileName, data);
    } catch (e) {
      throw new ElanRuntimeError(e);
    }
  }
  async saveAndClose() {
    if (this.status === 0) {
      throw new ElanRuntimeError(this.cannotUseOnClosed);
    }
    this.status = 0;
    try {
      await this.system.elanInputOutput.writeFile(this.fileName, this.content.join("\n"));
    } catch (e) {
      throw new ElanRuntimeError(e);
    }
  }
};
__decorateClass([
  elanProcedure([])
], _TextFileWriter.prototype, "writeLine", 1);
__decorateClass([
  elanProcedure([], 2 /* async */)
], _TextFileWriter.prototype, "writeWholeFile", 1);
__decorateClass([
  elanProcedure([], 2 /* async */)
], _TextFileWriter.prototype, "saveAndClose", 1);
var TextFileWriter = _TextFileWriter;

// src/compiler/standard-library/graphics-base.ts
var GraphicsBase = class {
  // this must be implemented by hand on all stdlib classes
  static emptyInstance() {
    return new GraphicsBase();
  }
  constructor() {
  }
  asHtml() {
    return "";
  }
};
GraphicsBase = __decorateClass([
  elanClass(1 /* abstract */)
], GraphicsBase);

// src/compiler/standard-library/turtle.ts
var Turtle = class extends GraphicsBase {
  // this must = implemented by hand on all stdlib classes
  static emptyInstance() {
    return new Turtle();
  }
  async _initialise() {
    return this;
  }
  _system;
  set system(value) {
    this._system = value;
    this.vg = this._system.initialise(new List());
  }
  constructor() {
    super();
    this.x = 0;
    this.y = 0;
    this.heading = 0;
    this.pen = true;
    this.shown = true;
    this.colour = 0;
    this.width = 1;
    this.vg = new List();
  }
  reset() {
    this.x = 0;
    this.y = 0;
    this.heading = 0;
    this.pen = true;
    this.shown = true;
    this.colour = 0;
    this.width = 1;
  }
  stdlib;
  // injected
  vg;
  x;
  y;
  heading;
  pen;
  shown;
  colour;
  width;
  async show() {
    this.removeTurtleIfShown();
    this.shown = true;
    this.addTurtleIfShown();
    await this.stdlib.displayVectorGraphics(this.vg);
  }
  async clearAndReset() {
    this.vg = this._system.initialise(new List());
    this.x = 0;
    this.y = 0;
    this.heading = 0;
    this.pen = true;
    this.colour = 0;
    this.width = 1;
    await this.stdlib.displayVectorGraphics(this.vg);
  }
  async hide() {
    this.removeTurtleIfShown();
    this.shown = false;
    await this.stdlib.displayVectorGraphics(this.vg);
  }
  penUp() {
    this.pen = false;
  }
  penDown() {
    this.pen = true;
  }
  addTurtleIfShown() {
    if (this.shown) {
      const turtle = new CircleVG();
      turtle.centreX = this.asVGx(this.x);
      turtle.centreY = this.asVGy(this.y);
      turtle.radius = 2;
      turtle.fillColour = 32768;
      turtle.strokeWidth = 0;
      const [x2, y2] = this.getDestination(2);
      const pointer = new LineVG();
      pointer.x1 = this.asVGx(this.x);
      pointer.y1 = this.asVGy(this.y);
      pointer.x2 = this.asVGx(x2);
      pointer.y2 = this.asVGy(y2);
      pointer.strokeWidth = 2;
      this.vg.append(turtle);
      this.vg.append(pointer);
    }
  }
  removeTurtleIfShown() {
    if (this.shown) {
      const len = this.vg.length();
      this.vg.removeAt(len - 1);
      this.vg.removeAt(len - 2);
    }
  }
  getDestination(distance) {
    const newX = this.x + distance * this.stdlib.sinDeg(this.heading);
    const newY = this.y + distance * this.stdlib.cosDeg(this.heading);
    return [newX, newY];
  }
  async move(distance) {
    const [x, y] = this.getDestination(distance);
    await this.moveTo(x, y);
  }
  asVGx(x) {
    return x / 2 + 50;
  }
  asVGy(y) {
    return -y / 2 + 37.5;
  }
  async moveTo(x, y) {
    this.removeTurtleIfShown();
    if (this.pen) {
      const line = new LineVG();
      line.x1 = this.asVGx(this.x);
      line.y1 = this.asVGy(this.y);
      line.x2 = this.asVGx(x);
      line.y2 = this.asVGy(y);
      line.strokeColour = this.colour;
      line.strokeWidth = this.width;
      this.vg.append(line);
    }
    this.x = x;
    this.y = y;
    this.addTurtleIfShown();
    await this.stdlib.displayVectorGraphics(this.vg);
  }
  async turn(degrees) {
    await this.turnToHeading(this.heading + degrees);
  }
  async turnToHeading(heading) {
    this.removeTurtleIfShown();
    this.heading = this.normaliseHeading(heading);
    this.addTurtleIfShown();
    await this.stdlib.displayVectorGraphics(this.vg);
  }
  normaliseHeading(x) {
    return x >= 360 ? this.normaliseHeading(x - 360) : x < 0 ? this.normaliseHeading(x + 360) : x;
  }
  penColour(colour) {
    this.colour = colour;
  }
  penWidth(width) {
    this.width = width > 0 ? width : 1;
  }
  async placeAt(x, y) {
    this.removeTurtleIfShown();
    this.x = x;
    this.y = y;
    this.addTurtleIfShown();
    await this.stdlib.displayVectorGraphics(this.vg);
  }
  asHtml() {
    return this.stdlib.vectorGraphicsAsHtml(this.vg);
  }
  /*   @elanProcedure(["otherTurtle"])
  shareDisplayWith(@elanClassType(Turtle) t2: Turtle) {
    const vg = t2.vg;
    vg.appendList(this.vg);
    this.vg = vg;
  } */
};
__decorateClass([
  elanProperty()
], Turtle.prototype, "x", 2);
__decorateClass([
  elanProperty()
], Turtle.prototype, "y", 2);
__decorateClass([
  elanProperty()
], Turtle.prototype, "heading", 2);
__decorateClass([
  elanProcedure([], 2 /* async */)
], Turtle.prototype, "show", 1);
__decorateClass([
  elanProcedure([], 2 /* async */)
], Turtle.prototype, "clearAndReset", 1);
__decorateClass([
  elanProcedure([], 2 /* async */)
], Turtle.prototype, "hide", 1);
__decorateClass([
  elanProcedure([])
], Turtle.prototype, "penUp", 1);
__decorateClass([
  elanProcedure([])
], Turtle.prototype, "penDown", 1);
__decorateClass([
  elanProcedure(["distance"], 2 /* async */)
], Turtle.prototype, "move", 1);
__decorateClass([
  elanProcedure(["x", "y"], 2 /* async */)
], Turtle.prototype, "moveTo", 1);
__decorateClass([
  elanProcedure(["degrees"], 2 /* async */)
], Turtle.prototype, "turn", 1);
__decorateClass([
  elanProcedure([], 2 /* async */)
], Turtle.prototype, "turnToHeading", 1);
__decorateClass([
  elanProcedure(["colour"]),
  __decorateParam(0, elanIntType())
], Turtle.prototype, "penColour", 1);
__decorateClass([
  elanProcedure(["width"]),
  __decorateParam(0, elanFloatType())
], Turtle.prototype, "penWidth", 1);
__decorateClass([
  elanProcedure(["x", "y"], 2 /* async */)
], Turtle.prototype, "placeAt", 1);
__decorateClass([
  elanFunction([], 0 /* pure */)
], Turtle.prototype, "asHtml", 1);
Turtle = __decorateClass([
  elanClass(0 /* concrete */, [], [], [], [ElanClass(GraphicsBase)])
], Turtle);

// src/compiler/standard-library/std-lib.ts
var _StdLib = class _StdLib {
  constructor(io) {
    this.system = new System(io);
  }
  static negatableLitIntOnly = /^\s*-?((0b[0-1]+)|(0x[0-9a-fA-F]+)|([0-9]+))$/;
  static negatableLitFloatOnly = /^\s*-?[0-9]+(\.[0-9]+)?((e|E)[+-]?[0-9]+)?$/;
  system;
  TextFileReader = TextFileReader;
  TextFileWriter = TextFileWriter;
  Random = Random;
  Stack = Stack;
  Queue = Queue;
  Set = ElanSet;
  Turtle = Turtle;
  VectorGraphic = VectorGraphic;
  CircleVG = CircleVG;
  LineVG = LineVG;
  RectangleVG = RectangleVG;
  ImageVG = ImageVG;
  RawVG = RawVG;
  List = List;
  Array = ElanArray;
  Array2D = ElanArray2D;
  ListImmutable = ListImmutable;
  Dictionary = Dictionary;
  DictionaryImmutable = DictionaryImmutable;
  black = 0;
  grey = 8421504;
  white = 16777215;
  red = 16711680;
  green = 32768;
  blue = 255;
  yellow = 16776960;
  brown = 10824234;
  transparent = -1;
  true = true;
  false = false;
  pi = Math.PI;
  meaningOfLife = 42;
  quotes = `"`;
  openBrace = `{`;
  closeBrace = `}`;
  isValueType(v) {
    return typeof v === "boolean" || typeof v === "string" || typeof v === "number";
  }
  async asString(v) {
    if (v === void 0 || v === null) {
      throw new ElanRuntimeError(`Out of range error`);
    }
    if (typeof v === "boolean") {
      return v ? "true" : "false";
    }
    if (typeof v === "string") {
      return v.toString();
    }
    if (typeof v === "number") {
      return v.toString();
    }
    if (v instanceof RegExp) {
      return "A RegExp";
    }
    if (Array.isArray(v)) {
      const items = [];
      for (const i of v) {
        const s = await this.asString(i);
        items.push(s);
      }
      if (items.length < 2) {
        return items.join("");
      }
      return `tuple(${items.join(", ")})`;
    }
    if (typeof v === "object" && "asString" in v) {
      return await v.asString();
    }
    if (typeof v === "object") {
      return `a ${v.constructor.name}`;
    }
    if (typeof v === "function") {
      return `function ${v.name}`;
    }
    throw new ElanCompilerError("Not implemented: " + typeof v);
  }
  unicode(n) {
    return String.fromCharCode(n);
  }
  asUnicode(s) {
    return s.charCodeAt(0);
  }
  indexOf(s, item) {
    return s.indexOf(item);
  }
  sequence(start, end) {
    const seq = [];
    for (let i = start; i <= end; i++) {
      seq.push(i);
    }
    return this.system.initialise(new List(seq));
  }
  sequenceWithStep(start, end, step) {
    const seq = [];
    if (step === 0) {
      throw new ElanRuntimeError("value for step cannot be zero");
    } else if (step > 0) {
      for (let i = start; i <= end; i = i + step) {
        seq.push(i);
      }
    } else if (step < 0) {
      if (start < end) {
        throw new ElanRuntimeError(
          "Loop will not terminate when start < end start with negative step"
        );
      }
      for (let i = start; i >= end; i = i + step) {
        seq.push(i);
      }
    }
    return this.system.initialise(new List(seq));
  }
  replace(instance, match, replacement) {
    return instance.replaceAll(match, replacement);
  }
  length(coll) {
    return coll.length;
  }
  upperCase(s1) {
    return s1.toUpperCase();
  }
  lowerCase(s1) {
    return s1.toLowerCase();
  }
  isBefore(instance, other) {
    return instance < other;
  }
  isAfter(instance, other) {
    return instance > other;
  }
  isAfterOrSameAs(instance, other) {
    return instance > other || instance === other;
  }
  isBeforeOrSameAs(instance, other) {
    return instance < other || instance === other;
  }
  trim(s) {
    return s.trim();
  }
  split(s, separator) {
    return this.system.initialise(new List(s.split(separator)));
  }
  floor(n) {
    return Math.floor(n);
  }
  isNaN(n) {
    return isNaN(n);
  }
  isInfinite(n) {
    return n === Number.POSITIVE_INFINITY || n === Number.NEGATIVE_INFINITY;
  }
  round(n, places) {
    const shift = 10 ** places;
    return Math.floor(n * shift + 0.5) / shift;
  }
  ceiling(n) {
    const fl = this.floor(n);
    return n > fl ? fl + 1 : fl;
  }
  maxFloat(source) {
    return Math.max(...source);
  }
  maxInt(source) {
    return Math.max(...source);
  }
  minFloat(source) {
    return Math.min(...source);
  }
  minInt(source) {
    return Math.min(...source);
  }
  contains(source, item) {
    return source.includes(item);
  }
  pause(ms) {
    return new Promise((resolve) => {
      setTimeout(() => resolve(), ms);
    });
  }
  clock() {
    return (/* @__PURE__ */ new Date()).getTime();
  }
  random() {
    return Math.random();
  }
  randomInt(low, high) {
    return Math.floor(Math.random() * (high - low + 1)) + low;
  }
  parseAsFloat(s) {
    if (_StdLib.negatableLitFloatOnly.test(s)) {
      const f = parseFloat(s);
      if (Number.isFinite(f)) {
        return this.system.tuple([true, f]);
      }
    }
    return this.system.tuple([false, 0]);
  }
  parseAsInt(s) {
    if (_StdLib.negatableLitIntOnly.test(s)) {
      const i = parseInt(s);
      if (isFinite(i)) {
        return this.system.tuple([true, i]);
      }
    }
    return this.system.tuple([false, 0]);
  }
  async printLine(s) {
    await this.system.elanInputOutput.print(`${s}
`);
  }
  async printNoLine(s) {
    await this.system.elanInputOutput.print(s);
  }
  async printTab(position, s) {
    await this.system.elanInputOutput.printTab(position, s);
  }
  async clearPrintedText() {
    await this.system.elanInputOutput.clearPrintedText();
  }
  async clearAllDisplays() {
    await this.clearPrintedText();
    await this.clearBlocks();
    await this.clearVectorGraphics();
    await this.clearHtml();
  }
  createList(x, value) {
    if (!this.isValueType(value)) {
      throw new ElanRuntimeError(`Can only create List with simple value`);
    }
    const toInit = [];
    for (let i = 0; i < x; i++) {
      toInit[i] = value;
    }
    return this.system.initialise(new List(toInit));
  }
  //Input functions
  async prompt(prompt) {
    await this.printLine(prompt);
  }
  async inputString(prompt) {
    await this.prompt(prompt);
    return await this.system.input();
  }
  async inputStringWithLimits(prompt, minLength, maxLength) {
    const s = await this.inputString(prompt);
    if (s.length < minLength) {
      await this.prompt(`minimum length ${minLength} characters`);
    } else if (s.length > maxLength) {
      await this.prompt(`maximum length ${maxLength} characters`);
    } else {
      return s;
    }
    return await this.inputStringWithLimits(prompt, minLength, maxLength);
  }
  async inputStringFromOptions(prompt, options) {
    const s = await this.inputString(prompt);
    if (options.contains(s)) {
      return s;
    }
    const valid = await options.asString();
    await this.prompt(`response must be one of ${valid}`);
    return await this.inputStringFromOptions(prompt, options);
  }
  async inputInt(prompt) {
    const s = await this.inputString(prompt);
    const [b, i] = this.parseAsInt(s);
    if (b && i.toString() === s) {
      return i;
    }
    await this.prompt("must be an integer");
    return await this.inputInt(prompt);
  }
  async inputIntBetween(prompt, min, max) {
    const s = await this.inputString(prompt);
    const [b, i] = this.parseAsInt(s);
    if (b && i.toString() === s && i >= min && i <= max) {
      return i;
    }
    await this.prompt(`must be an integer between ${min} and ${max} inclusive`);
    return await this.inputIntBetween(prompt, min, max);
  }
  async inputFloat(prompt) {
    const s = await this.inputString(prompt);
    const [b, i] = this.parseAsFloat(s);
    if (b) {
      return i;
    }
    await this.prompt("not a number");
    return await this.inputFloat(prompt);
  }
  async inputFloatBetween(prompt, min, max) {
    const s = await this.inputString(prompt);
    const [b, i] = this.parseAsFloat(s);
    if (b && i >= min && i <= max) {
      return i;
    }
    await this.prompt(`must be a number between ${min} and ${max} inclusive`);
    return await this.inputFloatBetween(prompt, min, max);
  }
  abs(x) {
    return Math.abs(x);
  }
  acos(x) {
    return Math.acos(x);
  }
  acosDeg(n) {
    return this.radToDeg(this.acos(n));
  }
  asin(x) {
    return Math.asin(x);
  }
  asinDeg(n) {
    return this.radToDeg(this.asin(n));
  }
  atan(x) {
    return Math.atan(x);
  }
  atanDeg(n) {
    return this.radToDeg(this.atan(n));
  }
  cos(x) {
    return Math.cos(x);
  }
  cosDeg(n) {
    return this.cos(this.degToRad(n));
  }
  exp(x) {
    return Math.exp(x);
  }
  logE(x) {
    return Math.log(x);
  }
  log10(x) {
    return Math.log10(x);
  }
  log2(x) {
    return Math.log2(x);
  }
  sin(x) {
    return Math.sin(x);
  }
  sinDeg(n) {
    return this.sin(this.degToRad(n));
  }
  sqrt(x) {
    return Math.sqrt(x);
  }
  tan(x) {
    return Math.tan(x);
  }
  tanDeg(n) {
    return this.tan(this.degToRad(n));
  }
  degToRad(d) {
    return d * this.pi / 180;
  }
  radToDeg(r) {
    return r / this.pi * 180;
  }
  bitAnd(a, b) {
    return a & b;
  }
  bitOr(a, b) {
    return a | b;
  }
  bitXor(a, b) {
    return a ^ b;
  }
  bitNot(a) {
    return ~a;
  }
  bitShiftL(value, shift) {
    return value << shift;
  }
  bitShiftR(value, places) {
    return value >>> places;
  }
  asBinary(a) {
    return a.toString(2);
  }
  matchesRegExp(a, r) {
    return r.test(a);
  }
  asRegExp(pattern) {
    return new RegExp(pattern, "");
  }
  openFileForReading() {
    return this.system.elanInputOutput.readFile().then(
      (s) => {
        const tf = this.system.initialise(new TextFileReader());
        tf.status = 1;
        tf.content = s ? s.split("\n") : [];
        return tf;
      },
      (e) => {
        throw new ElanRuntimeError(e);
      }
    );
  }
  createFileForWriting(fileName) {
    const tf = this.system.initialise(new TextFileWriter());
    tf.fileName = fileName;
    tf.status = 1;
    return tf;
  }
  async waitForAnyKey() {
    return await this.system.elanInputOutput.waitForAnyKey();
  }
  async pressAnyKeyToContinue(prompt) {
    if (prompt) {
      await this.prompt("Press any key to continue");
    }
    await this.waitForKey();
    return;
  }
  async waitForKey() {
    return await this.system.elanInputOutput.waitForKey();
  }
  async getKey() {
    return await this.system.elanInputOutput.getKey();
  }
  async getKeyWithModifier() {
    return await this.system.elanInputOutput.getKeyWithModifier();
  }
  async clearKeyBuffer() {
    await this.system.elanInputOutput.clearKeyBuffer();
  }
  blocksAsHtml(blocks) {
    let rendered = ``;
    for (let y = 0; y < 30; y++) {
      for (let x = 0; x < 40; x++) {
        const colour = blocks.read(x, y);
        rendered = `${rendered}<div style="background-color:${this.asHex(colour)};"></div>`;
      }
    }
    return rendered;
  }
  asHex(n) {
    const h = "000000" + n.toString(16);
    const h6 = h.substring(h.length - 6);
    return `#${h6}`;
  }
  async displayBlocks(blocks) {
    if (blocks.columns() !== 40 || blocks.rows() !== 30) {
      throw new ElanRuntimeError(`argument must be Array2D<of Int> with dimensions 40 x 30`);
    }
    const html = this.blocksAsHtml(blocks);
    return await this.system.elanInputOutput.drawBlockGraphics(html);
  }
  async clearBlocks() {
    await this.system.elanInputOutput.clearBlockGraphics();
  }
  vectorGraphicsAsHtml(vgs) {
    let content = ``;
    for (let i = 0; i < vgs.length(); i++) {
      const vg = vgs.read(i);
      content = content + vg.asSVG() + "\n";
    }
    const html = `<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
${content}</svg>
`;
    return html;
  }
  async displayVectorGraphics(vgs) {
    const html = this.vectorGraphicsAsHtml(vgs);
    return await this.system.elanInputOutput.drawVectorGraphics(html);
  }
  async clearVectorGraphics() {
    await this.system.elanInputOutput.clearVectorGraphics();
  }
  async displayHtml(html) {
    return await this.system.elanInputOutput.drawHtml(html);
  }
  async clearHtml() {
    return await this.system.elanInputOutput.clearHtml();
  }
  async tone(duration, frequency, volume) {
    await this.system.elanInputOutput.tone(duration, frequency, volume);
  }
};
__decorateClass([
  elanClassExport(TextFileReader)
], _StdLib.prototype, "TextFileReader", 2);
__decorateClass([
  elanClassExport(TextFileWriter)
], _StdLib.prototype, "TextFileWriter", 2);
__decorateClass([
  elanClassExport(Random)
], _StdLib.prototype, "Random", 2);
__decorateClass([
  elanClassExport(Stack)
], _StdLib.prototype, "Stack", 2);
__decorateClass([
  elanClassExport(Queue)
], _StdLib.prototype, "Queue", 2);
__decorateClass([
  elanClassExport(ElanSet)
], _StdLib.prototype, "Set", 2);
__decorateClass([
  elanClassExport(Turtle)
], _StdLib.prototype, "Turtle", 2);
__decorateClass([
  elanClassExport(VectorGraphic)
], _StdLib.prototype, "VectorGraphic", 2);
__decorateClass([
  elanClassExport(CircleVG)
], _StdLib.prototype, "CircleVG", 2);
__decorateClass([
  elanClassExport(LineVG)
], _StdLib.prototype, "LineVG", 2);
__decorateClass([
  elanClassExport(RectangleVG)
], _StdLib.prototype, "RectangleVG", 2);
__decorateClass([
  elanClassExport(ImageVG)
], _StdLib.prototype, "ImageVG", 2);
__decorateClass([
  elanClassExport(RawVG)
], _StdLib.prototype, "RawVG", 2);
__decorateClass([
  elanClassExport(List)
], _StdLib.prototype, "List", 2);
__decorateClass([
  elanClassExport(ElanArray)
], _StdLib.prototype, "Array", 2);
__decorateClass([
  elanClassExport(ElanArray2D)
], _StdLib.prototype, "Array2D", 2);
__decorateClass([
  elanClassExport(ListImmutable)
], _StdLib.prototype, "ListImmutable", 2);
__decorateClass([
  elanClassExport(Dictionary)
], _StdLib.prototype, "Dictionary", 2);
__decorateClass([
  elanClassExport(DictionaryImmutable)
], _StdLib.prototype, "DictionaryImmutable", 2);
__decorateClass([
  elanConstant(ElanInt)
], _StdLib.prototype, "black", 2);
__decorateClass([
  elanConstant(ElanInt)
], _StdLib.prototype, "grey", 2);
__decorateClass([
  elanConstant(ElanInt)
], _StdLib.prototype, "white", 2);
__decorateClass([
  elanConstant(ElanInt)
], _StdLib.prototype, "red", 2);
__decorateClass([
  elanConstant(ElanInt)
], _StdLib.prototype, "green", 2);
__decorateClass([
  elanConstant(ElanInt)
], _StdLib.prototype, "blue", 2);
__decorateClass([
  elanConstant(ElanInt)
], _StdLib.prototype, "yellow", 2);
__decorateClass([
  elanConstant(ElanInt)
], _StdLib.prototype, "brown", 2);
__decorateClass([
  elanConstant(ElanInt)
], _StdLib.prototype, "transparent", 2);
__decorateClass([
  elanConstant(ElanBoolean)
], _StdLib.prototype, "true", 2);
__decorateClass([
  elanConstant(ElanBoolean)
], _StdLib.prototype, "false", 2);
__decorateClass([
  elanConstant()
], _StdLib.prototype, "pi", 2);
__decorateClass([
  elanConstant(ElanInt)
], _StdLib.prototype, "meaningOfLife", 2);
__decorateClass([
  elanConstant(ElanString)
], _StdLib.prototype, "quotes", 2);
__decorateClass([
  elanConstant(ElanString)
], _StdLib.prototype, "openBrace", 2);
__decorateClass([
  elanConstant(ElanString)
], _StdLib.prototype, "closeBrace", 2);
__decorateClass([
  elanFunction([], 3 /* pureAsyncExtension */, ElanString),
  __decorateParam(0, elanGenericParamT1Type())
], _StdLib.prototype, "asString", 1);
__decorateClass([
  elanFunction(["value"]),
  __decorateParam(0, elanIntType())
], _StdLib.prototype, "unicode", 1);
__decorateClass([
  elanFunction(["character"], 1 /* pureExtension */, ElanInt)
], _StdLib.prototype, "asUnicode", 1);
__decorateClass([
  elanFunction(["", "item"], 1 /* pureExtension */, ElanInt),
  __decorateParam(0, elanStringType()),
  __decorateParam(1, elanStringType())
], _StdLib.prototype, "indexOf", 1);
__decorateClass([
  elanFunction(["start", "end"], 0 /* pure */, ElanClass(List, [ElanInt])),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanIntType())
], _StdLib.prototype, "sequence", 1);
__decorateClass([
  elanFunction(["start", "end", "step"], 0 /* pure */, ElanClass(List, [ElanInt])),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanIntType()),
  __decorateParam(2, elanIntType())
], _StdLib.prototype, "sequenceWithStep", 1);
__decorateClass([
  elanFunction(["instance", "match", "replacement"], 1 /* pureExtension */)
], _StdLib.prototype, "replace", 1);
__decorateClass([
  elanFunction([], 1 /* pureExtension */, ElanInt)
], _StdLib.prototype, "length", 1);
__decorateClass([
  elanFunction([], 1 /* pureExtension */)
], _StdLib.prototype, "upperCase", 1);
__decorateClass([
  elanFunction([], 1 /* pureExtension */)
], _StdLib.prototype, "lowerCase", 1);
__decorateClass([
  elanFunction(["instance", "other"], 1 /* pureExtension */)
], _StdLib.prototype, "isBefore", 1);
__decorateClass([
  elanFunction(["instance", "other"], 1 /* pureExtension */)
], _StdLib.prototype, "isAfter", 1);
__decorateClass([
  elanFunction(["instance", "other"], 1 /* pureExtension */)
], _StdLib.prototype, "isAfterOrSameAs", 1);
__decorateClass([
  elanFunction(["instance", "other"], 1 /* pureExtension */)
], _StdLib.prototype, "isBeforeOrSameAs", 1);
__decorateClass([
  elanFunction([], 1 /* pureExtension */)
], _StdLib.prototype, "trim", 1);
__decorateClass([
  elanFunction(["", "separator"], 1 /* pureExtension */, ElanClass(List, [ElanString]))
], _StdLib.prototype, "split", 1);
__decorateClass([
  elanFunction(["number"], 1 /* pureExtension */, ElanInt)
], _StdLib.prototype, "floor", 1);
__decorateClass([
  elanFunction(["number"], 1 /* pureExtension */, ElanBoolean)
], _StdLib.prototype, "isNaN", 1);
__decorateClass([
  elanFunction(["number"], 1 /* pureExtension */, ElanBoolean)
], _StdLib.prototype, "isInfinite", 1);
__decorateClass([
  elanFunction(["number", "decimalPlaces"], 1 /* pureExtension */),
  __decorateParam(1, elanIntType())
], _StdLib.prototype, "round", 1);
__decorateClass([
  elanFunction(["number"], 1 /* pureExtension */, ElanInt)
], _StdLib.prototype, "ceiling", 1);
__decorateClass([
  elanFunction(["listOfFloat"], 0 /* pure */, ElanFloat),
  __decorateParam(0, elanClassType(List, [ElanFloat]))
], _StdLib.prototype, "maxFloat", 1);
__decorateClass([
  elanFunction(["listOfInt"], 0 /* pure */, ElanInt),
  __decorateParam(0, elanClassType(List, [ElanInt]))
], _StdLib.prototype, "maxInt", 1);
__decorateClass([
  elanFunction(["listOfFloat"], 0 /* pure */, ElanFloat),
  __decorateParam(0, elanClassType(List, [ElanFloat]))
], _StdLib.prototype, "minFloat", 1);
__decorateClass([
  elanFunction(["listOfInt"], 0 /* pure */, ElanInt),
  __decorateParam(0, elanClassType(List, [ElanInt]))
], _StdLib.prototype, "minInt", 1);
__decorateClass([
  elanFunction(["", "item"], 1 /* pureExtension */)
], _StdLib.prototype, "contains", 1);
__decorateClass([
  elanProcedure(["milliseconds"], 2 /* async */),
  __decorateParam(0, elanIntType())
], _StdLib.prototype, "pause", 1);
__decorateClass([
  elanFunction([], 4 /* impure */, ElanInt)
], _StdLib.prototype, "clock", 1);
__decorateClass([
  elanFunction([], 4 /* impure */)
], _StdLib.prototype, "random", 1);
__decorateClass([
  elanFunction(["low", "high"], 4 /* impure */, ElanInt),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanIntType())
], _StdLib.prototype, "randomInt", 1);
__decorateClass([
  elanFunction(["string"], 0 /* pure */, ElanTuple([ElanBoolean, ElanFloat]))
], _StdLib.prototype, "parseAsFloat", 1);
__decorateClass([
  elanFunction(["string"], 0 /* pure */, ElanTuple([ElanBoolean, ElanInt]))
], _StdLib.prototype, "parseAsInt", 1);
__decorateClass([
  elanProcedure(["text"], 2 /* async */)
], _StdLib.prototype, "printLine", 1);
__decorateClass([
  elanProcedure(["text"], 2 /* async */)
], _StdLib.prototype, "printNoLine", 1);
__decorateClass([
  elanProcedure(["position", "text"], 2 /* async */),
  __decorateParam(0, elanIntType())
], _StdLib.prototype, "printTab", 1);
__decorateClass([
  elanProcedure([], 2 /* async */)
], _StdLib.prototype, "clearPrintedText", 1);
__decorateClass([
  elanProcedure([], 2 /* async */)
], _StdLib.prototype, "clearAllDisplays", 1);
__decorateClass([
  elanFunction(["size", "initialValue"], 0 /* pure */, ElanClass(List)),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanGenericParamT1Type())
], _StdLib.prototype, "createList", 1);
__decorateClass([
  elanFunction(["prompt"], 6 /* impureAsync */, ElanString)
], _StdLib.prototype, "inputString", 1);
__decorateClass([
  elanFunction(["prompt", "minLength", "maxLength"], 6 /* impureAsync */, ElanString),
  __decorateParam(1, elanIntType()),
  __decorateParam(2, elanIntType())
], _StdLib.prototype, "inputStringWithLimits", 1);
__decorateClass([
  elanFunction(["prompt", "options"], 6 /* impureAsync */, ElanString),
  __decorateParam(1, elanClassType(List, [ElanString]))
], _StdLib.prototype, "inputStringFromOptions", 1);
__decorateClass([
  elanFunction(["prompt"], 6 /* impureAsync */, ElanInt)
], _StdLib.prototype, "inputInt", 1);
__decorateClass([
  elanFunction(["prompt", "minValue", "maxValue"], 6 /* impureAsync */, ElanInt),
  __decorateParam(1, elanIntType()),
  __decorateParam(2, elanIntType())
], _StdLib.prototype, "inputIntBetween", 1);
__decorateClass([
  elanFunction(["prompt"], 6 /* impureAsync */, ElanFloat)
], _StdLib.prototype, "inputFloat", 1);
__decorateClass([
  elanFunction(["prompt", "minValue", "maxValue"], 6 /* impureAsync */, ElanFloat)
], _StdLib.prototype, "inputFloatBetween", 1);
__decorateClass([
  elanFunction(["number"])
], _StdLib.prototype, "abs", 1);
__decorateClass([
  elanFunction(["value"])
], _StdLib.prototype, "acos", 1);
__decorateClass([
  elanFunction(["value"])
], _StdLib.prototype, "acosDeg", 1);
__decorateClass([
  elanFunction(["value"])
], _StdLib.prototype, "asin", 1);
__decorateClass([
  elanFunction(["value"])
], _StdLib.prototype, "asinDeg", 1);
__decorateClass([
  elanFunction(["value"])
], _StdLib.prototype, "atan", 1);
__decorateClass([
  elanFunction(["value"])
], _StdLib.prototype, "atanDeg", 1);
__decorateClass([
  elanFunction(["radians"])
], _StdLib.prototype, "cos", 1);
__decorateClass([
  elanFunction(["degrees"])
], _StdLib.prototype, "cosDeg", 1);
__decorateClass([
  elanFunction(["x"])
], _StdLib.prototype, "exp", 1);
__decorateClass([
  elanFunction(["number"])
], _StdLib.prototype, "logE", 1);
__decorateClass([
  elanFunction(["number"])
], _StdLib.prototype, "log10", 1);
__decorateClass([
  elanFunction(["number"])
], _StdLib.prototype, "log2", 1);
__decorateClass([
  elanFunction(["radians"])
], _StdLib.prototype, "sin", 1);
__decorateClass([
  elanFunction(["degrees"])
], _StdLib.prototype, "sinDeg", 1);
__decorateClass([
  elanFunction(["number"])
], _StdLib.prototype, "sqrt", 1);
__decorateClass([
  elanFunction(["radians"])
], _StdLib.prototype, "tan", 1);
__decorateClass([
  elanFunction(["degrees"])
], _StdLib.prototype, "tanDeg", 1);
__decorateClass([
  elanFunction(["degrees"])
], _StdLib.prototype, "degToRad", 1);
__decorateClass([
  elanFunction(["radians"])
], _StdLib.prototype, "radToDeg", 1);
__decorateClass([
  elanFunction(["a", "b"], 0 /* pure */, ElanInt),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanIntType())
], _StdLib.prototype, "bitAnd", 1);
__decorateClass([
  elanFunction(["a", "b"], 0 /* pure */, ElanInt),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanIntType())
], _StdLib.prototype, "bitOr", 1);
__decorateClass([
  elanFunction(["a", "b"], 0 /* pure */, ElanInt),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanIntType())
], _StdLib.prototype, "bitXor", 1);
__decorateClass([
  elanFunction(["a"], 0 /* pure */, ElanInt),
  __decorateParam(0, elanIntType())
], _StdLib.prototype, "bitNot", 1);
__decorateClass([
  elanFunction(["value", "places"], 0 /* pure */, ElanInt),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanIntType())
], _StdLib.prototype, "bitShiftL", 1);
__decorateClass([
  elanFunction(["value", "places"], 0 /* pure */, ElanInt),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanIntType())
], _StdLib.prototype, "bitShiftR", 1);
__decorateClass([
  elanFunction([], 1 /* pureExtension */),
  __decorateParam(0, elanIntType())
], _StdLib.prototype, "asBinary", 1);
__decorateClass([
  elanFunction(["", "regExp"], 1 /* pureExtension */)
], _StdLib.prototype, "matchesRegExp", 1);
__decorateClass([
  elanFunction([], 1 /* pureExtension */)
], _StdLib.prototype, "asRegExp", 1);
__decorateClass([
  elanFunction([], 6 /* impureAsync */, ElanClass(TextFileReader))
], _StdLib.prototype, "openFileForReading", 1);
__decorateClass([
  elanFunction(["fileName"], 0 /* pure */, ElanClass(TextFileWriter))
], _StdLib.prototype, "createFileForWriting", 1);
__decorateClass([
  elanDeprecated(6 /* methodHidden */, 1, 1, ""),
  elanProcedure([], 2 /* async */)
], _StdLib.prototype, "waitForAnyKey", 1);
__decorateClass([
  elanProcedure(["prompt"], 2 /* async */)
], _StdLib.prototype, "pressAnyKeyToContinue", 1);
__decorateClass([
  elanFunction([], 6 /* impureAsync */, ElanString)
], _StdLib.prototype, "waitForKey", 1);
__decorateClass([
  elanFunction([], 6 /* impureAsync */, ElanString)
], _StdLib.prototype, "getKey", 1);
__decorateClass([
  elanFunction([], 6 /* impureAsync */, ElanTuple([ElanString, ElanString]))
], _StdLib.prototype, "getKeyWithModifier", 1);
__decorateClass([
  elanProcedure([], 2 /* async */)
], _StdLib.prototype, "clearKeyBuffer", 1);
__decorateClass([
  elanFunction([""], 1 /* pureExtension */),
  __decorateParam(0, elanClassType(ElanArray2D, [ElanInt]))
], _StdLib.prototype, "blocksAsHtml", 1);
__decorateClass([
  elanProcedure(["blocks"], 2 /* async */),
  __decorateParam(0, elanClassType(ElanArray2D, [ElanInt]))
], _StdLib.prototype, "displayBlocks", 1);
__decorateClass([
  elanProcedure([], 2 /* async */)
], _StdLib.prototype, "clearBlocks", 1);
__decorateClass([
  elanFunction([""], 1 /* pureExtension */),
  __decorateParam(0, elanClassType(List, [ElanT1Constrained(ElanClass(VectorGraphic))]))
], _StdLib.prototype, "vectorGraphicsAsHtml", 1);
__decorateClass([
  elanProcedure(["listOfVGs"], 2 /* async */),
  __decorateParam(0, elanClassType(List, [ElanT1Constrained(ElanClass(VectorGraphic))]))
], _StdLib.prototype, "displayVectorGraphics", 1);
__decorateClass([
  elanProcedure([], 2 /* async */)
], _StdLib.prototype, "clearVectorGraphics", 1);
__decorateClass([
  elanProcedure(["html"], 2 /* async */)
], _StdLib.prototype, "displayHtml", 1);
__decorateClass([
  elanProcedure([], 2 /* async */)
], _StdLib.prototype, "clearHtml", 1);
__decorateClass([
  elanProcedure(["durationMs", "frequencyHz", "volume"], 2 /* async */),
  __decorateParam(0, elanIntType()),
  __decorateParam(1, elanFloatType()),
  __decorateParam(2, elanFloatType())
], _StdLib.prototype, "tone", 1);
var StdLib = _StdLib;

// src/ide/stub-input-output.ts
var StubInputOutput = class {
  constructor() {
  }
  readFile() {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs(data.value);
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("readFile"));
    });
  }
  writeFile(fileName, data) {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data2 = e.data;
        if (data2.type === "read") {
          rs();
        }
        if (data2.type === "status" && data2.status === "error") {
          rj(data2.error);
        }
      };
      postMessage(this.writeMsg("writeFile", [fileName, data]));
    });
  }
  writeMsg(func, parameters) {
    return { type: "write", function: func, parameters: parameters ?? [] };
  }
  drawBlockGraphics(html) {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("drawBlockGraphics", [html]));
    });
  }
  clearBlockGraphics() {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("clearBlockGraphics"));
    });
  }
  drawVectorGraphics(html) {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("drawVectorGraphics", [html]));
    });
  }
  clearVectorGraphics() {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("clearVectorGraphics"));
    });
  }
  clearDisplay() {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("clearAllGraphics"));
    });
  }
  printLine(text) {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("printLine", [text]));
    });
  }
  print(text) {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("print", [text]));
    });
  }
  printTab(position, text) {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("printTab", [position, text]));
    });
  }
  stopReading() {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("stopReading"));
    });
  }
  readLine() {
    return new Promise((rs) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs(data.value);
        }
      };
      postMessage(this.writeMsg("readLine"));
    });
  }
  waitForAnyKey() {
    return new Promise((rs) => {
      onmessage = (_e) => {
        rs();
      };
      postMessage(this.writeMsg("waitForAnyKey"));
    });
  }
  waitForKey() {
    return new Promise((rs) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs(data.value);
        }
      };
      postMessage(this.writeMsg("waitForKey"));
    });
  }
  getKey() {
    return new Promise((rs) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs(data.value);
        }
      };
      postMessage(this.writeMsg("getKey"));
    });
  }
  getModKey(e) {
    return e.ctrlKey ? "Control" : e.shiftKey ? "Shift" : e.altKey ? "Alt" : "";
  }
  getKeyWithModifier() {
    return new Promise((rs) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs(data.value);
        }
      };
      postMessage(this.writeMsg("getKeyWithModifier"));
    });
  }
  clearKeyBuffer() {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("clearKeyBuffer"));
    });
  }
  clearPrintedText() {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("clearPrintedText"));
    });
  }
  clearSystemInfo() {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("clearSystemInfo"));
    });
  }
  drawHtml(html) {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("drawHtml", [html]));
    });
  }
  clearHtml() {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("clearHtml"));
    });
  }
  tone(duration, frequency, volume) {
    return new Promise((rs, rj) => {
      onmessage = (e) => {
        const data = e.data;
        if (data.type === "read") {
          rs();
        }
        if (data.type === "status" && data.status === "error") {
          rj(data.error);
        }
      };
      postMessage(this.writeMsg("tone", [duration, frequency, volume]));
    });
  }
  breakPoint(allScopedSymbols2, id, singlestep) {
    let paused = true;
    let nextPause = false;
    addEventListener("message", async (e) => {
      if (e.data.type === "resume") {
        paused = false;
      }
      if (e.data.type === "pause") {
        nextPause = true;
      }
    });
    return new Promise((rs) => {
      postMessage({
        type: singlestep ? "singlestep" : "breakpoint",
        value: allScopedSymbols2,
        pausedAt: id
      });
      const timeOut = setInterval(async () => {
        if (!paused) {
          clearInterval(timeOut);
          rs(nextPause);
        }
      }, 1);
    });
  }
};
export {
  StdLib,
  StubInputOutput
};
/*! Bundled license information:

reflect-metadata/Reflect.js:
  (*! *****************************************************************************
  Copyright (C) Microsoft. All rights reserved.
  Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  this file except in compliance with the License. You may obtain a copy of the
  License at http://www.apache.org/licenses/LICENSE-2.0
  
  THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
  WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
  MERCHANTABLITY OR NON-INFRINGEMENT.
  
  See the Apache Version 2.0 License for specific language governing permissions
  and limitations under the License.
  ***************************************************************************** *)
*/
