@mojir/lits 2.4.1 → 2.5.0
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/README.md +2 -2
- package/dist/cli/cli.js +69 -20
- package/dist/cli/src/Lits/Lits.d.ts +8 -4
- package/dist/cli/src/builtin/interface.d.ts +1 -0
- package/dist/cli/src/evaluator/ContextStack.d.ts +4 -2
- package/dist/cli/src/index.d.ts +1 -1
- package/dist/full.esm.js +1 -1
- package/dist/full.esm.js.map +1 -1
- package/dist/full.js +1 -1
- package/dist/full.js.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lits.iife.js +1 -1
- package/dist/lits.iife.js.map +1 -1
- package/dist/modules/random.esm.js +1 -1
- package/dist/modules/random.esm.js.map +1 -1
- package/dist/modules/random.js +1 -1
- package/dist/modules/random.js.map +1 -1
- package/dist/modules/src/Lits/Lits.d.ts +8 -4
- package/dist/modules/src/builtin/interface.d.ts +1 -0
- package/dist/modules/src/evaluator/ContextStack.d.ts +4 -2
- package/dist/modules/src/index.d.ts +1 -1
- package/dist/src/Lits/Lits.d.ts +8 -4
- package/dist/src/builtin/interface.d.ts +1 -0
- package/dist/src/evaluator/ContextStack.d.ts +4 -2
- package/dist/src/index.d.ts +1 -1
- package/dist/testFramework.esm.js +1 -1
- package/dist/testFramework.esm.js.map +1 -1
- package/dist/testFramework.js +1 -1
- package/dist/testFramework.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,10 +48,10 @@ $ lits eval "[1, 2, 3, 4] filter odd? map inc"
|
|
|
48
48
|
$ lits run script.lits
|
|
49
49
|
|
|
50
50
|
# Bundle a multi-file project into a single .json file
|
|
51
|
-
$ lits bundle main.lits -o bundle.json
|
|
51
|
+
$ lits bundle main.lits -o bundle.lits.json
|
|
52
52
|
|
|
53
53
|
# Run a bundle
|
|
54
|
-
$ lits run-bundle bundle.json
|
|
54
|
+
$ lits run-bundle bundle.lits.json
|
|
55
55
|
|
|
56
56
|
# Run tests
|
|
57
57
|
$ lits test tests.test.lits
|
package/dist/cli/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ var readline = require('node:readline');
|
|
|
7
7
|
var os = require('node:os');
|
|
8
8
|
var process$1 = require('node:process');
|
|
9
9
|
|
|
10
|
-
var version = "2.
|
|
10
|
+
var version = "2.5.0";
|
|
11
11
|
|
|
12
12
|
function getCodeMarker(sourceCodeInfo) {
|
|
13
13
|
if (!sourceCodeInfo.position || !sourceCodeInfo.code)
|
|
@@ -3677,6 +3677,7 @@ const miscNormalExpression = {
|
|
|
3677
3677
|
return asAny(params[params.length - 1], sourceCodeInfo);
|
|
3678
3678
|
return null;
|
|
3679
3679
|
},
|
|
3680
|
+
pure: false,
|
|
3680
3681
|
arity: {},
|
|
3681
3682
|
docs: {
|
|
3682
3683
|
category: 'misc',
|
|
@@ -6757,7 +6758,10 @@ function isNumberReservedSymbol(symbol) {
|
|
|
6757
6758
|
}
|
|
6758
6759
|
|
|
6759
6760
|
const functionExecutors = {
|
|
6760
|
-
NativeJsFunction: (fn, params, sourceCodeInfo) => {
|
|
6761
|
+
NativeJsFunction: (fn, params, sourceCodeInfo, contextStack) => {
|
|
6762
|
+
if (contextStack.pure && !fn.nativeFn.pure) {
|
|
6763
|
+
throw new LitsError(`Cannot call impure native function '${fn.name}' in pure mode`, sourceCodeInfo);
|
|
6764
|
+
}
|
|
6761
6765
|
try {
|
|
6762
6766
|
const result = fn.nativeFn.fn(...params);
|
|
6763
6767
|
// If the native function returns a Promise, await it transparently
|
|
@@ -6938,6 +6942,9 @@ const functionExecutors = {
|
|
|
6938
6942
|
},
|
|
6939
6943
|
Builtin: (fn, params, sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
6940
6944
|
const normalExpression = asNonUndefined(allNormalExpressions[fn.normalBuiltinSymbolType], sourceCodeInfo);
|
|
6945
|
+
if (contextStack.pure && normalExpression.pure === false) {
|
|
6946
|
+
throw new LitsError(`Cannot call impure function '${fn.name}' in pure mode`, sourceCodeInfo);
|
|
6947
|
+
}
|
|
6941
6948
|
return normalExpression.evaluate(params, sourceCodeInfo, contextStack, { executeFunction });
|
|
6942
6949
|
},
|
|
6943
6950
|
SpecialBuiltin: (fn, params, sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
@@ -6958,6 +6965,9 @@ const functionExecutors = {
|
|
|
6958
6965
|
if (!expression) {
|
|
6959
6966
|
throw new LitsError(`Function '${fn.functionName}' not found in module '${fn.moduleName}'.`, sourceCodeInfo);
|
|
6960
6967
|
}
|
|
6968
|
+
if (contextStack.pure && expression.pure === false) {
|
|
6969
|
+
throw new LitsError(`Cannot call impure function '${fn.functionName}' in pure mode`, sourceCodeInfo);
|
|
6970
|
+
}
|
|
6961
6971
|
assertNumberOfParams(expression.arity, params.length, sourceCodeInfo);
|
|
6962
6972
|
return expression.evaluate(params, sourceCodeInfo, contextStack, { executeFunction });
|
|
6963
6973
|
},
|
|
@@ -7056,6 +7066,9 @@ function evaluateNormalExpression(node, contextStack) {
|
|
|
7056
7066
|
if (isNormalBuiltinSymbolNode(nameSymbol)) {
|
|
7057
7067
|
const type = nameSymbol[1];
|
|
7058
7068
|
const normalExpression = builtin.allNormalExpressions[type];
|
|
7069
|
+
if (contextStack.pure && normalExpression.pure === false) {
|
|
7070
|
+
throw new LitsError(`Cannot call impure function '${normalExpression.name}' in pure mode`, node[2]);
|
|
7071
|
+
}
|
|
7059
7072
|
return normalExpression.evaluate(params, node[2], contextStack, { executeFunction });
|
|
7060
7073
|
}
|
|
7061
7074
|
else {
|
|
@@ -7152,13 +7165,15 @@ class ContextStackImpl {
|
|
|
7152
7165
|
nativeJsFunctions;
|
|
7153
7166
|
modules;
|
|
7154
7167
|
valueModules;
|
|
7155
|
-
|
|
7168
|
+
pure;
|
|
7169
|
+
constructor({ contexts, values: hostValues, nativeJsFunctions, modules, valueModules, pure, }) {
|
|
7156
7170
|
this.globalContext = asNonUndefined(contexts[0]);
|
|
7157
7171
|
this.contexts = contexts;
|
|
7158
7172
|
this.values = hostValues;
|
|
7159
7173
|
this.nativeJsFunctions = nativeJsFunctions;
|
|
7160
7174
|
this.modules = modules ?? new Map();
|
|
7161
7175
|
this.valueModules = valueModules ?? new Map();
|
|
7176
|
+
this.pure = pure ?? false;
|
|
7162
7177
|
}
|
|
7163
7178
|
getModule(name) {
|
|
7164
7179
|
return this.modules.get(name);
|
|
@@ -7180,13 +7195,14 @@ class ContextStackImpl {
|
|
|
7180
7195
|
nativeJsFunctions: this.nativeJsFunctions,
|
|
7181
7196
|
modules: this.modules,
|
|
7182
7197
|
valueModules: this.valueModules,
|
|
7198
|
+
pure: this.pure,
|
|
7183
7199
|
});
|
|
7184
7200
|
contextStack.globalContext = globalContext;
|
|
7185
7201
|
return contextStack;
|
|
7186
7202
|
}
|
|
7187
7203
|
new(context) {
|
|
7188
7204
|
const contexts = [{}, context];
|
|
7189
|
-
return new ContextStackImpl({ contexts, modules: this.modules, valueModules: this.valueModules });
|
|
7205
|
+
return new ContextStackImpl({ contexts, modules: this.modules, valueModules: this.valueModules, pure: this.pure });
|
|
7190
7206
|
}
|
|
7191
7207
|
addValues(values, sourceCodeInfo) {
|
|
7192
7208
|
const currentContext = this.contexts[0];
|
|
@@ -7292,7 +7308,7 @@ function assertNotShadowingBuiltin(name) {
|
|
|
7292
7308
|
throw new LitsError(`Cannot shadow ${shadowedName}`, undefined);
|
|
7293
7309
|
}
|
|
7294
7310
|
}
|
|
7295
|
-
function createContextStack(params = {}, modules) {
|
|
7311
|
+
function createContextStack(params = {}, modules, pure) {
|
|
7296
7312
|
const globalContext = params.globalContext ?? {};
|
|
7297
7313
|
// Contexts are checked from left to right
|
|
7298
7314
|
const contexts = params.contexts ? [globalContext, ...params.contexts] : [globalContext];
|
|
@@ -7336,6 +7352,7 @@ function createContextStack(params = {}, modules) {
|
|
|
7336
7352
|
values: hostValues,
|
|
7337
7353
|
modules,
|
|
7338
7354
|
nativeJsFunctions,
|
|
7355
|
+
pure,
|
|
7339
7356
|
});
|
|
7340
7357
|
return params.globalModuleScope ? contextStack : contextStack.create({});
|
|
7341
7358
|
}
|
|
@@ -9443,9 +9460,13 @@ class Lits {
|
|
|
9443
9460
|
return result;
|
|
9444
9461
|
}
|
|
9445
9462
|
runBundle(bundle, params = {}) {
|
|
9446
|
-
const contextStack = createContextStack(params, this.modules);
|
|
9463
|
+
const contextStack = createContextStack(params, this.modules, params.pure);
|
|
9447
9464
|
// Evaluate file modules in dependency order and register as value modules.
|
|
9448
9465
|
// Each file module is evaluated in its own scope so local bindings don't leak.
|
|
9466
|
+
// File modules are always evaluated in pure mode to ensure deterministic,
|
|
9467
|
+
// side-effect-free initialization regardless of the caller's pure setting.
|
|
9468
|
+
const savedPure = contextStack.pure;
|
|
9469
|
+
contextStack.pure = true;
|
|
9449
9470
|
for (const [name, source] of bundle.fileModules) {
|
|
9450
9471
|
const ast = this.generateAst(source, params);
|
|
9451
9472
|
const moduleContextStack = contextStack.create({});
|
|
@@ -9455,6 +9476,7 @@ class Lits {
|
|
|
9455
9476
|
}
|
|
9456
9477
|
contextStack.registerValueModule(name, result);
|
|
9457
9478
|
}
|
|
9479
|
+
contextStack.pure = savedPure;
|
|
9458
9480
|
// Parse and evaluate the main program
|
|
9459
9481
|
const ast = this.generateAst(bundle.program, params);
|
|
9460
9482
|
const result = evaluate(ast, contextStack);
|
|
@@ -9482,7 +9504,7 @@ class Lits {
|
|
|
9482
9504
|
return ast;
|
|
9483
9505
|
}
|
|
9484
9506
|
evaluate(ast, params) {
|
|
9485
|
-
const contextStack = createContextStack(params, this.modules);
|
|
9507
|
+
const contextStack = createContextStack(params, this.modules, params.pure);
|
|
9486
9508
|
return evaluate(ast, contextStack);
|
|
9487
9509
|
}
|
|
9488
9510
|
transformSymbols(tokenStream, transformer) {
|
|
@@ -13256,6 +13278,7 @@ const randomFunctions = {
|
|
|
13256
13278
|
evaluate: () => {
|
|
13257
13279
|
return Math.random();
|
|
13258
13280
|
},
|
|
13281
|
+
pure: false,
|
|
13259
13282
|
arity: toFixedArity(0),
|
|
13260
13283
|
},
|
|
13261
13284
|
'random-int!': {
|
|
@@ -13264,6 +13287,7 @@ const randomFunctions = {
|
|
|
13264
13287
|
assertNumber(max, sourceCodeInfo, { integer: true, gt: min });
|
|
13265
13288
|
return Math.floor(Math.random() * (max - min)) + min;
|
|
13266
13289
|
},
|
|
13290
|
+
pure: false,
|
|
13267
13291
|
arity: toFixedArity(2),
|
|
13268
13292
|
},
|
|
13269
13293
|
'random-int-inclusive!': {
|
|
@@ -13272,6 +13296,7 @@ const randomFunctions = {
|
|
|
13272
13296
|
assertNumber(max, sourceCodeInfo, { integer: true, gte: min });
|
|
13273
13297
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
13274
13298
|
},
|
|
13299
|
+
pure: false,
|
|
13275
13300
|
arity: toFixedArity(2),
|
|
13276
13301
|
},
|
|
13277
13302
|
'random-float!': {
|
|
@@ -13280,6 +13305,7 @@ const randomFunctions = {
|
|
|
13280
13305
|
assertNumber(max, sourceCodeInfo, { gt: min });
|
|
13281
13306
|
return Math.random() * (max - min) + min;
|
|
13282
13307
|
},
|
|
13308
|
+
pure: false,
|
|
13283
13309
|
arity: toFixedArity(2),
|
|
13284
13310
|
},
|
|
13285
13311
|
'random-boolean!': {
|
|
@@ -13288,6 +13314,7 @@ const randomFunctions = {
|
|
|
13288
13314
|
assertNumber(probability, sourceCodeInfo, { gte: 0, lte: 1 });
|
|
13289
13315
|
return Math.random() < probability;
|
|
13290
13316
|
},
|
|
13317
|
+
pure: false,
|
|
13291
13318
|
arity: { min: 0, max: 1 },
|
|
13292
13319
|
},
|
|
13293
13320
|
'random-item!': {
|
|
@@ -13296,6 +13323,7 @@ const randomFunctions = {
|
|
|
13296
13323
|
const index = Math.floor(Math.random() * array.length);
|
|
13297
13324
|
return asAny(array[index]);
|
|
13298
13325
|
},
|
|
13326
|
+
pure: false,
|
|
13299
13327
|
arity: toFixedArity(1),
|
|
13300
13328
|
},
|
|
13301
13329
|
'random-sample!': {
|
|
@@ -13314,6 +13342,7 @@ const randomFunctions = {
|
|
|
13314
13342
|
}
|
|
13315
13343
|
return result;
|
|
13316
13344
|
},
|
|
13345
|
+
pure: false,
|
|
13317
13346
|
arity: toFixedArity(2),
|
|
13318
13347
|
},
|
|
13319
13348
|
'random-sample-unique!': {
|
|
@@ -13335,6 +13364,7 @@ const randomFunctions = {
|
|
|
13335
13364
|
}
|
|
13336
13365
|
return result;
|
|
13337
13366
|
},
|
|
13367
|
+
pure: false,
|
|
13338
13368
|
arity: toFixedArity(2),
|
|
13339
13369
|
},
|
|
13340
13370
|
'shuffle!': {
|
|
@@ -13347,6 +13377,7 @@ const randomFunctions = {
|
|
|
13347
13377
|
}
|
|
13348
13378
|
return shuffledArray;
|
|
13349
13379
|
},
|
|
13380
|
+
pure: false,
|
|
13350
13381
|
arity: toFixedArity(1),
|
|
13351
13382
|
},
|
|
13352
13383
|
'random-normal!': {
|
|
@@ -13358,6 +13389,7 @@ const randomFunctions = {
|
|
|
13358
13389
|
const z0 = Math.sqrt(-2.0 * Math.log(u1)) * Math.cos(2.0 * Math.PI * u2);
|
|
13359
13390
|
return z0 * stdDev + mean;
|
|
13360
13391
|
},
|
|
13392
|
+
pure: false,
|
|
13361
13393
|
arity: toFixedArity(2),
|
|
13362
13394
|
},
|
|
13363
13395
|
'random-exponential!': {
|
|
@@ -13366,6 +13398,7 @@ const randomFunctions = {
|
|
|
13366
13398
|
const u = Math.random();
|
|
13367
13399
|
return -Math.log(u) / lambda;
|
|
13368
13400
|
},
|
|
13401
|
+
pure: false,
|
|
13369
13402
|
arity: toFixedArity(1),
|
|
13370
13403
|
},
|
|
13371
13404
|
'random-binomial!': {
|
|
@@ -13380,6 +13413,7 @@ const randomFunctions = {
|
|
|
13380
13413
|
}
|
|
13381
13414
|
return k;
|
|
13382
13415
|
},
|
|
13416
|
+
pure: false,
|
|
13383
13417
|
arity: toFixedArity(2),
|
|
13384
13418
|
},
|
|
13385
13419
|
'random-poisson!': {
|
|
@@ -13394,6 +13428,7 @@ const randomFunctions = {
|
|
|
13394
13428
|
} while (p > L);
|
|
13395
13429
|
return k - 1;
|
|
13396
13430
|
},
|
|
13431
|
+
pure: false,
|
|
13397
13432
|
arity: toFixedArity(1),
|
|
13398
13433
|
},
|
|
13399
13434
|
'random-gamma!': {
|
|
@@ -13402,6 +13437,7 @@ const randomFunctions = {
|
|
|
13402
13437
|
assertNumber(scale, sourceCodeInfo, { gt: 0 });
|
|
13403
13438
|
return randomGamma(shape, scale);
|
|
13404
13439
|
},
|
|
13440
|
+
pure: false,
|
|
13405
13441
|
arity: toFixedArity(2),
|
|
13406
13442
|
},
|
|
13407
13443
|
'random-pareto!': {
|
|
@@ -13410,6 +13446,7 @@ const randomFunctions = {
|
|
|
13410
13446
|
const u = Math.random();
|
|
13411
13447
|
return (1 / u) ** (1 / alpha);
|
|
13412
13448
|
},
|
|
13449
|
+
pure: false,
|
|
13413
13450
|
arity: toFixedArity(1),
|
|
13414
13451
|
},
|
|
13415
13452
|
'uuid!': {
|
|
@@ -13420,6 +13457,7 @@ const randomFunctions = {
|
|
|
13420
13457
|
return value.toString(16);
|
|
13421
13458
|
});
|
|
13422
13459
|
},
|
|
13460
|
+
pure: false,
|
|
13423
13461
|
arity: toFixedArity(0),
|
|
13424
13462
|
},
|
|
13425
13463
|
'random-char!': {
|
|
@@ -13431,6 +13469,7 @@ const randomFunctions = {
|
|
|
13431
13469
|
const randomIndex = Math.floor(Math.random() * charSet.length);
|
|
13432
13470
|
return charSet[randomIndex];
|
|
13433
13471
|
},
|
|
13472
|
+
pure: false,
|
|
13434
13473
|
arity: toFixedArity(1),
|
|
13435
13474
|
},
|
|
13436
13475
|
'random-string!': {
|
|
@@ -13447,6 +13486,7 @@ const randomFunctions = {
|
|
|
13447
13486
|
}
|
|
13448
13487
|
return result;
|
|
13449
13488
|
},
|
|
13489
|
+
pure: false,
|
|
13450
13490
|
arity: toFixedArity(2),
|
|
13451
13491
|
},
|
|
13452
13492
|
'random-id!': {
|
|
@@ -13460,6 +13500,7 @@ const randomFunctions = {
|
|
|
13460
13500
|
}
|
|
13461
13501
|
return result;
|
|
13462
13502
|
},
|
|
13503
|
+
pure: false,
|
|
13463
13504
|
arity: toFixedArity(1),
|
|
13464
13505
|
},
|
|
13465
13506
|
'random-color!': {
|
|
@@ -13467,6 +13508,7 @@ const randomFunctions = {
|
|
|
13467
13508
|
const randomColor = Math.floor(Math.random() * 0x1000000).toString(16);
|
|
13468
13509
|
return `#${randomColor.padStart(6, '0')}`;
|
|
13469
13510
|
},
|
|
13511
|
+
pure: false,
|
|
13470
13512
|
arity: toFixedArity(0),
|
|
13471
13513
|
},
|
|
13472
13514
|
};
|
|
@@ -34633,18 +34675,19 @@ const helpRegExp = new RegExp(`^\`help\\s+(${polishSymbolFirstCharacterClass}${p
|
|
|
34633
34675
|
const expressions = [...normalExpressionKeys, ...specialExpressionKeys];
|
|
34634
34676
|
const config = processArguments(process.argv.slice(2));
|
|
34635
34677
|
const cliModules = getCliModules();
|
|
34636
|
-
function createLits(context) {
|
|
34678
|
+
function createLits(context, pure) {
|
|
34637
34679
|
const _lits = new Lits({ debug: true, modules: [...allBuiltinModules, ...cliModules] });
|
|
34638
34680
|
return {
|
|
34639
34681
|
run: (program) => _lits.run(program, {
|
|
34640
34682
|
globalContext: context,
|
|
34641
34683
|
globalModuleScope: true,
|
|
34684
|
+
pure,
|
|
34642
34685
|
}),
|
|
34643
34686
|
};
|
|
34644
34687
|
}
|
|
34645
34688
|
switch (config.subcommand) {
|
|
34646
34689
|
case 'run': {
|
|
34647
|
-
const lits = createLits(config.context);
|
|
34690
|
+
const lits = createLits(config.context, config.pure);
|
|
34648
34691
|
try {
|
|
34649
34692
|
const content = fs.readFileSync(config.filename, { encoding: 'utf-8' });
|
|
34650
34693
|
const result = lits.run(content);
|
|
@@ -34660,7 +34703,7 @@ switch (config.subcommand) {
|
|
|
34660
34703
|
break;
|
|
34661
34704
|
}
|
|
34662
34705
|
case 'run-bundle': {
|
|
34663
|
-
const lits = createLits(config.context);
|
|
34706
|
+
const lits = createLits(config.context, config.pure);
|
|
34664
34707
|
try {
|
|
34665
34708
|
const content = fs.readFileSync(config.filename, { encoding: 'utf-8' });
|
|
34666
34709
|
let parsed;
|
|
@@ -34688,7 +34731,7 @@ switch (config.subcommand) {
|
|
|
34688
34731
|
break;
|
|
34689
34732
|
}
|
|
34690
34733
|
case 'eval': {
|
|
34691
|
-
const lits = createLits(config.context);
|
|
34734
|
+
const lits = createLits(config.context, config.pure);
|
|
34692
34735
|
try {
|
|
34693
34736
|
const result = lits.run(config.expression);
|
|
34694
34737
|
if (config.printResult) {
|
|
@@ -34728,7 +34771,7 @@ switch (config.subcommand) {
|
|
|
34728
34771
|
}
|
|
34729
34772
|
case 'repl': {
|
|
34730
34773
|
if (config.loadFilename) {
|
|
34731
|
-
const lits = createLits(config.context);
|
|
34774
|
+
const lits = createLits(config.context, false);
|
|
34732
34775
|
const content = fs.readFileSync(config.loadFilename, { encoding: 'utf-8' });
|
|
34733
34776
|
const result = lits.run(content);
|
|
34734
34777
|
if (result !== null && typeof result === 'object' && !Array.isArray(result)) {
|
|
@@ -34765,7 +34808,7 @@ function runLitsTest(testPath, testNamePattern) {
|
|
|
34765
34808
|
process.exit(1);
|
|
34766
34809
|
}
|
|
34767
34810
|
function execute(expression, context) {
|
|
34768
|
-
const lits = createLits(context);
|
|
34811
|
+
const lits = createLits(context, false);
|
|
34769
34812
|
try {
|
|
34770
34813
|
const result = lits.run(expression);
|
|
34771
34814
|
historyResults.unshift(result);
|
|
@@ -34884,6 +34927,7 @@ function parsePrintOptions(args, startIndex) {
|
|
|
34884
34927
|
function parseRunEvalOptions(args, startIndex) {
|
|
34885
34928
|
let context = {};
|
|
34886
34929
|
let printResult = true;
|
|
34930
|
+
let pure = false;
|
|
34887
34931
|
let i = startIndex;
|
|
34888
34932
|
while (i < args.length) {
|
|
34889
34933
|
const parsed = parseOption(args, i);
|
|
@@ -34906,6 +34950,10 @@ function parseRunEvalOptions(args, startIndex) {
|
|
|
34906
34950
|
i = result.nextIndex;
|
|
34907
34951
|
break;
|
|
34908
34952
|
}
|
|
34953
|
+
case '--pure':
|
|
34954
|
+
pure = true;
|
|
34955
|
+
i += parsed.count;
|
|
34956
|
+
break;
|
|
34909
34957
|
default:
|
|
34910
34958
|
printErrorMessage(`Unknown option "${parsed.option}"`);
|
|
34911
34959
|
process.exit(1);
|
|
@@ -34915,7 +34963,7 @@ function parseRunEvalOptions(args, startIndex) {
|
|
|
34915
34963
|
printErrorMessage(`Unknown argument "${args[i]}"`);
|
|
34916
34964
|
process.exit(1);
|
|
34917
34965
|
}
|
|
34918
|
-
return { context, printResult, nextIndex: i };
|
|
34966
|
+
return { context, printResult, pure, nextIndex: i };
|
|
34919
34967
|
}
|
|
34920
34968
|
function processArguments(args) {
|
|
34921
34969
|
// Global flags (no subcommand)
|
|
@@ -34936,8 +34984,8 @@ function processArguments(args) {
|
|
|
34936
34984
|
printErrorMessage('Missing filename after "run"');
|
|
34937
34985
|
process.exit(1);
|
|
34938
34986
|
}
|
|
34939
|
-
const { context, printResult } = parseRunEvalOptions(args, 2);
|
|
34940
|
-
return { subcommand: 'run', filename, context, printResult };
|
|
34987
|
+
const { context, printResult, pure } = parseRunEvalOptions(args, 2);
|
|
34988
|
+
return { subcommand: 'run', filename, context, printResult, pure };
|
|
34941
34989
|
}
|
|
34942
34990
|
case 'run-bundle': {
|
|
34943
34991
|
const filename = args[1];
|
|
@@ -34945,8 +34993,8 @@ function processArguments(args) {
|
|
|
34945
34993
|
printErrorMessage('Missing filename after "run-bundle"');
|
|
34946
34994
|
process.exit(1);
|
|
34947
34995
|
}
|
|
34948
|
-
const { context, printResult } = parseRunEvalOptions(args, 2);
|
|
34949
|
-
return { subcommand: 'run-bundle', filename, context, printResult };
|
|
34996
|
+
const { context, printResult, pure } = parseRunEvalOptions(args, 2);
|
|
34997
|
+
return { subcommand: 'run-bundle', filename, context, printResult, pure };
|
|
34950
34998
|
}
|
|
34951
34999
|
case 'eval': {
|
|
34952
35000
|
const expression = args[1];
|
|
@@ -34954,8 +35002,8 @@ function processArguments(args) {
|
|
|
34954
35002
|
printErrorMessage('Missing expression after "eval"');
|
|
34955
35003
|
process.exit(1);
|
|
34956
35004
|
}
|
|
34957
|
-
const { context, printResult } = parseRunEvalOptions(args, 2);
|
|
34958
|
-
return { subcommand: 'eval', expression, context, printResult };
|
|
35005
|
+
const { context, printResult, pure } = parseRunEvalOptions(args, 2);
|
|
35006
|
+
return { subcommand: 'eval', expression, context, printResult, pure };
|
|
34959
35007
|
}
|
|
34960
35008
|
case 'bundle': {
|
|
34961
35009
|
const filename = args[1];
|
|
@@ -35147,6 +35195,7 @@ Run/Run-bundle/Eval options:
|
|
|
35147
35195
|
-c, --context=<json> Context as a JSON string
|
|
35148
35196
|
-C, --context-file=<file> Context from a .json file
|
|
35149
35197
|
-s, --silent Suppress printing the result
|
|
35198
|
+
--pure Enforce pure mode (no side effects or non-determinism)
|
|
35150
35199
|
|
|
35151
35200
|
Bundle options:
|
|
35152
35201
|
-o, --output=<file> Write bundle to file (default: stdout)
|
|
@@ -16,6 +16,7 @@ export interface LitsRuntimeInfo {
|
|
|
16
16
|
export interface JsFunction {
|
|
17
17
|
fn: (...args: any[]) => unknown;
|
|
18
18
|
arity?: Arity;
|
|
19
|
+
pure?: boolean;
|
|
19
20
|
docString?: string;
|
|
20
21
|
}
|
|
21
22
|
export interface ContextParams {
|
|
@@ -30,6 +31,9 @@ export interface MinifyParams {
|
|
|
30
31
|
export interface FilePathParams {
|
|
31
32
|
filePath?: string;
|
|
32
33
|
}
|
|
34
|
+
export interface PureParams {
|
|
35
|
+
pure?: boolean;
|
|
36
|
+
}
|
|
33
37
|
interface LitsConfig {
|
|
34
38
|
initialCache?: Record<string, Ast>;
|
|
35
39
|
astCacheSize?: number | null;
|
|
@@ -44,10 +48,10 @@ export declare class Lits {
|
|
|
44
48
|
constructor(config?: LitsConfig);
|
|
45
49
|
getRuntimeInfo(): LitsRuntimeInfo;
|
|
46
50
|
readonly async: {
|
|
47
|
-
run: (programOrBundle: string | LitsBundle, params?: ContextParams & FilePathParams) => Promise<unknown>;
|
|
48
|
-
apply: (fn: LitsFunction, fnParams: unknown[], params?: ContextParams) => Promise<unknown>;
|
|
51
|
+
run: (programOrBundle: string | LitsBundle, params?: ContextParams & FilePathParams & PureParams) => Promise<unknown>;
|
|
52
|
+
apply: (fn: LitsFunction, fnParams: unknown[], params?: ContextParams & PureParams) => Promise<unknown>;
|
|
49
53
|
};
|
|
50
|
-
run(programOrBundle: string | LitsBundle, params?: ContextParams & FilePathParams): unknown;
|
|
54
|
+
run(programOrBundle: string | LitsBundle, params?: ContextParams & FilePathParams & PureParams): unknown;
|
|
51
55
|
private runBundle;
|
|
52
56
|
getUndefinedSymbols(programOrAst: string | Ast, params?: ContextParams): Set<string>;
|
|
53
57
|
tokenize(program: string, tokenizeParams?: FilePathParams & MinifyParams): TokenStream;
|
|
@@ -55,7 +59,7 @@ export declare class Lits {
|
|
|
55
59
|
private evaluate;
|
|
56
60
|
transformSymbols(tokenStream: TokenStream, transformer: (symbol: string) => string): TokenStream;
|
|
57
61
|
untokenize(tokenStream: TokenStream): string;
|
|
58
|
-
apply(fn: LitsFunction, fnParams: unknown[], params?: ContextParams): MaybePromise<Any>;
|
|
62
|
+
apply(fn: LitsFunction, fnParams: unknown[], params?: ContextParams & PureParams): MaybePromise<Any>;
|
|
59
63
|
private generateApplyFunctionCall;
|
|
60
64
|
private generateAst;
|
|
61
65
|
getAutoCompleter(program: string, position: number, params?: ContextParams): AutoCompleter;
|
|
@@ -80,6 +80,7 @@ type NormalExpressionEvaluator<T> = (params: Arr, sourceCodeInfo: SourceCodeInfo
|
|
|
80
80
|
}) => MaybePromise<T>;
|
|
81
81
|
export interface BuiltinNormalExpression<T> {
|
|
82
82
|
evaluate: NormalExpressionEvaluator<T>;
|
|
83
|
+
pure?: boolean;
|
|
83
84
|
name?: string;
|
|
84
85
|
arity: Arity;
|
|
85
86
|
docs?: FunctionDocs;
|
|
@@ -12,12 +12,14 @@ export declare class ContextStackImpl {
|
|
|
12
12
|
private nativeJsFunctions?;
|
|
13
13
|
private modules;
|
|
14
14
|
private valueModules;
|
|
15
|
-
|
|
15
|
+
pure: boolean;
|
|
16
|
+
constructor({ contexts, values: hostValues, nativeJsFunctions, modules, valueModules, pure, }: {
|
|
16
17
|
contexts: Context[];
|
|
17
18
|
values?: Record<string, unknown>;
|
|
18
19
|
nativeJsFunctions?: Record<string, NativeJsFunction>;
|
|
19
20
|
modules?: Map<string, LitsModule>;
|
|
20
21
|
valueModules?: Map<string, unknown>;
|
|
22
|
+
pure?: boolean;
|
|
21
23
|
});
|
|
22
24
|
getModule(name: string): LitsModule | undefined;
|
|
23
25
|
getValueModule(name: string): {
|
|
@@ -32,4 +34,4 @@ export declare class ContextStackImpl {
|
|
|
32
34
|
lookUp(node: UserDefinedSymbolNode): LookUpResult;
|
|
33
35
|
evaluateSymbol(node: SymbolNode): Any;
|
|
34
36
|
}
|
|
35
|
-
export declare function createContextStack(params?: ContextParams, modules?: Map<string, LitsModule
|
|
37
|
+
export declare function createContextStack(params?: ContextParams, modules?: Map<string, LitsModule>, pure?: boolean): ContextStack;
|
package/dist/cli/src/index.d.ts
CHANGED
|
@@ -11,6 +11,6 @@ export type { LitsModule } from './builtin/modules/interface';
|
|
|
11
11
|
export type { LitsBundle } from './bundler/interface';
|
|
12
12
|
export { isLitsBundle } from './bundler/interface';
|
|
13
13
|
export { type LitsError, isLitsError } from './errors';
|
|
14
|
-
export type { ContextParams, FilePathParams, MinifyParams, LitsRuntimeInfo, JsFunction } from './Lits/Lits';
|
|
14
|
+
export type { ContextParams, FilePathParams, MinifyParams, PureParams, LitsRuntimeInfo, JsFunction } from './Lits/Lits';
|
|
15
15
|
export { isGrid, isMatrix, isVector } from './typeGuards/annotatedArrays';
|
|
16
16
|
export type { AutoCompleter } from './AutoCompleter/AutoCompleter';
|