@thigasdevelopment/luam 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/luam.mjs CHANGED
@@ -3609,6 +3609,8 @@ var LUA_KEYWORDS = /* @__PURE__ */ new Set([
3609
3609
  "while"
3610
3610
  ]);
3611
3611
  var LUAM_KEYWORDS = /* @__PURE__ */ new Set([
3612
+ "async",
3613
+ "await",
3612
3614
  "class",
3613
3615
  "constructor",
3614
3616
  "continue",
@@ -4279,7 +4281,20 @@ function parseParameters(stream) {
4279
4281
  stream.expect("punctuation", ")");
4280
4282
  return parameters;
4281
4283
  }
4282
- function parseFunctionExpression(stream) {
4284
+ var ASYNC_MODIFIER = "async";
4285
+ function isAsyncFunctionStart(stream, offset = 0) {
4286
+ return stream.checkAhead(offset, "keyword", ASYNC_MODIFIER) && stream.checkAhead(offset + 1, "keyword", "function");
4287
+ }
4288
+ function consumeAsyncModifier(stream) {
4289
+ if (!isAsyncFunctionStart(stream)) {
4290
+ return false;
4291
+ }
4292
+ const checkpoint = stream.checkpoint();
4293
+ stream.next();
4294
+ stream.eraseToCurrent(checkpoint);
4295
+ return true;
4296
+ }
4297
+ function parseFunctionExpression(stream, isAsync = false) {
4283
4298
  const position2 = stream.expect("keyword", "function").position;
4284
4299
  const typeParameters = parseTypeParameters(stream);
4285
4300
  const parameters = parseParameters(stream);
@@ -4288,6 +4303,7 @@ function parseFunctionExpression(stream) {
4288
4303
  stream.expect("keyword", "end");
4289
4304
  return {
4290
4305
  kind: "function-expression",
4306
+ isAsync,
4291
4307
  typeParameters: typeParameters.names,
4292
4308
  typeConstraints: typeParameters.constraints,
4293
4309
  parameters,
@@ -4309,7 +4325,7 @@ function parseFunctionName(stream) {
4309
4325
  const property = stream.expect("identifier").value;
4310
4326
  return { name: { kind: "member-expression", object: name, property, position: token.position }, isMethod: true };
4311
4327
  }
4312
- function parseFunctionDeclaration(stream, isLocal, isExported = false, isHttpExport = false) {
4328
+ function parseFunctionDeclaration(stream, isLocal, isExported = false, isHttpExport = false, isAsync = false) {
4313
4329
  const position2 = stream.expect("keyword", "function").position;
4314
4330
  const { name, isMethod } = parseFunctionName(stream);
4315
4331
  const typeParameters = parseTypeParameters(stream);
@@ -4320,6 +4336,7 @@ function parseFunctionDeclaration(stream, isLocal, isExported = false, isHttpExp
4320
4336
  return {
4321
4337
  kind: "function-declaration",
4322
4338
  name,
4339
+ isAsync,
4323
4340
  isLocal,
4324
4341
  isExported,
4325
4342
  isHttpExport,
@@ -4374,6 +4391,14 @@ function isRightAssociative(operator) {
4374
4391
 
4375
4392
  // ../compiler/src/parser/expression.ts
4376
4393
  var LITERAL_KEYWORDS = /* @__PURE__ */ new Set(["nil", "true", "false"]);
4394
+ var AWAIT_OPERATOR = "await";
4395
+ function isAwaitStart(stream) {
4396
+ return stream.check("keyword", AWAIT_OPERATOR);
4397
+ }
4398
+ function parseAwaitExpression(stream) {
4399
+ const position2 = stream.next().position;
4400
+ return { kind: "await-expression", operand: parseSuffixed(stream), position: position2 };
4401
+ }
4377
4402
  function parseKeywordLiteral(token) {
4378
4403
  if (token.value === "nil") {
4379
4404
  return { kind: "nil-literal", position: token.position };
@@ -4432,6 +4457,10 @@ function parsePrimary(stream) {
4432
4457
  stream.next();
4433
4458
  return { kind: "identifier", name: token.value, position: token.position };
4434
4459
  }
4460
+ if (isAsyncFunctionStart(stream)) {
4461
+ consumeAsyncModifier(stream);
4462
+ return parseFunctionExpression(stream, true);
4463
+ }
4435
4464
  if (token.kind === "identifier") {
4436
4465
  stream.next();
4437
4466
  return { kind: "identifier", name: token.value, position: token.position };
@@ -4524,6 +4553,9 @@ function parseSuffixed(stream) {
4524
4553
  }
4525
4554
  }
4526
4555
  function parseUnary(stream) {
4556
+ if (isAwaitStart(stream)) {
4557
+ return parseAwaitExpression(stream);
4558
+ }
4527
4559
  const token = stream.current();
4528
4560
  const isUnary2 = (token.kind === "operator" || token.kind === "keyword") && UNARY_OPERATORS.has(token.value);
4529
4561
  if (!isUnary2) {
@@ -4715,12 +4747,14 @@ function parseDecorators(stream) {
4715
4747
  }
4716
4748
  return decorators;
4717
4749
  }
4718
- function parseClassMethod(stream, token, decorators, isStatic) {
4750
+ function parseClassMethod(stream, token, decorators, isStatic, isAsync) {
4719
4751
  stream.expect("operator", "=");
4720
- const expression = parseFunctionExpression(stream);
4752
+ const modified = consumeAsyncModifier(stream) || isAsync;
4753
+ const expression = parseFunctionExpression(stream, modified);
4721
4754
  return {
4722
4755
  kind: "class-method",
4723
4756
  name: token.value,
4757
+ isAsync: modified,
4724
4758
  isConstructor: token.value === "constructor",
4725
4759
  isSynthetic: false,
4726
4760
  isStatic,
@@ -4733,13 +4767,14 @@ function parseClassMethod(stream, token, decorators, isStatic) {
4733
4767
  position: token.position
4734
4768
  };
4735
4769
  }
4736
- function parseBraceClassMethod(stream, token, decorators, isStatic) {
4770
+ function parseBraceClassMethod(stream, token, decorators, isStatic, isAsync) {
4737
4771
  const parameters = parseParameters(stream);
4738
4772
  const returnAnnotation = parseOptionalAnnotation(stream);
4739
4773
  const body = parseBraceBlock(stream);
4740
4774
  return {
4741
4775
  kind: "class-method",
4742
4776
  name: token.value,
4777
+ isAsync,
4743
4778
  isConstructor: token.value === "constructor",
4744
4779
  isSynthetic: false,
4745
4780
  isStatic,
@@ -4772,12 +4807,12 @@ function expectClassFieldBoundary(stream, token) {
4772
4807
  throw stream.error(`Expected a line break or separator after class member "${token.value}".`, "parse-unexpected-token");
4773
4808
  }
4774
4809
  var STATIC_MODIFIER = "static";
4775
- function parseStaticModifier(stream) {
4776
- if (!stream.check("identifier", STATIC_MODIFIER)) {
4810
+ function parseMemberModifier(stream, modifier, kind = "identifier") {
4811
+ if (!stream.check(kind, modifier)) {
4777
4812
  return false;
4778
4813
  }
4779
- const modifier = stream.current();
4780
- if (!stream.checkName(1) || stream.peek(1).position.line !== modifier.position.line) {
4814
+ const token = stream.current();
4815
+ if (!stream.checkName(1) || stream.peek(1).position.line !== token.position.line) {
4781
4816
  return false;
4782
4817
  }
4783
4818
  const checkpoint = stream.checkpoint();
@@ -4787,14 +4822,15 @@ function parseStaticModifier(stream) {
4787
4822
  }
4788
4823
  function parseClassMember(stream) {
4789
4824
  const decorators = parseDecorators(stream);
4790
- const isStatic = parseStaticModifier(stream);
4825
+ const isStatic = parseMemberModifier(stream, STATIC_MODIFIER);
4826
+ const isAsync = parseMemberModifier(stream, ASYNC_MODIFIER, "keyword");
4791
4827
  const token = stream.expectMemberKey();
4792
4828
  if (stream.check("punctuation", "(")) {
4793
4829
  stream.report("parse-class-method-form", `Write class member "${token.value}" as "${token.value} = function (...) ... end".`, token.position);
4794
- return parseBraceClassMethod(stream, token, decorators, isStatic);
4830
+ return parseBraceClassMethod(stream, token, decorators, isStatic, isAsync);
4795
4831
  }
4796
- if (stream.check("operator", "=") && stream.checkAhead(1, "keyword", "function")) {
4797
- return parseClassMethod(stream, token, decorators, isStatic);
4832
+ if (stream.check("operator", "=") && (stream.checkAhead(1, "keyword", "function") || isAsyncFunctionStart(stream, 1))) {
4833
+ return parseClassMethod(stream, token, decorators, isStatic, isAsync);
4798
4834
  }
4799
4835
  const annotation = parseFieldAnnotation(stream);
4800
4836
  const value = stream.match("operator", "=") ? parseFieldValue(stream) : null;
@@ -5075,6 +5111,10 @@ function parseGlobalDeclaration(stream) {
5075
5111
  return null;
5076
5112
  }
5077
5113
  function parseExpressionStatement(stream) {
5114
+ if (isAwaitStart(stream)) {
5115
+ const expression = parseAwaitExpression(stream);
5116
+ return { kind: "call-statement", expression, position: expression.position };
5117
+ }
5078
5118
  const declaration = parseGlobalDeclaration(stream);
5079
5119
  if (declaration !== null) {
5080
5120
  return declaration;
@@ -5106,6 +5146,10 @@ function parseKeywordStatement(stream, value) {
5106
5146
  if (stream.check("keyword", "function")) {
5107
5147
  return parseFunctionDeclaration(stream, true);
5108
5148
  }
5149
+ if (isAsyncFunctionStart(stream)) {
5150
+ consumeAsyncModifier(stream);
5151
+ return parseFunctionDeclaration(stream, true, false, false, true);
5152
+ }
5109
5153
  const isEnum = stream.check("keyword", "enum") && stream.checkAhead(1, "identifier");
5110
5154
  return isEnum ? parseEnumDeclaration(stream, true) : parseLocalStatement(stream, token.position);
5111
5155
  }
@@ -5148,6 +5192,10 @@ function parseStatement(stream) {
5148
5192
  return statement;
5149
5193
  }
5150
5194
  }
5195
+ if (isAsyncFunctionStart(stream)) {
5196
+ consumeAsyncModifier(stream);
5197
+ return parseFunctionDeclaration(stream, false, false, false, true);
5198
+ }
5151
5199
  if (isTypeAlias(stream)) {
5152
5200
  return parseTypeAlias(stream);
5153
5201
  }
@@ -5794,9 +5842,16 @@ var RUNTIME_HELPERS = {
5794
5842
  },
5795
5843
  env: { name: "env", file: "env.lua", injection: "manual", features: [], environment: "server" },
5796
5844
  math: { name: "math", file: "math.lua", injection: "automatic", features: ["number-extension"] },
5845
+ promise: {
5846
+ name: "promise",
5847
+ file: "promise.lua",
5848
+ injection: "reference",
5849
+ features: ["async-function"],
5850
+ globals: ["Promise", "delay", "sleep"]
5851
+ },
5797
5852
  string: { name: "string", file: "string.lua", injection: "automatic", features: ["string-extension", "template-string"] },
5798
5853
  table: { name: "table", file: "table.lua", injection: "automatic", features: ["table-extension"] },
5799
- threads: { name: "threads", file: "threads.lua", injection: "reference", features: ["thread"], globals: ["sleep", "Threads"] },
5854
+ threads: { name: "threads", file: "threads.lua", injection: "reference", features: ["thread"], globals: ["Threads"], requires: ["promise"] },
5800
5855
  validate: { name: "validate", file: "validate.lua", injection: "automatic", features: ["boundary-validation"] }
5801
5856
  };
5802
5857
  var DEVELOPMENT_RUNTIME_HELPERS = {
@@ -7099,7 +7154,7 @@ import { tmpdir } from "node:os";
7099
7154
  import { join as join2 } from "node:path";
7100
7155
 
7101
7156
  // src/cli/version.ts
7102
- var VERSION = true ? "1.0.0" : "0.0.0-dev";
7157
+ var VERSION = true ? "1.0.2" : "0.0.0-dev";
7103
7158
  var PROGRAM_NAME = "luam";
7104
7159
  var PROGRAM_DESCRIPTION = "luam \u2014 the Luam compiler for Multi Theft Auto resources.";
7105
7160
 
@@ -8987,7 +9042,7 @@ var EMPTY_AMBIENT = { classes: [], interfaces: [], enums: [], aliases: [], globa
8987
9042
  function ambientFromRegistry(registry) {
8988
9043
  return {
8989
9044
  classes: registry.allClasses(),
8990
- interfaces: registry.allInterfaces(),
9045
+ interfaces: registry.allInterfaces().filter((info) => info.isBuiltin !== true),
8991
9046
  enums: registry.allEnums().filter((info) => info.isLocal !== true),
8992
9047
  aliases: registry.allAliases(),
8993
9048
  globals: registry.allGlobals(),
@@ -9155,6 +9210,74 @@ function descriptorToType(descriptor) {
9155
9210
  return PRIMITIVES[descriptor.kind] ?? ANY_TYPE;
9156
9211
  }
9157
9212
 
9213
+ // ../compiler/src/checker/async.ts
9214
+ var PROMISE_TYPE = "Promise";
9215
+ var SLEEP_FUNCTION = "sleep";
9216
+ var PROMISE_PARAMETER = "T";
9217
+ var ORIGIN = { line: 0, column: 0, offset: 0 };
9218
+ var AWAIT_OUTSIDE_MESSAGE = '"await" is only valid inside an async function. Declare the function "async function name()", or wait on the promise with ":next(...)".';
9219
+ var ASYNC_ANNOTATION_MESSAGE = 'An async function is annotated with the type it resolves to, not with "Promise". Write the inner type and the signature becomes a promise of it.';
9220
+ var SLEEP_OUTSIDE_MESSAGE = '"sleep" suspends a coroutine and there is none here. Declare the function "async function name()", or run the body as a thread pool job.';
9221
+ function promiseOf(inner) {
9222
+ return createNamed(PROMISE_TYPE, [inner]);
9223
+ }
9224
+ function isPromiseType(type) {
9225
+ return (type.kind === "named" || type.kind === "record") && type.name === PROMISE_TYPE;
9226
+ }
9227
+ function declarePromiseType(declarations) {
9228
+ const value = createNamed(PROMISE_PARAMETER);
9229
+ const onFulfilled = createFunction([value], ANY_TYPE, 1, false, ["value"]);
9230
+ const onRejected = createFunction([ANY_TYPE], ANY_TYPE, 1, false, ["reason"]);
9231
+ const chained = promiseOf(ANY_TYPE);
9232
+ const next = createFunction([onFulfilled, createOptional(onRejected)], chained, 1, false, ["onFulfilled", "onRejected"]);
9233
+ const failure3 = createFunction([onRejected], chained, 1, false, ["onRejected"]);
9234
+ declarations.declareInterface({
9235
+ name: PROMISE_TYPE,
9236
+ isBuiltin: true,
9237
+ typeParameters: [PROMISE_PARAMETER],
9238
+ typeConstraints: [null],
9239
+ superInterfaces: [],
9240
+ members: /* @__PURE__ */ new Map([
9241
+ ["next", { name: "next", type: next, isMethod: true, position: ORIGIN }],
9242
+ ["catch", { name: "catch", type: failure3, isMethod: true, position: ORIGIN }]
9243
+ ]),
9244
+ position: ORIGIN
9245
+ });
9246
+ }
9247
+ function awaitedType(context, operand, expression) {
9248
+ if (!context.inAsyncBody()) {
9249
+ context.report("check-await-outside-async", AWAIT_OUTSIDE_MESSAGE, expression.position);
9250
+ return ANY_TYPE;
9251
+ }
9252
+ if (operand.kind === "any" || operand.kind === "unknown") {
9253
+ return ANY_TYPE;
9254
+ }
9255
+ if (isPromiseType(operand)) {
9256
+ return (operand.kind === "named" ? operand.typeArguments?.[0] : ANY_TYPE) ?? ANY_TYPE;
9257
+ }
9258
+ const message = `"await" expects a promise but received "${typeToString(operand)}". Only an async function or "new Promise(...)" produces one.`;
9259
+ context.report("check-await-non-promise", message, expression.position);
9260
+ return ANY_TYPE;
9261
+ }
9262
+ function isPromiseAnnotation(isAsync, annotation) {
9263
+ return isAsync && annotation !== null && annotation.kind === "type-name" && annotation.name === PROMISE_TYPE;
9264
+ }
9265
+ function asyncInnerAnnotation(isAsync, annotation) {
9266
+ return isPromiseAnnotation(isAsync, annotation) ? null : annotation;
9267
+ }
9268
+ function reportAsyncAnnotation(context, isAsync, annotation) {
9269
+ if (!isPromiseAnnotation(isAsync, annotation) || annotation === null) {
9270
+ return;
9271
+ }
9272
+ context.report("check-async-return-annotation", ASYNC_ANNOTATION_MESSAGE, annotation.position);
9273
+ }
9274
+ function reportSleepOutsideAsync(context, name, position2) {
9275
+ if (name !== SLEEP_FUNCTION || context.declaredGlobals.has(name) || context.binder.lookup(name)?.isLocal === true || context.suspendable()) {
9276
+ return;
9277
+ }
9278
+ context.warn("check-sleep-outside-async", SLEEP_OUTSIDE_MESSAGE, position2);
9279
+ }
9280
+
9158
9281
  // ../compiler/src/checker/binder.ts
9159
9282
  var Binder = class {
9160
9283
  scopes = [/* @__PURE__ */ new Map()];
@@ -9486,6 +9609,17 @@ var LUA_GLOBALS = {
9486
9609
  };
9487
9610
 
9488
9611
  // ../mta-types/src/luam-runtime.ts
9612
+ var PROMISE_VALUE = named("Promise");
9613
+ var RESOLVE = fn([ANY], VOID, 0, true, ["values"]);
9614
+ var REJECT = fn([ANY], VOID, 0, true, ["reason"]);
9615
+ var EXECUTOR = fn([RESOLVE, REJECT], ANY, 2, false, ["resolve", "reject"]);
9616
+ var ON_FULFILLED = fn([ANY], ANY, 0, true, ["value"]);
9617
+ var ON_REJECTED = fn([ANY], ANY, 1, false, ["reason"]);
9618
+ var PROMISE = record("Promise", [
9619
+ { name: "next", type: fn([ON_FULFILLED, optionalOf(ON_REJECTED)], PROMISE_VALUE, 1, false, ["onFulfilled", "onRejected"]) },
9620
+ { name: "catch", type: fn([ON_REJECTED], PROMISE_VALUE, 1, false, ["onRejected"]) }
9621
+ ]);
9622
+ var JOB = tupleOf([NUMBER, PROMISE]);
9489
9623
  var THREAD = record("Thread", [
9490
9624
  { name: "get", type: fn([], NUMBER, 0) },
9491
9625
  { name: "set", type: fn([NUMBER], BOOLEAN, 1) },
@@ -9494,8 +9628,10 @@ var THREAD = record("Thread", [
9494
9628
  { name: "isPaused", type: fn([], BOOLEAN, 0) },
9495
9629
  { name: "isStarted", type: fn([], BOOLEAN, 0) }
9496
9630
  ]);
9631
+ var JOB_BODY = fn([THREAD], ANY, 0, true, ["thread"]);
9632
+ var TASK_BODY = fn([ANY], ANY, 0, true, ["values"]);
9497
9633
  var THREADS = record("Threads", [
9498
- { name: "add", type: fn([ANY, TABLE], NUMBER, 1, true) },
9634
+ { name: "add", type: fn([JOB_BODY, TABLE], JOB, 1, true, ["target", "options"]) },
9499
9635
  { name: "remove", type: fn([NUMBER], BOOLEAN, 1) },
9500
9636
  { name: "clear", type: fn([], BOOLEAN, 0) },
9501
9637
  { name: "start", type: fn([], BOOLEAN, 0) },
@@ -9503,18 +9639,31 @@ var THREADS = record("Threads", [
9503
9639
  { name: "getType", type: fn([], STRING, 0) }
9504
9640
  ]);
9505
9641
  var ASYNC = record("Async", [
9506
- { name: "map", type: fn([TABLE, ANY, ANY], NUMBER, 2) },
9507
- { name: "iterate", type: fn([NUMBER, NUMBER, NUMBER, ANY, ANY], NUMBER, 4) },
9508
- { name: "foreach", type: fn([TABLE, ANY, ANY], NUMBER, 2) },
9642
+ { name: "map", type: fn([TABLE, ANY, ANY], JOB, 2) },
9643
+ { name: "iterate", type: fn([NUMBER, NUMBER, NUMBER, ANY, ANY], JOB, 4) },
9644
+ { name: "foreach", type: fn([TABLE, ANY, ANY], JOB, 2) },
9509
9645
  { name: "getInterval", type: fn([], NUMBER, 0) },
9510
9646
  { name: "setInterval", type: fn([NUMBER], BOOLEAN, 1) }
9511
9647
  ]);
9648
+ var PROMISE_LIBRARY = record("PromiseLibrary", [
9649
+ { name: "new", type: fn([EXECUTOR], PROMISE, 1, false, ["executor"]) },
9650
+ { name: "spawn", type: fn([TASK_BODY], PROMISE, 1, true, ["target"]) },
9651
+ { name: "resolve", type: fn([ANY], PROMISE, 0, true) },
9652
+ { name: "reject", type: fn([ANY], PROMISE, 0, true) },
9653
+ { name: "all", type: fn([arrayOf(ANY)], PROMISE, 1) },
9654
+ { name: "race", type: fn([arrayOf(ANY)], PROMISE, 1) },
9655
+ { name: "settle", type: fn([PROMISE], tupleOf([BOOLEAN, ANY]), 1) },
9656
+ { name: "await", type: fn([PROMISE], ANY, 1) },
9657
+ { name: "delay", type: fn([NUMBER], PROMISE, 1) }
9658
+ ]);
9512
9659
  var LUAM_RUNTIME_SERVER_GLOBALS = {};
9513
9660
  var LUAM_RUNTIME_GLOBALS = {
9514
9661
  bind: fn([ANY, ANY], ANY, 2),
9515
9662
  getClass: fn([STRING], optionalOf(TABLE), 1),
9516
9663
  getClasses: fn([], TABLE, 0),
9517
9664
  sleep: fn([NUMBER], ANY, 1),
9665
+ delay: fn([NUMBER], PROMISE, 1),
9666
+ Promise: PROMISE_LIBRARY,
9518
9667
  Thread: THREAD,
9519
9668
  Threads: record("ThreadsLibrary", [{ name: "new", type: fn([STRING, STRING], THREADS, 0) }]),
9520
9669
  Async: record("AsyncLibrary", [{ name: "new", type: fn([NUMBER], ASYNC, 0) }])
@@ -14591,6 +14740,7 @@ var CheckContext = class {
14591
14740
  isDeclarationFile = false;
14592
14741
  returnStack = [];
14593
14742
  methodStack = [];
14743
+ functionStack = [];
14594
14744
  projectEnvironments = /* @__PURE__ */ new Map();
14595
14745
  predeclared = /* @__PURE__ */ new Map();
14596
14746
  ambientClasses = /* @__PURE__ */ new Set();
@@ -14606,6 +14756,7 @@ var CheckContext = class {
14606
14756
  this.environment = environment;
14607
14757
  this.mtaClasses = oop ? mtaClassRegistry() : null;
14608
14758
  this.binder.useBuiltins(builtinSymbols(environment));
14759
+ declarePromiseType(this.declarations);
14609
14760
  this.declareProject(project);
14610
14761
  this.declareAmbient(ambient);
14611
14762
  }
@@ -14779,6 +14930,18 @@ var CheckContext = class {
14779
14930
  currentClassMethod() {
14780
14931
  return this.methodStack[this.methodStack.length - 1] ?? null;
14781
14932
  }
14933
+ pushFunctionFrame(frame) {
14934
+ this.functionStack.push(frame);
14935
+ }
14936
+ popFunctionFrame() {
14937
+ this.functionStack.pop();
14938
+ }
14939
+ inAsyncBody() {
14940
+ return this.functionStack[this.functionStack.length - 1]?.isAsync === true;
14941
+ }
14942
+ suspendable() {
14943
+ return this.functionStack.some((frame) => frame.isAsync || frame.isExpression);
14944
+ }
14782
14945
  resolveAnnotation(annotation) {
14783
14946
  if (annotation === null) {
14784
14947
  return ANY_TYPE;
@@ -15040,6 +15203,7 @@ function childExpressions(expression) {
15040
15203
  case "binary-expression":
15041
15204
  return [expression.left, expression.right];
15042
15205
  case "unary-expression":
15206
+ case "await-expression":
15043
15207
  return [expression.operand];
15044
15208
  case "group-expression":
15045
15209
  return [expression.expression];
@@ -15615,6 +15779,7 @@ function accessorMethod(field2, decorator, name) {
15615
15779
  return {
15616
15780
  kind: "class-method",
15617
15781
  name,
15782
+ isAsync: false,
15618
15783
  isConstructor: false,
15619
15784
  isSynthetic: true,
15620
15785
  isStatic: false,
@@ -15628,7 +15793,7 @@ function accessorMethod(field2, decorator, name) {
15628
15793
  };
15629
15794
  }
15630
15795
  function generatedMethod(field2, name, parameters, returnAnnotation, kind, fields) {
15631
- return { kind: "class-method", name, isConstructor: false, isSynthetic: true, isStatic: false, typeParameters: [], typeConstraints: [], parameters, returnAnnotation, body: [], decorators: [], generated: { kind, fields }, position: field2.position };
15796
+ return { kind: "class-method", name, isAsync: false, isConstructor: false, isSynthetic: true, isStatic: false, typeParameters: [], typeConstraints: [], parameters, returnAnnotation, body: [], decorators: [], generated: { kind, fields }, position: field2.position };
15632
15797
  }
15633
15798
  function typeName(name, node) {
15634
15799
  return { kind: "type-name", name, typeArguments: [], position: node.position };
@@ -15663,6 +15828,7 @@ function staticMethod(statement, name, returnAnnotation, kind, descriptor) {
15663
15828
  return {
15664
15829
  kind: "class-method",
15665
15830
  name,
15831
+ isAsync: false,
15666
15832
  isConstructor: false,
15667
15833
  isSynthetic: true,
15668
15834
  isStatic: true,
@@ -15818,6 +15984,7 @@ function childExpressions2(expression) {
15818
15984
  case "binary-expression":
15819
15985
  return [expression.left, expression.right];
15820
15986
  case "unary-expression":
15987
+ case "await-expression":
15821
15988
  return [expression.operand];
15822
15989
  case "group-expression":
15823
15990
  return [expression.expression];
@@ -20721,7 +20888,7 @@ function checkEventDeclaration(context, declaration) {
20721
20888
  }
20722
20889
 
20723
20890
  // ../compiler/src/checker/statements.ts
20724
- var ORIGIN = { line: 0, column: 0, offset: 0 };
20891
+ var ORIGIN2 = { line: 0, column: 0, offset: 0 };
20725
20892
  function minimumArguments(context, parameters) {
20726
20893
  const index = parameters.findIndex((parameter) => {
20727
20894
  const type = context.resolveAnnotation(parameter.annotation);
@@ -20729,14 +20896,17 @@ function minimumArguments(context, parameters) {
20729
20896
  });
20730
20897
  return index === -1 ? parameters.length : index;
20731
20898
  }
20732
- function buildFunctionType(context, parameters, returnAnnotation, contextual = null) {
20899
+ function buildFunctionType(context, parameters, returnAnnotation, contextual = null, isAsync = false) {
20733
20900
  const isVariadic = parameters.some((parameter) => parameter.isVararg);
20734
20901
  const named2 = parameters.filter((parameter) => !parameter.isVararg);
20735
20902
  const types = named2.map(
20736
20903
  (parameter, index) => parameter.annotation === null ? contextual?.parameters[index] ?? ANY_TYPE : context.resolveValueAnnotation(parameter.annotation, "a parameter")
20737
20904
  );
20738
20905
  const names = named2.map((parameter) => parameter.name);
20739
- return createFunction(types, context.resolveAnnotation(returnAnnotation), minimumArguments(context, parameters), isVariadic, names);
20906
+ reportAsyncAnnotation(context, isAsync, returnAnnotation);
20907
+ const declared = context.resolveAnnotation(asyncInnerAnnotation(isAsync, returnAnnotation));
20908
+ const returnType = isAsync ? promiseOf(declared) : declared;
20909
+ return createFunction(types, returnType, minimumArguments(context, parameters), isVariadic, names);
20740
20910
  }
20741
20911
  function applyTypeParameters(context, type, names, constraints) {
20742
20912
  if (names.length === 0) {
@@ -20762,14 +20932,16 @@ function reportMissingReturn(context, declared, position2) {
20762
20932
  const repair = declared.kind === "tuple" ? "Add a return on every path." : `Add a return on every path, or declare "${name}?".`;
20763
20933
  context.report("check-missing-return", `This function declares "${name}" but can end without returning a value. ${repair}`, position2);
20764
20934
  }
20765
- function checkFunctionBody(context, parameters, returnAnnotation, body, signature2, selfType2, position2 = ORIGIN) {
20935
+ function checkFunctionBody(context, parameters, returnAnnotation, body, signature2, selfType2, position2 = ORIGIN2, frame = { isAsync: false, isExpression: false }) {
20766
20936
  forgetAssignedPaths(context, body);
20767
20937
  const entry = context.flowState;
20938
+ const annotation = asyncInnerAnnotation(frame.isAsync, returnAnnotation);
20768
20939
  context.setFlow(cloneFlow(entry));
20769
20940
  context.binder.pushScope();
20770
- context.pushReturnType(returnAnnotation === null ? null : context.resolveAnnotation(returnAnnotation));
20941
+ context.pushFunctionFrame(frame);
20942
+ context.pushReturnType(annotation === null ? null : context.resolveAnnotation(annotation));
20771
20943
  if (selfType2 !== null) {
20772
- context.binder.declare({ name: "self", type: selfType2, isLocal: true, position: ORIGIN });
20944
+ context.binder.declare({ name: "self", type: selfType2, isLocal: true, position: ORIGIN2 });
20773
20945
  }
20774
20946
  let parameterIndex = 0;
20775
20947
  for (const parameter of parameters) {
@@ -20789,9 +20961,10 @@ function checkFunctionBody(context, parameters, returnAnnotation, body, signatur
20789
20961
  reportMissingReturn(context, declared, position2);
20790
20962
  }
20791
20963
  const inferred = context.popReturnType();
20792
- if (returnAnnotation === null) {
20793
- signature2.returnType = inferred;
20964
+ if (annotation === null) {
20965
+ signature2.returnType = frame.isAsync ? promiseOf(inferred) : inferred;
20794
20966
  }
20967
+ context.popFunctionFrame();
20795
20968
  context.binder.popScope();
20796
20969
  context.setFlow(entry);
20797
20970
  }
@@ -20931,7 +21104,7 @@ function reportShadowedAssignment(context, target) {
20931
21104
  }
20932
21105
  }
20933
21106
  function checkFunctionDeclaration(context, statement) {
20934
- const built = buildFunctionType(context, statement.parameters, statement.returnAnnotation);
21107
+ const built = buildFunctionType(context, statement.parameters, statement.returnAnnotation, null, statement.isAsync);
20935
21108
  const type = applyTypeParameters(context, built, statement.typeParameters, statement.typeConstraints);
20936
21109
  if (statement.name.kind === "identifier") {
20937
21110
  const symbol = { name: statement.name.name, type, isLocal: statement.isLocal, position: statement.position };
@@ -20946,7 +21119,10 @@ function checkFunctionDeclaration(context, statement) {
20946
21119
  reportShadowedAssignment(context, statement.name);
20947
21120
  }
20948
21121
  context.record(statement.name, type);
20949
- checkFunctionBody(context, statement.parameters, statement.returnAnnotation, statement.body, type, statement.isMethod ? ANY_TYPE : null, statement.position);
21122
+ checkFunctionBody(context, statement.parameters, statement.returnAnnotation, statement.body, type, statement.isMethod ? ANY_TYPE : null, statement.position, {
21123
+ isAsync: statement.isAsync,
21124
+ isExpression: false
21125
+ });
20950
21126
  }
20951
21127
  function checkReturn(context, statement) {
20952
21128
  const valueTypes = checkValueList(context, statement.values);
@@ -21299,6 +21475,9 @@ function checkMethodCall(context, expression, method, receiver) {
21299
21475
  return checkSignature(context, expression.args, member.type, expression.position);
21300
21476
  }
21301
21477
  function checkCall(context, expression) {
21478
+ if (expression.method === null && expression.callee.kind === "identifier") {
21479
+ reportSleepOutsideAsync(context, expression.callee.name, expression.position);
21480
+ }
21302
21481
  const contracted = checkResourceCall(context, expression);
21303
21482
  if (contracted !== null) {
21304
21483
  return context.record(expression, contracted);
@@ -21430,9 +21609,12 @@ function checkMultiValueExpression(context, expression, expected = null) {
21430
21609
  case "table-expression":
21431
21610
  return checkTable(context, expression);
21432
21611
  case "function-expression": {
21433
- const built = buildFunctionType(context, expression.parameters, expression.returnAnnotation, contextualFunction(expected));
21612
+ const built = buildFunctionType(context, expression.parameters, expression.returnAnnotation, contextualFunction(expected), expression.isAsync);
21434
21613
  const type = applyTypeParameters(context, built, expression.typeParameters, expression.typeConstraints);
21435
- checkFunctionBody(context, expression.parameters, expression.returnAnnotation, expression.body, type, null, expression.position);
21614
+ checkFunctionBody(context, expression.parameters, expression.returnAnnotation, expression.body, type, null, expression.position, {
21615
+ isAsync: expression.isAsync,
21616
+ isExpression: true
21617
+ });
21436
21618
  return context.record(expression, type);
21437
21619
  }
21438
21620
  case "binary-expression": {
@@ -21442,6 +21624,8 @@ function checkMultiValueExpression(context, expression, expected = null) {
21442
21624
  }
21443
21625
  case "unary-expression":
21444
21626
  return checkUnary(context, expression.operator, checkExpression(context, expression.operand), expression);
21627
+ case "await-expression":
21628
+ return context.record(expression, awaitedType(context, checkExpression(context, expression.operand), expression));
21445
21629
  default:
21446
21630
  return context.record(expression, checkExpression(context, expression.expression, expected));
21447
21631
  }
@@ -21517,7 +21701,12 @@ function registerMembers(context, info, statement) {
21517
21701
  }
21518
21702
  const generated = expandClassDecorators(context, statement, fieldTypes);
21519
21703
  for (const member of [...statement.members, ...generated]) {
21520
- const type = member.kind === "class-field" ? fieldTypes.get(member) ?? ANY_TYPE : member.isSynthetic ? syntheticMethodType(context, member, fieldTypes) : applyTypeParameters(context, buildFunctionType(context, member.parameters, member.returnAnnotation), member.typeParameters, member.typeConstraints);
21704
+ const type = member.kind === "class-field" ? fieldTypes.get(member) ?? ANY_TYPE : member.isSynthetic ? syntheticMethodType(context, member, fieldTypes) : applyTypeParameters(
21705
+ context,
21706
+ buildFunctionType(context, member.parameters, member.returnAnnotation, null, member.isAsync),
21707
+ member.typeParameters,
21708
+ member.typeConstraints
21709
+ );
21521
21710
  const decorators = member.decorators.map((decorator) => decorator.name);
21522
21711
  if (member.kind === "class-method" && isMetamethodMember(member)) {
21523
21712
  checkMetamethod(context, info.name, member, type);
@@ -21577,12 +21766,13 @@ function checkMethodBody(context, info, member) {
21577
21766
  if (signature2?.kind !== "function") {
21578
21767
  return;
21579
21768
  }
21769
+ const frame = { isAsync: member.isAsync, isExpression: false };
21580
21770
  if (member.isStatic) {
21581
- checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature2, null, member.position);
21771
+ checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature2, null, member.position, frame);
21582
21772
  return;
21583
21773
  }
21584
21774
  context.pushClassMethod({ className: info.name, methodName: member.name });
21585
- checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature2, selfType(info), member.position);
21775
+ checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature2, selfType(info), member.position, frame);
21586
21776
  context.popClassMethod();
21587
21777
  }
21588
21778
  function assignSuperClass(context, info, statement) {
@@ -21665,7 +21855,8 @@ function checkClassDeclaration(context, statement) {
21665
21855
  }
21666
21856
  }
21667
21857
  function checkInterfaceDeclaration(context, statement) {
21668
- if (context.declarations.lookupInterface(statement.name) !== null) {
21858
+ const existing = context.declarations.lookupInterface(statement.name);
21859
+ if (existing !== null && existing.isBuiltin !== true) {
21669
21860
  context.report("check-duplicate-interface", `Interface "${statement.name}" is already defined.`, statement.position);
21670
21861
  return;
21671
21862
  }
@@ -21697,10 +21888,10 @@ function checkInterfaceDeclaration(context, statement) {
21697
21888
  const inherited = /* @__PURE__ */ new Map();
21698
21889
  for (const parent of statement.superInterfaces) {
21699
21890
  for (const member of context.declarations.collectInterfaceContract(parent)) {
21700
- const existing = members.get(member.name) ?? inherited.get(member.name);
21701
- if (existing !== void 0 && (existing.isMethod !== member.isMethod || typeToString(existing.type) !== typeToString(member.type))) {
21891
+ const existing2 = members.get(member.name) ?? inherited.get(member.name);
21892
+ if (existing2 !== void 0 && (existing2.isMethod !== member.isMethod || typeToString(existing2.type) !== typeToString(member.type))) {
21702
21893
  context.report("check-conflicting-interface-member", `Interface "${statement.name}" inherits conflicting declarations of "${member.name}".`, statement.position);
21703
- } else if (existing === void 0) {
21894
+ } else if (existing2 === void 0) {
21704
21895
  inherited.set(member.name, member);
21705
21896
  }
21706
21897
  }
@@ -22087,7 +22278,24 @@ function emitString(value) {
22087
22278
  function emitParameters(parameters) {
22088
22279
  return parameters.map((parameter) => parameter.isVararg ? "..." : parameter.name).join(", ");
22089
22280
  }
22090
- function emitFunctionBody(state, parameters, body, header) {
22281
+ function emitAsyncFunctionBody(state, parameters, body, header, receiver) {
22282
+ requireHelper(state, "promise");
22283
+ const declared = emitParameters(parameters);
22284
+ const forwarded = (receiver === null ? [declared] : [receiver, declared]).filter((part) => part.length > 0).join(", ");
22285
+ const previous = state.loopWrap;
22286
+ state.indent += 1;
22287
+ state.loopWrap = false;
22288
+ const lines = emitBlock(state, body);
22289
+ state.loopWrap = previous;
22290
+ state.indent -= 1;
22291
+ const signature2 = `${header}(${declared}) return Promise.spawn(function(${forwarded})`;
22292
+ const closing = indentLine(state, `end${forwarded.length === 0 ? "" : `, ${forwarded}`}) end`);
22293
+ return [signature2, ...lines, closing].join("\n");
22294
+ }
22295
+ function emitFunctionBody(state, parameters, body, header, isAsync = false, receiver = null) {
22296
+ if (isAsync) {
22297
+ return emitAsyncFunctionBody(state, parameters, body, header, receiver);
22298
+ }
22091
22299
  const previous = state.loopWrap;
22092
22300
  state.indent += 1;
22093
22301
  state.loopWrap = false;
@@ -22197,7 +22405,7 @@ function emitExpression(state, expression, limit = 0) {
22197
22405
  case "table-expression":
22198
22406
  return emitTable(state, expression);
22199
22407
  case "function-expression":
22200
- return emitFunctionBody(state, expression.parameters, expression.body, "function");
22408
+ return emitFunctionBody(state, expression.parameters, expression.body, "function", expression.isAsync);
22201
22409
  case "binary-expression":
22202
22410
  return emitBinary(state, expression, limit);
22203
22411
  case "unary-expression": {
@@ -22205,6 +22413,9 @@ function emitExpression(state, expression, limit = 0) {
22205
22413
  const text = expression.operator === "not" ? `not ${operand}` : `${expression.operator}${operand}`;
22206
22414
  return UNARY_PRECEDENCE < limit ? `(${text})` : text;
22207
22415
  }
22416
+ case "await-expression":
22417
+ requireHelper(state, "promise");
22418
+ return `Promise.await(${emitExpression(state, expression.operand)})`;
22208
22419
  default:
22209
22420
  return `(${emitExpression(state, expression.expression)})`;
22210
22421
  }
@@ -22221,7 +22432,7 @@ function emitMethod(state, className, member) {
22221
22432
  return emitGeneratedMethod(state, className, member);
22222
22433
  }
22223
22434
  const parameters = member.isStatic ? member.parameters : [self, ...member.parameters];
22224
- return withSymbol(state, `${className}${member.isStatic ? "." : ":"}${member.name}`, () => emitFunctionBody(state, parameters, member.body, `${emitMemberKey(member.name)} = function`));
22435
+ return withSymbol(state, `${className}${member.isStatic ? "." : ":"}${member.name}`, () => emitFunctionBody(state, parameters, member.body, `${emitMemberKey(member.name)} = function`, member.isAsync));
22225
22436
  }
22226
22437
  function emitGeneratedMethod(state, className, member) {
22227
22438
  const fields = member.generated?.fields ?? [];
@@ -22461,7 +22672,7 @@ function emitFunctionDeclaration(state, statement) {
22461
22672
  const prefix = statement.isLocal ? "local function " : "function ";
22462
22673
  const name = emitFunctionName(state, statement);
22463
22674
  const header = `${prefix}${name}`;
22464
- return withSymbol(state, name, () => emitFunctionBody(state, statement.parameters, statement.body, header));
22675
+ return withSymbol(state, name, () => emitFunctionBody(state, statement.parameters, statement.body, header, statement.isAsync, statement.isMethod ? "self" : null));
22465
22676
  }
22466
22677
  function emitNested2(state, body) {
22467
22678
  state.indent += 1;
@@ -22675,6 +22886,7 @@ function fromExpression(expression, blocks) {
22675
22886
  fromExpression(expression.right, blocks);
22676
22887
  return;
22677
22888
  case "unary-expression":
22889
+ case "await-expression":
22678
22890
  fromExpression(expression.operand, blocks);
22679
22891
  return;
22680
22892
  case "group-expression":
@@ -22790,6 +23002,16 @@ function reindent(code, indent) {
22790
23002
  }
22791
23003
  return code.split("\n").map((line2, index) => index === 0 || line2.length === 0 ? line2 : `${indent}${line2}`).join("\n");
22792
23004
  }
23005
+ var CLOSING_LINE = /^\s*(?:end|\})/;
23006
+ function padAboveClosing(replacement, missing2) {
23007
+ const lines = replacement.split("\n");
23008
+ const closing = lines[lines.length - 1] ?? "";
23009
+ const blanks = Array.from({ length: missing2 }, () => "");
23010
+ if (lines.length < 2 || !CLOSING_LINE.test(closing)) {
23011
+ return [replacement, ...blanks].join("\n");
23012
+ }
23013
+ return [...lines.slice(0, -1), ...blanks, closing].join("\n");
23014
+ }
22793
23015
  function erasedEnd(source, span) {
22794
23016
  const trailing = TRAILING_SEMICOLON.exec(source.slice(span.end));
22795
23017
  return trailing === null ? span.end : span.end + trailing[0].length;
@@ -22812,7 +23034,7 @@ function canonicalEdit(input, statement, span) {
22812
23034
  if (missing2 < 0 && input.development) {
22813
23035
  return null;
22814
23036
  }
22815
- const padded = missing2 > 0 && source.slice(end).trim().length > 0 ? `${replacement}${"\n".repeat(missing2)}` : replacement;
23037
+ const padded = missing2 > 0 && source.slice(end).trim().length > 0 ? padAboveClosing(replacement, missing2) : replacement;
22816
23038
  return { start: span.start, end, replacement: padded, lines: emitted2.lines };
22817
23039
  }
22818
23040
 
@@ -22841,7 +23063,10 @@ function isPreservableExpression(expression, types, statics = NO_STATIC_ACCESS)
22841
23063
  switch (expression.kind) {
22842
23064
  case "template-literal":
22843
23065
  case "new-expression":
23066
+ case "await-expression":
22844
23067
  return false;
23068
+ case "function-expression":
23069
+ return !expression.isAsync;
22845
23070
  case "member-expression":
22846
23071
  return !statics.has(expression) && resolvePropertyExtension(types.get(expression.object) ?? null, expression.property) === null && isPreservableExpression(expression.object, types, statics);
22847
23072
  case "index-expression":
@@ -22890,11 +23115,12 @@ function isPreservableStatement(statement, types, statics = NO_STATIC_ACCESS) {
22890
23115
  return isPreservableExpression(statement.start, types, statics) && isPreservableExpression(statement.limit, types, statics) && (statement.step === null || isPreservableExpression(statement.step, types, statics));
22891
23116
  case "generic-for-statement":
22892
23117
  return every(statement.iterators, types, statics);
23118
+ case "function-declaration":
23119
+ return !statement.isAsync;
22893
23120
  case "break-statement":
22894
23121
  case "declare-statement":
22895
23122
  case "do-statement":
22896
23123
  case "event-declaration":
22897
- case "function-declaration":
22898
23124
  case "interface-declaration":
22899
23125
  case "type-alias-statement":
22900
23126
  return true;
@@ -23070,6 +23296,7 @@ function children(expression) {
23070
23296
  case "binary-expression":
23071
23297
  return [expression.left, expression.right];
23072
23298
  case "unary-expression":
23299
+ case "await-expression":
23073
23300
  return [expression.operand];
23074
23301
  case "group-expression":
23075
23302
  return [expression.expression];
@@ -23122,6 +23349,22 @@ function statementExpressions3(statement) {
23122
23349
  return null;
23123
23350
  }
23124
23351
  }
23352
+ function constructionEdit(input, expression, span) {
23353
+ const start = input.source.indexOf(expression.className, span.start);
23354
+ if (start === -1 || start >= span.end) {
23355
+ return null;
23356
+ }
23357
+ const isLibrary2 = input.types.get(expression)?.kind === "record";
23358
+ if (isLibrary2) {
23359
+ return { start: span.start, end: start + expression.className.length, replacement: `${expression.className}.new` };
23360
+ }
23361
+ const spacing = /^[ \t]*/.exec(input.source.slice(start + expression.className.length))?.[0] ?? "";
23362
+ return {
23363
+ start: span.start,
23364
+ end: start + expression.className.length + spacing.length,
23365
+ replacement: `new ${emitString(expression.className)} `
23366
+ };
23367
+ }
23125
23368
  function expressionEdits(input, statement) {
23126
23369
  const slots = input.development ? statementExpressions3(statement) : null;
23127
23370
  if (slots === null) {
@@ -23134,7 +23377,18 @@ function expressionEdits(input, statement) {
23134
23377
  const edits = [];
23135
23378
  for (const expression of found) {
23136
23379
  const span = input.spans.get(expression);
23137
- if (span === void 0 || holdsFunction(expression)) {
23380
+ if (span === void 0) {
23381
+ return null;
23382
+ }
23383
+ if (expression.kind === "new-expression") {
23384
+ const edit = constructionEdit(input, expression, span);
23385
+ if (edit === null) {
23386
+ return null;
23387
+ }
23388
+ edits.push(edit);
23389
+ continue;
23390
+ }
23391
+ if (holdsFunction(expression)) {
23138
23392
  return null;
23139
23393
  }
23140
23394
  const state = createEmitState(input.types, input.references, input.generatedMembers, input.staticAccess);