@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.
- package/luam.mjs +116 -19
- 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"
|
|
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 (
|
|
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.
|
|
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("
|
|
8301
|
-
dbExec: fn([named("
|
|
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("
|
|
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("
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
12663
|
+
return context.record(expression, createBooleanLiteral(expression.value));
|
|
12578
12664
|
case "number-literal":
|
|
12579
|
-
return context.record(expression,
|
|
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"
|
|
12922
|
+
if (left.kind !== "member-expression" || left.object.kind !== "identifier") {
|
|
12828
12923
|
return null;
|
|
12829
12924
|
}
|
|
12830
|
-
|
|
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 :
|
|
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,
|