@thigasdevelopment/luam 0.9.0 → 0.10.1

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.
Files changed (2) hide show
  1. package/luam.mjs +269 -13
  2. package/package.json +1 -1
package/luam.mjs CHANGED
@@ -3534,6 +3534,7 @@ var SYMBOLS = [
3534
3534
  ">",
3535
3535
  "=",
3536
3536
  "|",
3537
+ "&",
3537
3538
  "?",
3538
3539
  "@",
3539
3540
  "(",
@@ -3685,7 +3686,8 @@ function scan(source) {
3685
3686
  }
3686
3687
 
3687
3688
  // ../compiler/src/parser/type-annotation.ts
3688
- var TYPE_KEYWORDS = /* @__PURE__ */ new Set(["nil", "true", "false"]);
3689
+ var TYPE_KEYWORDS = /* @__PURE__ */ new Set(["nil"]);
3690
+ var BOOLEAN_KEYWORDS = /* @__PURE__ */ new Set(["true", "false"]);
3689
3691
  var FUNCTION_TYPE = "fun";
3690
3692
  function parseTypeName(stream) {
3691
3693
  const token = stream.current();
@@ -3775,11 +3777,24 @@ function parseObjectType(stream) {
3775
3777
  stream.expect("punctuation", "}");
3776
3778
  return { kind: "type-object", members, position: position2 };
3777
3779
  }
3780
+ function parseNumberLiteralType(stream) {
3781
+ const sign = stream.check("operator", "-") ? stream.next() : null;
3782
+ const token = stream.expect("number");
3783
+ const value = Number(token.value);
3784
+ return { kind: "type-number-literal", value: sign === null ? value : -value, position: sign?.position ?? token.position };
3785
+ }
3778
3786
  function parsePrimaryType(stream) {
3779
3787
  if (stream.check("string")) {
3780
3788
  const token = stream.next();
3781
3789
  return { kind: "type-string-literal", value: token.value, position: token.position };
3782
3790
  }
3791
+ if (stream.check("number") || stream.check("operator", "-") && stream.checkAhead(1, "number")) {
3792
+ return parseNumberLiteralType(stream);
3793
+ }
3794
+ if (stream.check("keyword") && BOOLEAN_KEYWORDS.has(stream.current().value)) {
3795
+ const token = stream.next();
3796
+ return { kind: "type-boolean-literal", value: token.value === "true", position: token.position };
3797
+ }
3783
3798
  if (stream.check("keyword", "function")) {
3784
3799
  throw stream.error(`Use "${FUNCTION_TYPE}" for function types. "function" is a keyword and cannot name a type.`, "parse-invalid-type");
3785
3800
  }
@@ -3809,14 +3824,25 @@ function parsePostfixType(stream) {
3809
3824
  return annotation;
3810
3825
  }
3811
3826
  }
3812
- function parseTypeAnnotation(stream) {
3827
+ function parseIntersectionType(stream) {
3813
3828
  const first = parsePostfixType(stream);
3829
+ if (!stream.check("operator", "&")) {
3830
+ return first;
3831
+ }
3832
+ const parts = [first];
3833
+ while (stream.match("operator", "&")) {
3834
+ parts.push(parsePostfixType(stream));
3835
+ }
3836
+ return { kind: "type-intersection", parts, position: first.position };
3837
+ }
3838
+ function parseTypeAnnotation(stream) {
3839
+ const first = parseIntersectionType(stream);
3814
3840
  if (!stream.check("operator", "|")) {
3815
3841
  return first;
3816
3842
  }
3817
3843
  const options = [first];
3818
3844
  while (stream.match("operator", "|")) {
3819
- options.push(parsePostfixType(stream));
3845
+ options.push(parseIntersectionType(stream));
3820
3846
  }
3821
3847
  return { kind: "type-union", options, position: first.position };
3822
3848
  }
@@ -4780,7 +4806,22 @@ function createMap(key, value) {
4780
4806
  function createStringLiteral(value) {
4781
4807
  return { kind: "string-literal", value };
4782
4808
  }
4809
+ function createBooleanLiteral(value) {
4810
+ return { kind: "boolean-literal", value };
4811
+ }
4812
+ function createNumberLiteral(value) {
4813
+ return { kind: "number-literal", value };
4814
+ }
4815
+ function isLiteralType(type) {
4816
+ return type.kind === "string-literal" || type.kind === "boolean-literal" || type.kind === "number-literal";
4817
+ }
4783
4818
  function widenLiteral(type) {
4819
+ if (type.kind === "boolean-literal") {
4820
+ return BOOLEAN_TYPE;
4821
+ }
4822
+ if (type.kind === "number-literal") {
4823
+ return NUMBER_TYPE;
4824
+ }
4784
4825
  return type.kind === "string-literal" ? STRING_TYPE : type;
4785
4826
  }
4786
4827
  function createRecord(name, members, origin = null) {
@@ -4865,6 +4906,9 @@ function typeToString(type) {
4865
4906
  if (type.kind === "string-literal") {
4866
4907
  return `'${type.value.replace(/(['\\])/g, "\\$1")}'`;
4867
4908
  }
4909
+ if (type.kind === "boolean-literal" || type.kind === "number-literal") {
4910
+ return String(type.value);
4911
+ }
4868
4912
  if (type.kind === "named" || type.kind === "record") {
4869
4913
  return type.name;
4870
4914
  }
@@ -4900,13 +4944,13 @@ function isTableLike(type) {
4900
4944
  }
4901
4945
  function isBooleanType(type) {
4902
4946
  const resolved2 = type?.kind === "optional" ? type.element : type;
4903
- return resolved2?.kind === "boolean";
4947
+ return resolved2?.kind === "boolean" || resolved2?.kind === "boolean-literal";
4904
4948
  }
4905
4949
  function isNumeric(type) {
4906
4950
  if (type.kind === "union") {
4907
4951
  return type.options.every(isNumeric);
4908
4952
  }
4909
- return type.kind === "number" || type.kind === "any" || type.kind === "unknown" || type.kind === "named";
4953
+ return type.kind === "number" || type.kind === "number-literal" || type.kind === "any" || type.kind === "unknown" || type.kind === "named";
4910
4954
  }
4911
4955
  function isConcatenable(type) {
4912
4956
  if (type.kind === "union") {
@@ -5001,7 +5045,13 @@ function isAssignable(source, target, options = { allowNil: false }) {
5001
5045
  if (source.kind === "string-literal") {
5002
5046
  return target.kind === "string" || target.kind === "string-literal" && source.value === target.value;
5003
5047
  }
5004
- if (target.kind === "string-literal") {
5048
+ if (source.kind === "boolean-literal") {
5049
+ return target.kind === "boolean" || target.kind === "boolean-literal" && source.value === target.value;
5050
+ }
5051
+ if (source.kind === "number-literal") {
5052
+ return target.kind === "number" || target.kind === "number-literal" && source.value === target.value;
5053
+ }
5054
+ if (isLiteralType(target)) {
5005
5055
  return false;
5006
5056
  }
5007
5057
  return source.kind === target.kind;
@@ -5987,7 +6037,7 @@ import { tmpdir } from "node:os";
5987
6037
  import { join as join2 } from "node:path";
5988
6038
 
5989
6039
  // src/cli/version.ts
5990
- var VERSION = true ? "0.9.0" : "0.0.0-dev";
6040
+ var VERSION = true ? "0.10.1" : "0.0.0-dev";
5991
6041
  var PROGRAM_NAME = "luam";
5992
6042
  var PROGRAM_DESCRIPTION = "luam \u2014 the Luam compiler for Multi Theft Auto resources.";
5993
6043
 
@@ -7186,6 +7236,9 @@ var Binder = class {
7186
7236
  lookupAlias(name) {
7187
7237
  return this.aliases.get(name) ?? null;
7188
7238
  }
7239
+ resolvedAliases() {
7240
+ return new Map([...this.aliases].map(([name, info]) => [name, info.type]));
7241
+ }
7189
7242
  };
7190
7243
 
7191
7244
  // ../mta-types/src/lua-standard.ts
@@ -11021,6 +11074,41 @@ function mtaMember(className, member) {
11021
11074
  return mtaClassRegistry().lookupMember(className, member);
11022
11075
  }
11023
11076
 
11077
+ // ../compiler/src/checker/type-intersection.ts
11078
+ function namedMembers(context, name) {
11079
+ if (context.declarations.lookupInterface(name) === null && context.declarations.lookupClass(name) === null) {
11080
+ return null;
11081
+ }
11082
+ return new Map(context.declarations.collectMembers(name).map((member) => [member.name, member.type]));
11083
+ }
11084
+ function partMembers(context, part) {
11085
+ if (part.kind === "record") {
11086
+ return part.members;
11087
+ }
11088
+ return part.kind === "named" ? namedMembers(context, part.name) : null;
11089
+ }
11090
+ function mergeIntersection(context, parts, position2) {
11091
+ const members = /* @__PURE__ */ new Map();
11092
+ for (const part of parts) {
11093
+ const collected = partMembers(context, part);
11094
+ if (collected === null) {
11095
+ const message = `"${typeToString(part)}" is not an object type, so it cannot take part in an intersection.`;
11096
+ context.report("check-invalid-intersection", message, position2);
11097
+ continue;
11098
+ }
11099
+ for (const [name, type] of collected) {
11100
+ const existing = members.get(name);
11101
+ if (existing !== void 0 && typeToString(existing) !== typeToString(type)) {
11102
+ const message = `Intersection declares "${name}" as both "${typeToString(existing)}" and "${typeToString(type)}".`;
11103
+ context.report("check-conflicting-intersection-member", message, position2);
11104
+ continue;
11105
+ }
11106
+ members.set(name, type);
11107
+ }
11108
+ }
11109
+ return createObjectType(members);
11110
+ }
11111
+
11024
11112
  // ../compiler/src/checker/type-substitution.ts
11025
11113
  function substituteType(type, substitutions) {
11026
11114
  if (type.kind === "named") {
@@ -11085,6 +11173,8 @@ var CheckContext = class {
11085
11173
  references = /* @__PURE__ */ new Set();
11086
11174
  declaredGlobals = /* @__PURE__ */ new Map();
11087
11175
  externalReferences = /* @__PURE__ */ new Map();
11176
+ unknownTypes = /* @__PURE__ */ new Map();
11177
+ typeParameters = /* @__PURE__ */ new Set();
11088
11178
  generatedMembers = /* @__PURE__ */ new Map();
11089
11179
  mode;
11090
11180
  environment;
@@ -11145,6 +11235,12 @@ var CheckContext = class {
11145
11235
  }
11146
11236
  }
11147
11237
  report(code, message, position2) {
11238
+ this.push(code, message, position2, "error");
11239
+ }
11240
+ warn(code, message, position2) {
11241
+ this.push(code, message, position2, "warning");
11242
+ }
11243
+ push(code, message, position2, severity) {
11148
11244
  if (this.mode === "nocheck") {
11149
11245
  return;
11150
11246
  }
@@ -11153,7 +11249,20 @@ var CheckContext = class {
11153
11249
  return;
11154
11250
  }
11155
11251
  this.reported.add(key);
11156
- this.diagnostics.push(createDiagnostic("checker", code, message, position2));
11252
+ this.diagnostics.push(createDiagnostic("checker", code, message, position2, severity));
11253
+ }
11254
+ noteTypeParameters(names) {
11255
+ for (const name of names) {
11256
+ this.typeParameters.add(name);
11257
+ }
11258
+ }
11259
+ isTypeParameter(name) {
11260
+ return this.typeParameters.has(name);
11261
+ }
11262
+ noteUnknownType(name, position2) {
11263
+ if (!this.unknownTypes.has(name)) {
11264
+ this.unknownTypes.set(name, position2);
11265
+ }
11157
11266
  }
11158
11267
  record(expression, type) {
11159
11268
  this.types.set(expression, type);
@@ -11212,9 +11321,19 @@ var CheckContext = class {
11212
11321
  if (annotation.kind === "type-union") {
11213
11322
  return createUnion(annotation.options.map((option) => this.resolveAnnotation(option)));
11214
11323
  }
11324
+ if (annotation.kind === "type-intersection") {
11325
+ const parts = annotation.parts.map((part) => this.resolveAnnotation(part));
11326
+ return mergeIntersection(this, parts, annotation.position);
11327
+ }
11215
11328
  if (annotation.kind === "type-string-literal") {
11216
11329
  return createStringLiteral(annotation.value);
11217
11330
  }
11331
+ if (annotation.kind === "type-boolean-literal") {
11332
+ return createBooleanLiteral(annotation.value);
11333
+ }
11334
+ if (annotation.kind === "type-number-literal") {
11335
+ return createNumberLiteral(annotation.value);
11336
+ }
11218
11337
  if (annotation.kind === "type-object") {
11219
11338
  const members = /* @__PURE__ */ new Map();
11220
11339
  for (const member of annotation.members) {
@@ -11237,7 +11356,7 @@ var CheckContext = class {
11237
11356
  if (isAssignable(source, target, { allowNil: this.allowNil })) {
11238
11357
  return;
11239
11358
  }
11240
- const received = target.kind === "string-literal" || target.kind === "union" ? source : widenLiteral(source);
11359
+ const received = isLiteralType(target) || target.kind === "union" ? source : widenLiteral(source);
11241
11360
  const message = `${subject} expects "${typeToString(target)}" but received "${typeToString(received)}".`;
11242
11361
  this.report("check-type-mismatch", `${message}${nilHint(source, target, this.mode)}`, position2);
11243
11362
  }
@@ -11293,6 +11412,7 @@ var CheckContext = class {
11293
11412
  }
11294
11413
  const alias = this.binder.lookupAlias(name);
11295
11414
  if (alias === null) {
11415
+ this.noteUnknownType(name, position2);
11296
11416
  return createNamed(name);
11297
11417
  }
11298
11418
  if (typeArguments.length !== alias.parameters.length) {
@@ -12277,6 +12397,9 @@ function checkUnary(context, operator, operand, expression) {
12277
12397
  if (operator === "-" && !isNumeric(operand)) {
12278
12398
  reportInvalidOperand(context, operator, operand, expression);
12279
12399
  }
12400
+ if (operator === "-" && operand.kind === "number-literal") {
12401
+ return context.record(expression, createNumberLiteral(-operand.value));
12402
+ }
12280
12403
  return context.record(expression, NUMBER_TYPE);
12281
12404
  }
12282
12405
 
@@ -12304,6 +12427,47 @@ function templateLiteralText(segments) {
12304
12427
  return segments.map((segment) => segment.kind === "text" ? segment.value : `\${${segment.value}}`).join("");
12305
12428
  }
12306
12429
 
12430
+ // ../compiler/src/checker/union-members.ts
12431
+ function isShapeOption(context, option) {
12432
+ if (option.kind === "record") {
12433
+ return true;
12434
+ }
12435
+ if (option.kind !== "named") {
12436
+ return false;
12437
+ }
12438
+ return context.declarations.lookupInterface(option.name) !== null || context.declarations.lookupClass(option.name) !== null;
12439
+ }
12440
+ function memberOf(context, option, property) {
12441
+ if (option.kind === "record") {
12442
+ return option.members.get(property) ?? null;
12443
+ }
12444
+ return option.kind === "named" ? context.declarations.lookupMember(option.name, property)?.type ?? null : null;
12445
+ }
12446
+ function optionMemberType(context, option, property) {
12447
+ return isShapeOption(context, option) ? memberOf(context, option, property) : null;
12448
+ }
12449
+ function resolveUnionMember(context, type, expression) {
12450
+ if (!type.options.every((option) => isShapeOption(context, option))) {
12451
+ return null;
12452
+ }
12453
+ const resolved2 = [];
12454
+ const missing = [];
12455
+ for (const option of type.options) {
12456
+ const member = memberOf(context, option, expression.property);
12457
+ if (member === null) {
12458
+ missing.push(`"${typeToString(option)}"`);
12459
+ } else {
12460
+ resolved2.push(member);
12461
+ }
12462
+ }
12463
+ if (missing.length === 0) {
12464
+ return createUnion(resolved2);
12465
+ }
12466
+ const message = `"${expression.property}" is not a key of every member of "${typeToString(type)}". It is missing from ${missing.join(", ")}.`;
12467
+ context.report("check-unknown-union-key", message, expression.position);
12468
+ return ANY_TYPE;
12469
+ }
12470
+
12307
12471
  // ../compiler/src/checker/expressions.ts
12308
12472
  var EXTENSION_RESULTS = {
12309
12473
  boolean: BOOLEAN_TYPE,
@@ -12312,7 +12476,8 @@ var EXTENSION_RESULTS = {
12312
12476
  table: TABLE_TYPE
12313
12477
  };
12314
12478
  function extensionType(receiver, property) {
12315
- const kind = receiver.kind === "string-literal" ? "string" : receiver.kind === "string" || receiver.kind === "number" ? receiver.kind : null;
12479
+ const literal = receiver.kind === "string-literal" ? "string" : receiver.kind === "number-literal" ? "number" : null;
12480
+ const kind = literal ?? (receiver.kind === "string" || receiver.kind === "number" ? receiver.kind : null);
12316
12481
  const target = kind ?? (isTableLike(receiver) ? "table" : null);
12317
12482
  if (target === null) {
12318
12483
  return null;
@@ -12346,6 +12511,12 @@ function checkMember(context, expression) {
12346
12511
  if (objectType.kind === "record") {
12347
12512
  return context.record(expression, resolveRecordMember(context, objectType, expression));
12348
12513
  }
12514
+ if (objectType.kind === "union") {
12515
+ const option = resolveUnionMember(context, objectType, expression);
12516
+ if (option !== null) {
12517
+ return context.record(expression, option);
12518
+ }
12519
+ }
12349
12520
  if (objectType.kind === "map" && isAssignable(STRING_TYPE, objectType.key)) {
12350
12521
  return context.record(expression, objectType.value);
12351
12522
  }
@@ -12454,9 +12625,9 @@ function checkMultiValueExpression(context, expression) {
12454
12625
  case "nil-literal":
12455
12626
  return context.record(expression, NIL_TYPE);
12456
12627
  case "boolean-literal":
12457
- return context.record(expression, BOOLEAN_TYPE);
12628
+ return context.record(expression, createBooleanLiteral(expression.value));
12458
12629
  case "number-literal":
12459
- return context.record(expression, NUMBER_TYPE);
12630
+ return context.record(expression, createNumberLiteral(expression.value));
12460
12631
  case "string-literal":
12461
12632
  return context.record(expression, createStringLiteral(expression.value));
12462
12633
  case "template-literal":
@@ -12702,6 +12873,53 @@ function checkEnumDeclaration(context, statement) {
12702
12873
  context.declareModuleGlobal({ name: statement.name, type: createNamed(statement.name), isLocal: false, position: statement.position });
12703
12874
  }
12704
12875
 
12876
+ // ../compiler/src/checker/discriminant.ts
12877
+ function literalValue(expression) {
12878
+ if (expression.kind === "string-literal") {
12879
+ return createStringLiteral(expression.value);
12880
+ }
12881
+ if (expression.kind === "boolean-literal") {
12882
+ return createBooleanLiteral(expression.value);
12883
+ }
12884
+ return expression.kind === "number-literal" ? createNumberLiteral(expression.value) : null;
12885
+ }
12886
+ function discriminantTest(left, right) {
12887
+ if (left.kind !== "member-expression" || left.object.kind !== "identifier") {
12888
+ return null;
12889
+ }
12890
+ const value = literalValue(right);
12891
+ return value === null ? null : { name: left.object.name, property: left.property, value };
12892
+ }
12893
+ function subjectType(context, name) {
12894
+ const type = context.narrowedType(name) ?? context.binder.lookup(name)?.type ?? null;
12895
+ return type === null ? null : withoutNil(type);
12896
+ }
12897
+ function filterOptions(context, test, keep) {
12898
+ const subject = subjectType(context, test.name);
12899
+ if (subject === null || subject.kind !== "union") {
12900
+ return null;
12901
+ }
12902
+ const matched = [];
12903
+ for (const option of subject.options) {
12904
+ const member = optionMemberType(context, option, test.property);
12905
+ if (member === null) {
12906
+ return null;
12907
+ }
12908
+ if (isAssignable(test.value, member) === keep) {
12909
+ matched.push(option);
12910
+ }
12911
+ }
12912
+ return matched.length === 0 || matched.length === subject.options.length ? null : createUnion(matched);
12913
+ }
12914
+ function discriminantFact(context, left, right, keep) {
12915
+ const test = discriminantTest(left, right) ?? discriminantTest(right, left);
12916
+ if (test === null) {
12917
+ return null;
12918
+ }
12919
+ const narrowed = filterOptions(context, test, keep);
12920
+ return narrowed === null ? null : [test.name, narrowed];
12921
+ }
12922
+
12705
12923
  // ../compiler/src/checker/narrowing.ts
12706
12924
  var GUARD_FUNCTION = "type";
12707
12925
  var GUARD_TYPES = {
@@ -12749,6 +12967,12 @@ function mergeAlternatives(left, right, facts) {
12749
12967
  }
12750
12968
  }
12751
12969
  }
12970
+ function applyDiscriminant(context, left, right, keep, facts) {
12971
+ const fact = discriminantFact(context, left, right, keep);
12972
+ if (fact !== null) {
12973
+ facts.set(fact[0], fact[1]);
12974
+ }
12975
+ }
12752
12976
  function collectFacts(context, expression, facts) {
12753
12977
  if (expression.kind === "group-expression") {
12754
12978
  collectFacts(context, expression.expression, facts);
@@ -12777,6 +13001,8 @@ function collectFacts(context, expression, facts) {
12777
13001
  facts.set(guard[0], guard[1]);
12778
13002
  } else if (missing !== null) {
12779
13003
  facts.set(missing, NIL_TYPE);
13004
+ } else {
13005
+ applyDiscriminant(context, expression.left, expression.right, true, facts);
12780
13006
  }
12781
13007
  return;
12782
13008
  }
@@ -12784,6 +13010,8 @@ function collectFacts(context, expression, facts) {
12784
13010
  const name = nilComparison(expression.left, expression.right);
12785
13011
  if (name !== null) {
12786
13012
  present2(context, name, facts);
13013
+ } else {
13014
+ applyDiscriminant(context, expression.left, expression.right, false, facts);
12787
13015
  }
12788
13016
  }
12789
13017
  }
@@ -12824,8 +13052,13 @@ function negatedFacts(context, condition) {
12824
13052
  const name = nilComparison(condition.left, condition.right);
12825
13053
  if (name !== null) {
12826
13054
  present2(context, name, facts);
13055
+ } else {
13056
+ applyDiscriminant(context, condition.left, condition.right, false, facts);
12827
13057
  }
12828
13058
  }
13059
+ if (condition.kind === "binary-expression" && condition.operator === "~=") {
13060
+ applyDiscriminant(context, condition.left, condition.right, true, facts);
13061
+ }
12829
13062
  if (condition.kind === "unary-expression" && condition.operator === "not" && condition.operand.kind === "identifier") {
12830
13063
  present2(context, condition.operand.name, facts);
12831
13064
  }
@@ -13082,7 +13315,9 @@ function checkStatement(context, statement) {
13082
13315
  return checkGenericFor(context, statement);
13083
13316
  case "type-alias-statement": {
13084
13317
  const resolved2 = context.resolveAnnotation(statement.annotation);
13085
- const named2 = statement.annotation.kind === "type-object" ? renameRecord(resolved2, statement.name) : resolved2;
13318
+ const shape = statement.annotation.kind === "type-object" || statement.annotation.kind === "type-intersection";
13319
+ const named2 = shape ? renameRecord(resolved2, statement.name) : resolved2;
13320
+ context.noteTypeParameters(statement.typeParameters);
13086
13321
  context.binder.declareAlias(statement.name, named2, statement.typeParameters);
13087
13322
  return;
13088
13323
  }
@@ -13114,6 +13349,25 @@ function checkStatements(context, statements) {
13114
13349
  }
13115
13350
  }
13116
13351
 
13352
+ // ../compiler/src/checker/type-names.ts
13353
+ function isDeclaredType(context, name) {
13354
+ const declarations = context.declarations;
13355
+ return declarations.lookupClass(name) !== null || declarations.lookupInterface(name) !== null || declarations.lookupEnum(name) !== null;
13356
+ }
13357
+ function isKnownTypeName(context, name) {
13358
+ if (context.binder.lookupAlias(name) !== null || context.isTypeParameter(name)) {
13359
+ return true;
13360
+ }
13361
+ return isDeclaredType(context, name) || isMtaClass(name);
13362
+ }
13363
+ function reportUnknownTypes(context) {
13364
+ for (const [name, position2] of context.unknownTypes) {
13365
+ if (!isKnownTypeName(context, name)) {
13366
+ context.warn("check-unknown-type", `Type "${name}" is not defined.`, position2);
13367
+ }
13368
+ }
13369
+ }
13370
+
13117
13371
  // ../compiler/src/checker/checker.ts
13118
13372
  function externalReferences(context) {
13119
13373
  const external = /* @__PURE__ */ new Map();
@@ -13132,11 +13386,13 @@ function check(program2, mode, environment = DEFAULT_ENVIRONMENT, options = {})
13132
13386
  const structure = context.isDeclarationFile ? checkDeclarationFile(program2.body) : checkJumps(program2.body);
13133
13387
  const directives = collectDirectives(program2.body, { isDeclarationFile: context.isDeclarationFile });
13134
13388
  checkStatements(context, program2.body);
13389
+ reportUnknownTypes(context);
13135
13390
  return {
13136
13391
  diagnostics: sortDiagnostics([...structure, ...directives.diagnostics, ...context.diagnostics]),
13137
13392
  types: context.types,
13138
13393
  references: context.references,
13139
13394
  declarations: context.declarations,
13395
+ aliases: context.binder.resolvedAliases(),
13140
13396
  declaredGlobals: context.declaredGlobals,
13141
13397
  externalReferences: externalReferences(context),
13142
13398
  directives: directives.directives,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thigasdevelopment/luam",
3
- "version": "0.9.0",
3
+ "version": "0.10.1",
4
4
  "description": "The Luam compiler for Multi Theft Auto resources.",
5
5
  "keywords": [
6
6
  "mta",