@thigasdevelopment/luam 0.10.0 → 0.10.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.
Files changed (2) hide show
  1. package/luam.mjs +116 -19
  2. package/package.json +1 -1
package/luam.mjs CHANGED
@@ -3686,7 +3686,8 @@ function scan(source) {
3686
3686
  }
3687
3687
 
3688
3688
  // ../compiler/src/parser/type-annotation.ts
3689
- 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"]);
3690
3691
  var FUNCTION_TYPE = "fun";
3691
3692
  function parseTypeName(stream) {
3692
3693
  const token = stream.current();
@@ -3776,11 +3777,24 @@ function parseObjectType(stream) {
3776
3777
  stream.expect("punctuation", "}");
3777
3778
  return { kind: "type-object", members, position: position2 };
3778
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
+ }
3779
3786
  function parsePrimaryType(stream) {
3780
3787
  if (stream.check("string")) {
3781
3788
  const token = stream.next();
3782
3789
  return { kind: "type-string-literal", value: token.value, position: token.position };
3783
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
+ }
3784
3798
  if (stream.check("keyword", "function")) {
3785
3799
  throw stream.error(`Use "${FUNCTION_TYPE}" for function types. "function" is a keyword and cannot name a type.`, "parse-invalid-type");
3786
3800
  }
@@ -4792,7 +4806,22 @@ function createMap(key, value) {
4792
4806
  function createStringLiteral(value) {
4793
4807
  return { kind: "string-literal", value };
4794
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
+ }
4795
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
+ }
4796
4825
  return type.kind === "string-literal" ? STRING_TYPE : type;
4797
4826
  }
4798
4827
  function createRecord(name, members, origin = null) {
@@ -4807,6 +4836,19 @@ function createObjectType(members) {
4807
4836
  );
4808
4837
  return createRecord(keys.length === 0 ? "{}" : `{ ${keys.join(", ")} }`, members);
4809
4838
  }
4839
+ function createLiteralRecord(members) {
4840
+ const literal = createObjectType(members);
4841
+ return literal.kind === "record" ? { ...literal, isLiteral: true } : literal;
4842
+ }
4843
+ function isEmptyLiteral(type) {
4844
+ return type.kind === "record" && type.isLiteral === true && type.members.size === 0;
4845
+ }
4846
+ function widenInferred(type) {
4847
+ if (type.kind !== "record" || type.isLiteral !== true) {
4848
+ return widenLiteral(type);
4849
+ }
4850
+ return type.members.size === 0 ? TABLE_TYPE : createRecord(type.name, type.members, type.origin);
4851
+ }
4810
4852
  function createFunction(parameters, returnType, minimumArguments2, isVariadic = false) {
4811
4853
  return { kind: "function", parameters, returnType, minimumArguments: minimumArguments2 ?? parameters.length, isVariadic };
4812
4854
  }
@@ -4877,6 +4919,9 @@ function typeToString(type) {
4877
4919
  if (type.kind === "string-literal") {
4878
4920
  return `'${type.value.replace(/(['\\])/g, "\\$1")}'`;
4879
4921
  }
4922
+ if (type.kind === "boolean-literal" || type.kind === "number-literal") {
4923
+ return String(type.value);
4924
+ }
4880
4925
  if (type.kind === "named" || type.kind === "record") {
4881
4926
  return type.name;
4882
4927
  }
@@ -4912,13 +4957,13 @@ function isTableLike(type) {
4912
4957
  }
4913
4958
  function isBooleanType(type) {
4914
4959
  const resolved2 = type?.kind === "optional" ? type.element : type;
4915
- return resolved2?.kind === "boolean";
4960
+ return resolved2?.kind === "boolean" || resolved2?.kind === "boolean-literal";
4916
4961
  }
4917
4962
  function isNumeric(type) {
4918
4963
  if (type.kind === "union") {
4919
4964
  return type.options.every(isNumeric);
4920
4965
  }
4921
- return type.kind === "number" || type.kind === "any" || type.kind === "unknown" || type.kind === "named";
4966
+ return type.kind === "number" || type.kind === "number-literal" || type.kind === "any" || type.kind === "unknown" || type.kind === "named";
4922
4967
  }
4923
4968
  function isConcatenable(type) {
4924
4969
  if (type.kind === "union") {
@@ -5002,7 +5047,7 @@ function isAssignable(source, target, options = { allowNil: false }) {
5002
5047
  return source.kind === "record" ? isRecordAssignable(source, target, options) : source.kind === "table";
5003
5048
  }
5004
5049
  if (target.kind === "array") {
5005
- return source.kind === "table" || source.kind === "array" && isAssignable(source.element, target.element, options);
5050
+ return source.kind === "table" || isEmptyLiteral(source) || source.kind === "array" && isAssignable(source.element, target.element, options);
5006
5051
  }
5007
5052
  if (target.kind === "map") {
5008
5053
  return isMapAssignable(source, target, options);
@@ -5013,7 +5058,13 @@ function isAssignable(source, target, options = { allowNil: false }) {
5013
5058
  if (source.kind === "string-literal") {
5014
5059
  return target.kind === "string" || target.kind === "string-literal" && source.value === target.value;
5015
5060
  }
5016
- if (target.kind === "string-literal") {
5061
+ if (source.kind === "boolean-literal") {
5062
+ return target.kind === "boolean" || target.kind === "boolean-literal" && source.value === target.value;
5063
+ }
5064
+ if (source.kind === "number-literal") {
5065
+ return target.kind === "number" || target.kind === "number-literal" && source.value === target.value;
5066
+ }
5067
+ if (isLiteralType(target)) {
5017
5068
  return false;
5018
5069
  }
5019
5070
  return source.kind === target.kind;
@@ -5999,7 +6050,7 @@ import { tmpdir } from "node:os";
5999
6050
  import { join as join2 } from "node:path";
6000
6051
 
6001
6052
  // src/cli/version.ts
6002
- var VERSION = true ? "0.10.0" : "0.0.0-dev";
6053
+ var VERSION = true ? "0.10.2" : "0.0.0-dev";
6003
6054
  var PROGRAM_NAME = "luam";
6004
6055
  var PROGRAM_DESCRIPTION = "luam \u2014 the Luam compiler for Multi Theft Auto resources.";
6005
6056
 
@@ -7198,6 +7249,9 @@ var Binder = class {
7198
7249
  lookupAlias(name) {
7199
7250
  return this.aliases.get(name) ?? null;
7200
7251
  }
7252
+ resolvedAliases() {
7253
+ return new Map([...this.aliases].map(([name, info]) => [name, info.type]));
7254
+ }
7201
7255
  };
7202
7256
 
7203
7257
  // ../mta-types/src/lua-standard.ts
@@ -8297,11 +8351,11 @@ var MTA_SETTINGS_SERVER = {
8297
8351
 
8298
8352
  // ../mta-types/src/generated/api/mta-sql-server.ts
8299
8353
  var MTA_SQL_SERVER = {
8300
- dbConnect: fn([STRING, STRING, STRING, STRING, STRING], named("Element"), 2),
8301
- dbExec: fn([named("Element"), STRING, ANY], BOOLEAN, 2, true),
8354
+ dbConnect: fn([STRING, STRING, STRING, STRING, STRING], named("Connection"), 2),
8355
+ dbExec: fn([named("Connection"), STRING, ANY], BOOLEAN, 2, true),
8302
8356
  dbFree: fn([ANY], BOOLEAN, 1),
8303
8357
  dbPoll: fn([ANY, NUMBER, BOOLEAN], TABLE, 2),
8304
- dbPrepareString: fn([named("Element"), STRING, ANY], STRING, 2, true),
8358
+ dbPrepareString: fn([named("Connection"), STRING, ANY], STRING, 2, true),
8305
8359
  dbQuery: fn([ANY, ANY, ANY, ANY, ANY], ANY, 2, true),
8306
8360
  executeSQLQuery: fn([STRING, ANY], TABLE, 1, true)
8307
8361
  };
@@ -9369,6 +9423,17 @@ var MTA_OOP_1 = [
9369
9423
  ],
9370
9424
  null
9371
9425
  ),
9426
+ oopClass(
9427
+ "Connection",
9428
+ "Element",
9429
+ [
9430
+ oopMethod("exec", "server", "dbExec", fn([STRING, ANY], BOOLEAN, 1, true)),
9431
+ oopMethod("prepareString", "server", "dbPrepareString", fn([STRING, ANY], STRING, 1, true)),
9432
+ oopMethod("query", "server", "dbQuery", fn([ANY, ANY, ANY, ANY, ANY], ANY, 2, true))
9433
+ ],
9434
+ [],
9435
+ oopConstructor("server", fn([STRING, STRING, STRING, STRING, STRING], named("Connection"), 2))
9436
+ ),
9372
9437
  oopClass(
9373
9438
  "DxFont",
9374
9439
  null,
@@ -10049,7 +10114,7 @@ var MTA_OOP_4 = [
10049
10114
  oopMethod("toggleRespawn", "client", "toggleObjectRespawn", fn([BOOLEAN], BOOLEAN, 1))
10050
10115
  ],
10051
10116
  [],
10052
- oopConstructor("shared", fn([NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, BOOLEAN], named("MTASAObject"), 4))
10117
+ oopConstructor("shared", fn([NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, BOOLEAN], named("Object"), 4))
10053
10118
  ),
10054
10119
  oopClass("Ped", "Element", [
10055
10120
  oopMethod("addClothes", "shared", "addPedClothes", fn([STRING, STRING, NUMBER], BOOLEAN, 3)),
@@ -11256,7 +11321,7 @@ var CheckContext = class {
11256
11321
  return this.returnStack[this.returnStack.length - 1]?.expected ?? null;
11257
11322
  }
11258
11323
  inferReturnType(type) {
11259
- this.returnStack[this.returnStack.length - 1]?.inferred.push(widenLiteral(type));
11324
+ this.returnStack[this.returnStack.length - 1]?.inferred.push(widenInferred(type));
11260
11325
  }
11261
11326
  pushClassMethod(frame) {
11262
11327
  this.methodStack.push(frame);
@@ -11287,6 +11352,12 @@ var CheckContext = class {
11287
11352
  if (annotation.kind === "type-string-literal") {
11288
11353
  return createStringLiteral(annotation.value);
11289
11354
  }
11355
+ if (annotation.kind === "type-boolean-literal") {
11356
+ return createBooleanLiteral(annotation.value);
11357
+ }
11358
+ if (annotation.kind === "type-number-literal") {
11359
+ return createNumberLiteral(annotation.value);
11360
+ }
11290
11361
  if (annotation.kind === "type-object") {
11291
11362
  const members = /* @__PURE__ */ new Map();
11292
11363
  for (const member of annotation.members) {
@@ -11309,7 +11380,7 @@ var CheckContext = class {
11309
11380
  if (isAssignable(source, target, { allowNil: this.allowNil })) {
11310
11381
  return;
11311
11382
  }
11312
- const received = target.kind === "string-literal" || target.kind === "union" ? source : widenLiteral(source);
11383
+ const received = isLiteralType(target) || target.kind === "union" ? source : widenLiteral(source);
11313
11384
  const message = `${subject} expects "${typeToString(target)}" but received "${typeToString(received)}".`;
11314
11385
  this.report("check-type-mismatch", `${message}${nilHint(source, target, this.mode)}`, position2);
11315
11386
  }
@@ -12049,6 +12120,7 @@ var ELEMENT_TYPES = [
12049
12120
  { name: "Browser", parent: "Element" },
12050
12121
  { name: "Camera", parent: "Element" },
12051
12122
  { name: "ColShape", parent: "Element" },
12123
+ { name: "Connection", parent: "Element" },
12052
12124
  { name: "DxFont", parent: null },
12053
12125
  { name: "DxRenderTarget", parent: null },
12054
12126
  { name: "DxScreenSource", parent: null },
@@ -12350,6 +12422,9 @@ function checkUnary(context, operator, operand, expression) {
12350
12422
  if (operator === "-" && !isNumeric(operand)) {
12351
12423
  reportInvalidOperand(context, operator, operand, expression);
12352
12424
  }
12425
+ if (operator === "-" && operand.kind === "number-literal") {
12426
+ return context.record(expression, createNumberLiteral(-operand.value));
12427
+ }
12353
12428
  return context.record(expression, NUMBER_TYPE);
12354
12429
  }
12355
12430
 
@@ -12426,7 +12501,8 @@ var EXTENSION_RESULTS = {
12426
12501
  table: TABLE_TYPE
12427
12502
  };
12428
12503
  function extensionType(receiver, property) {
12429
- const kind = receiver.kind === "string-literal" ? "string" : receiver.kind === "string" || receiver.kind === "number" ? receiver.kind : null;
12504
+ const literal = receiver.kind === "string-literal" ? "string" : receiver.kind === "number-literal" ? "number" : null;
12505
+ const kind = literal ?? (receiver.kind === "string" || receiver.kind === "number" ? receiver.kind : null);
12430
12506
  const target = kind ?? (isTableLike(receiver) ? "table" : null);
12431
12507
  if (target === null) {
12432
12508
  return null;
@@ -12549,8 +12625,18 @@ function checkTable(context, expression) {
12549
12625
  }
12550
12626
  return checkExpression(context, field2.value);
12551
12627
  });
12628
+ const isRecord = expression.fields.every((field2) => field2.name !== null);
12629
+ if (isRecord) {
12630
+ const members = /* @__PURE__ */ new Map();
12631
+ expression.fields.forEach((field2, index) => {
12632
+ if (field2.name !== null) {
12633
+ members.set(field2.name, valueTypes[index] ?? ANY_TYPE);
12634
+ }
12635
+ });
12636
+ return context.record(expression, createLiteralRecord(members));
12637
+ }
12552
12638
  const isArray = expression.fields.every((field2) => field2.key === null && field2.name === null);
12553
- if (!isArray || valueTypes.length === 0) {
12639
+ if (!isArray) {
12554
12640
  return context.record(expression, TABLE_TYPE);
12555
12641
  }
12556
12642
  return context.record(expression, createArray(createUnion(valueTypes)));
@@ -12574,9 +12660,9 @@ function checkMultiValueExpression(context, expression) {
12574
12660
  case "nil-literal":
12575
12661
  return context.record(expression, NIL_TYPE);
12576
12662
  case "boolean-literal":
12577
- return context.record(expression, BOOLEAN_TYPE);
12663
+ return context.record(expression, createBooleanLiteral(expression.value));
12578
12664
  case "number-literal":
12579
- return context.record(expression, NUMBER_TYPE);
12665
+ return context.record(expression, createNumberLiteral(expression.value));
12580
12666
  case "string-literal":
12581
12667
  return context.record(expression, createStringLiteral(expression.value));
12582
12668
  case "template-literal":
@@ -12823,11 +12909,21 @@ function checkEnumDeclaration(context, statement) {
12823
12909
  }
12824
12910
 
12825
12911
  // ../compiler/src/checker/discriminant.ts
12912
+ function literalValue(expression) {
12913
+ if (expression.kind === "string-literal") {
12914
+ return createStringLiteral(expression.value);
12915
+ }
12916
+ if (expression.kind === "boolean-literal") {
12917
+ return createBooleanLiteral(expression.value);
12918
+ }
12919
+ return expression.kind === "number-literal" ? createNumberLiteral(expression.value) : null;
12920
+ }
12826
12921
  function discriminantTest(left, right) {
12827
- if (left.kind !== "member-expression" || left.object.kind !== "identifier" || right.kind !== "string-literal") {
12922
+ if (left.kind !== "member-expression" || left.object.kind !== "identifier") {
12828
12923
  return null;
12829
12924
  }
12830
- return { name: left.object.name, property: left.property, value: createStringLiteral(right.value) };
12925
+ const value = literalValue(right);
12926
+ return value === null ? null : { name: left.object.name, property: left.property, value };
12831
12927
  }
12832
12928
  function subjectType(context, name) {
12833
12929
  const type = context.narrowedType(name) ?? context.binder.lookup(name)?.type ?? null;
@@ -13112,7 +13208,7 @@ function checkLocal(context, statement) {
13112
13208
  const valueType = valueTypes[index] ?? NIL_TYPE;
13113
13209
  context.forgetNarrowing(declaration.name);
13114
13210
  if (declaration.annotation === null) {
13115
- const inferred = context.allowNil || value === void 0 ? ANY_TYPE : widenLiteral(valueType);
13211
+ const inferred = context.allowNil || value === void 0 ? ANY_TYPE : widenInferred(valueType);
13116
13212
  context.binder.declare({ name: declaration.name, type: inferred, isLocal: true, position: declaration.position });
13117
13213
  return;
13118
13214
  }
@@ -13331,6 +13427,7 @@ function check(program2, mode, environment = DEFAULT_ENVIRONMENT, options = {})
13331
13427
  types: context.types,
13332
13428
  references: context.references,
13333
13429
  declarations: context.declarations,
13430
+ aliases: context.binder.resolvedAliases(),
13334
13431
  declaredGlobals: context.declaredGlobals,
13335
13432
  externalReferences: externalReferences(context),
13336
13433
  directives: directives.directives,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thigasdevelopment/luam",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "description": "The Luam compiler for Multi Theft Auto resources.",
5
5
  "keywords": [
6
6
  "mta",