alanvww/p5js-object-detection-webgpu
1
1/******/ var __webpack_modules__ = ({2 3/***/ "?2ce3":4/*!**********************************!*\5 !*** onnxruntime-node (ignored) ***!6 \**********************************/7/***/ (() => {8 9/* (ignored) */10 11/***/ }),12 13/***/ "?7a2c":14/*!********************!*\15 !*** fs (ignored) ***!16 \********************/17/***/ (() => {18 19/* (ignored) */20 21/***/ }),22 23/***/ "?a42a":24/*!**********************!*\25 !*** path (ignored) ***!26 \**********************/27/***/ (() => {28 29/* (ignored) */30 31/***/ }),32 33/***/ "?2b25":34/*!***********************!*\35 !*** sharp (ignored) ***!36 \***********************/37/***/ (() => {38 39/* (ignored) */40 41/***/ }),42 43/***/ "?569f":44/*!********************!*\45 !*** fs (ignored) ***!46 \********************/47/***/ (() => {48 49/* (ignored) */50 51/***/ }),52 53/***/ "?3f59":54/*!**********************!*\55 !*** path (ignored) ***!56 \**********************/57/***/ (() => {58 59/* (ignored) */60 61/***/ }),62 63/***/ "?154a":64/*!*********************!*\65 !*** url (ignored) ***!66 \*********************/67/***/ (() => {68 69/* (ignored) */70 71/***/ }),72 73/***/ "./node_modules/@huggingface/jinja/dist/index.js":74/*!*******************************************************!*\75 !*** ./node_modules/@huggingface/jinja/dist/index.js ***!76 \*******************************************************/77/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {78 79__webpack_require__.r(__webpack_exports__);80/* harmony export */ __webpack_require__.d(__webpack_exports__, {81/* harmony export */ "Environment": () => (/* binding */ Environment),82/* harmony export */ "Interpreter": () => (/* binding */ Interpreter),83/* harmony export */ "Template": () => (/* binding */ Template),84/* harmony export */ "parse": () => (/* binding */ parse),85/* harmony export */ "tokenize": () => (/* binding */ tokenize)86/* harmony export */ });87// src/lexer.ts88var TOKEN_TYPES = Object.freeze({89 Text: "Text",90 // The text between Jinja statements or expressions91 NumericLiteral: "NumericLiteral",92 // e.g., 12393 BooleanLiteral: "BooleanLiteral",94 // true or false95 StringLiteral: "StringLiteral",96 // 'string'97 Identifier: "Identifier",98 // Variables, functions, etc.99 Equals: "Equals",100 // =101 OpenParen: "OpenParen",102 // (103 CloseParen: "CloseParen",104 // )105 OpenStatement: "OpenStatement",106 // {%107 CloseStatement: "CloseStatement",108 // %}109 OpenExpression: "OpenExpression",110 // {{111 CloseExpression: "CloseExpression",112 // }}113 OpenSquareBracket: "OpenSquareBracket",114 // [115 CloseSquareBracket: "CloseSquareBracket",116 // ]117 OpenCurlyBracket: "OpenCurlyBracket",118 // {119 CloseCurlyBracket: "CloseCurlyBracket",120 // }121 Comma: "Comma",122 // ,123 Dot: "Dot",124 // .125 Colon: "Colon",126 // :127 Pipe: "Pipe",128 // |129 CallOperator: "CallOperator",130 // ()131 AdditiveBinaryOperator: "AdditiveBinaryOperator",132 // + -133 MultiplicativeBinaryOperator: "MultiplicativeBinaryOperator",134 // * / %135 ComparisonBinaryOperator: "ComparisonBinaryOperator",136 // < > <= >= == !=137 UnaryOperator: "UnaryOperator",138 // ! - +139 // Keywords140 Set: "Set",141 If: "If",142 For: "For",143 In: "In",144 Is: "Is",145 NotIn: "NotIn",146 Else: "Else",147 EndIf: "EndIf",148 ElseIf: "ElseIf",149 EndFor: "EndFor",150 And: "And",151 Or: "Or",152 Not: "UnaryOperator"153});154var KEYWORDS = Object.freeze({155 set: TOKEN_TYPES.Set,156 for: TOKEN_TYPES.For,157 in: TOKEN_TYPES.In,158 is: TOKEN_TYPES.Is,159 if: TOKEN_TYPES.If,160 else: TOKEN_TYPES.Else,161 endif: TOKEN_TYPES.EndIf,162 elif: TOKEN_TYPES.ElseIf,163 endfor: TOKEN_TYPES.EndFor,164 and: TOKEN_TYPES.And,165 or: TOKEN_TYPES.Or,166 not: TOKEN_TYPES.Not,167 "not in": TOKEN_TYPES.NotIn,168 // Literals169 true: TOKEN_TYPES.BooleanLiteral,170 false: TOKEN_TYPES.BooleanLiteral171});172var Token = class {173 /**174 * Constructs a new Token.175 * @param {string} value The raw value as seen inside the source code.176 * @param {TokenType} type The type of token.177 */178 constructor(value, type) {179 this.value = value;180 this.type = type;181 }182};183function isWord(char) {184 return /\w/.test(char);185}186function isInteger(char) {187 return /[0-9]/.test(char);188}189var ORDERED_MAPPING_TABLE = [190 // Control sequences191 ["{%", TOKEN_TYPES.OpenStatement],192 ["%}", TOKEN_TYPES.CloseStatement],193 ["{{", TOKEN_TYPES.OpenExpression],194 ["}}", TOKEN_TYPES.CloseExpression],195 // Single character tokens196 ["(", TOKEN_TYPES.OpenParen],197 [")", TOKEN_TYPES.CloseParen],198 ["{", TOKEN_TYPES.OpenCurlyBracket],199 ["}", TOKEN_TYPES.CloseCurlyBracket],200 ["[", TOKEN_TYPES.OpenSquareBracket],201 ["]", TOKEN_TYPES.CloseSquareBracket],202 [",", TOKEN_TYPES.Comma],203 [".", TOKEN_TYPES.Dot],204 [":", TOKEN_TYPES.Colon],205 ["|", TOKEN_TYPES.Pipe],206 // Comparison operators207 ["<=", TOKEN_TYPES.ComparisonBinaryOperator],208 [">=", TOKEN_TYPES.ComparisonBinaryOperator],209 ["==", TOKEN_TYPES.ComparisonBinaryOperator],210 ["!=", TOKEN_TYPES.ComparisonBinaryOperator],211 ["<", TOKEN_TYPES.ComparisonBinaryOperator],212 [">", TOKEN_TYPES.ComparisonBinaryOperator],213 // Arithmetic operators214 ["+", TOKEN_TYPES.AdditiveBinaryOperator],215 ["-", TOKEN_TYPES.AdditiveBinaryOperator],216 ["*", TOKEN_TYPES.MultiplicativeBinaryOperator],217 ["/", TOKEN_TYPES.MultiplicativeBinaryOperator],218 ["%", TOKEN_TYPES.MultiplicativeBinaryOperator],219 // Assignment operator220 ["=", TOKEN_TYPES.Equals]221];222var ESCAPE_CHARACTERS = /* @__PURE__ */ new Map([223 ["n", "\n"],224 // New line225 ["t", " "],226 // Horizontal tab227 ["r", "\r"],228 // Carriage return229 ["b", "\b"],230 // Backspace231 ["f", "\f"],232 // Form feed233 ["v", "\v"],234 // Vertical tab235 ["'", "'"],236 // Single quote237 ['"', '"'],238 // Double quote239 ["\\", "\\"]240 // Backslash241]);242function preprocess(template, options = {}) {243 if (template.endsWith("\n")) {244 template = template.slice(0, -1);245 }246 template = template.replace(/{#.*?#}/gs, "{##}");247 if (options.lstrip_blocks) {248 template = template.replace(/^[ \t]*({[#%])/gm, "$1");249 }250 if (options.trim_blocks) {251 template = template.replace(/([#%]})\n/g, "$1");252 }253 return template.replace(/{##}/g, "").replace(/-%}\s*/g, "%}").replace(/\s*{%-/g, "{%").replace(/-}}\s*/g, "}}").replace(/\s*{{-/g, "{{");254}255function tokenize(source, options = {}) {256 const tokens = [];257 const src = preprocess(source, options);258 let cursorPosition = 0;259 const consumeWhile = (predicate) => {260 let str = "";261 while (predicate(src[cursorPosition])) {262 if (src[cursorPosition] === "\\") {263 ++cursorPosition;264 if (cursorPosition >= src.length)265 throw new SyntaxError("Unexpected end of input");266 const escaped = src[cursorPosition++];267 const unescaped = ESCAPE_CHARACTERS.get(escaped);268 if (unescaped === void 0) {269 throw new SyntaxError(`Unexpected escaped character: ${escaped}`);270 }271 str += unescaped;272 continue;273 }274 str += src[cursorPosition++];275 if (cursorPosition >= src.length)276 throw new SyntaxError("Unexpected end of input");277 }278 return str;279 };280 main:281 while (cursorPosition < src.length) {282 const lastTokenType = tokens.at(-1)?.type;283 if (lastTokenType === void 0 || lastTokenType === TOKEN_TYPES.CloseStatement || lastTokenType === TOKEN_TYPES.CloseExpression) {284 let text = "";285 while (cursorPosition < src.length && // Keep going until we hit the next Jinja statement or expression286 !(src[cursorPosition] === "{" && (src[cursorPosition + 1] === "%" || src[cursorPosition + 1] === "{"))) {287 text += src[cursorPosition++];288 }289 if (text.length > 0) {290 tokens.push(new Token(text, TOKEN_TYPES.Text));291 continue;292 }293 }294 consumeWhile((char2) => /\s/.test(char2));295 const char = src[cursorPosition];296 if (char === "-" || char === "+") {297 const lastTokenType2 = tokens.at(-1)?.type;298 if (lastTokenType2 === TOKEN_TYPES.Text || lastTokenType2 === void 0) {299 throw new SyntaxError(`Unexpected character: ${char}`);300 }301 switch (lastTokenType2) {302 case TOKEN_TYPES.Identifier:303 case TOKEN_TYPES.NumericLiteral:304 case TOKEN_TYPES.BooleanLiteral:305 case TOKEN_TYPES.StringLiteral:306 case TOKEN_TYPES.CloseParen:307 case TOKEN_TYPES.CloseSquareBracket:308 break;309 default: {310 ++cursorPosition;311 const num = consumeWhile(isInteger);312 tokens.push(313 new Token(`${char}${num}`, num.length > 0 ? TOKEN_TYPES.NumericLiteral : TOKEN_TYPES.UnaryOperator)314 );315 continue;316 }317 }318 }319 for (const [char2, token] of ORDERED_MAPPING_TABLE) {320 const slice2 = src.slice(cursorPosition, cursorPosition + char2.length);321 if (slice2 === char2) {322 tokens.push(new Token(char2, token));323 cursorPosition += char2.length;324 continue main;325 }326 }327 if (char === "'" || char === '"') {328 ++cursorPosition;329 const str = consumeWhile((c) => c !== char);330 tokens.push(new Token(str, TOKEN_TYPES.StringLiteral));331 ++cursorPosition;332 continue;333 }334 if (isInteger(char)) {335 const num = consumeWhile(isInteger);336 tokens.push(new Token(num, TOKEN_TYPES.NumericLiteral));337 continue;338 }339 if (isWord(char)) {340 const word = consumeWhile(isWord);341 const type = Object.hasOwn(KEYWORDS, word) ? KEYWORDS[word] : TOKEN_TYPES.Identifier;342 if (type === TOKEN_TYPES.In && tokens.at(-1)?.type === TOKEN_TYPES.Not) {343 tokens.pop();344 tokens.push(new Token("not in", TOKEN_TYPES.NotIn));345 } else {346 tokens.push(new Token(word, type));347 }348 continue;349 }350 throw new SyntaxError(`Unexpected character: ${char}`);351 }352 return tokens;353}354 355// src/ast.ts356var Statement = class {357 type = "Statement";358};359var Program = class extends Statement {360 constructor(body) {361 super();362 this.body = body;363 }364 type = "Program";365};366var If = class extends Statement {367 constructor(test, body, alternate) {368 super();369 this.test = test;370 this.body = body;371 this.alternate = alternate;372 }373 type = "If";374};375var For = class extends Statement {376 constructor(loopvar, iterable, body) {377 super();378 this.loopvar = loopvar;379 this.iterable = iterable;380 this.body = body;381 }382 type = "For";383};384var SetStatement = class extends Statement {385 constructor(assignee, value) {386 super();387 this.assignee = assignee;388 this.value = value;389 }390 type = "Set";391};392var Expression = class extends Statement {393 type = "Expression";394};395var MemberExpression = class extends Expression {396 constructor(object, property, computed) {397 super();398 this.object = object;399 this.property = property;400 this.computed = computed;401 }402 type = "MemberExpression";403};404var CallExpression = class extends Expression {405 constructor(callee, args) {406 super();407 this.callee = callee;408 this.args = args;409 }410 type = "CallExpression";411};412var Identifier = class extends Expression {413 /**414 * @param {string} value The name of the identifier415 */416 constructor(value) {417 super();418 this.value = value;419 }420 type = "Identifier";421};422var Literal = class extends Expression {423 constructor(value) {424 super();425 this.value = value;426 }427 type = "Literal";428};429var NumericLiteral = class extends Literal {430 type = "NumericLiteral";431};432var StringLiteral = class extends Literal {433 type = "StringLiteral";434};435var BooleanLiteral = class extends Literal {436 type = "BooleanLiteral";437};438var ArrayLiteral = class extends Literal {439 type = "ArrayLiteral";440};441var TupleLiteral = class extends Literal {442 type = "TupleLiteral";443};444var ObjectLiteral = class extends Literal {445 type = "ObjectLiteral";446};447var BinaryExpression = class extends Expression {448 constructor(operator, left, right) {449 super();450 this.operator = operator;451 this.left = left;452 this.right = right;453 }454 type = "BinaryExpression";455};456var FilterExpression = class extends Expression {457 constructor(operand, filter) {458 super();459 this.operand = operand;460 this.filter = filter;461 }462 type = "FilterExpression";463};464var TestExpression = class extends Expression {465 constructor(operand, negate, test) {466 super();467 this.operand = operand;468 this.negate = negate;469 this.test = test;470 }471 type = "TestExpression";472};473var UnaryExpression = class extends Expression {474 constructor(operator, argument) {475 super();476 this.operator = operator;477 this.argument = argument;478 }479 type = "UnaryExpression";480};481var SliceExpression = class extends Expression {482 constructor(start = void 0, stop = void 0, step = void 0) {483 super();484 this.start = start;485 this.stop = stop;486 this.step = step;487 }488 type = "SliceExpression";489};490var KeywordArgumentExpression = class extends Expression {491 constructor(key, value) {492 super();493 this.key = key;494 this.value = value;495 }496 type = "KeywordArgumentExpression";497};498 499// src/parser.ts500function parse(tokens) {501 const program = new Program([]);502 let current = 0;503 function expect(type, error) {504 const prev = tokens[current++];505 if (!prev || prev.type !== type) {506 throw new Error(`Parser Error: ${error}. ${prev.type} !== ${type}.`);507 }508 return prev;509 }510 function parseAny() {511 switch (tokens[current].type) {512 case TOKEN_TYPES.Text:513 return parseText();514 case TOKEN_TYPES.OpenStatement:515 return parseJinjaStatement();516 case TOKEN_TYPES.OpenExpression:517 return parseJinjaExpression();518 default:519 throw new SyntaxError(`Unexpected token type: ${tokens[current].type}`);520 }521 }522 function not(...types) {523 return current + types.length <= tokens.length && types.some((type, i) => type !== tokens[current + i].type);524 }525 function is(...types) {526 return current + types.length <= tokens.length && types.every((type, i) => type === tokens[current + i].type);527 }528 function parseText() {529 return new StringLiteral(expect(TOKEN_TYPES.Text, "Expected text token").value);530 }531 function parseJinjaStatement() {532 expect(TOKEN_TYPES.OpenStatement, "Expected opening statement token");533 let result;534 switch (tokens[current].type) {535 case TOKEN_TYPES.Set:536 ++current;537 result = parseSetStatement();538 expect(TOKEN_TYPES.CloseStatement, "Expected closing statement token");539 break;540 case TOKEN_TYPES.If:541 ++current;542 result = parseIfStatement();543 expect(TOKEN_TYPES.OpenStatement, "Expected {% token");544 expect(TOKEN_TYPES.EndIf, "Expected endif token");545 expect(TOKEN_TYPES.CloseStatement, "Expected %} token");546 break;547 case TOKEN_TYPES.For:548 ++current;549 result = parseForStatement();550 expect(TOKEN_TYPES.OpenStatement, "Expected {% token");551 expect(TOKEN_TYPES.EndFor, "Expected endfor token");552 expect(TOKEN_TYPES.CloseStatement, "Expected %} token");553 break;554 default:555 throw new SyntaxError(`Unknown statement type: ${tokens[current].type}`);556 }557 return result;558 }559 function parseJinjaExpression() {560 expect(TOKEN_TYPES.OpenExpression, "Expected opening expression token");561 const result = parseExpression();562 expect(TOKEN_TYPES.CloseExpression, "Expected closing expression token");563 return result;564 }565 function parseSetStatement() {566 const left = parseExpression();567 if (is(TOKEN_TYPES.Equals)) {568 ++current;569 const value = parseSetStatement();570 return new SetStatement(left, value);571 }572 return left;573 }574 function parseIfStatement() {575 const test = parseExpression();576 expect(TOKEN_TYPES.CloseStatement, "Expected closing statement token");577 const body = [];578 const alternate = [];579 while (!(tokens[current]?.type === TOKEN_TYPES.OpenStatement && (tokens[current + 1]?.type === TOKEN_TYPES.ElseIf || tokens[current + 1]?.type === TOKEN_TYPES.Else || tokens[current + 1]?.type === TOKEN_TYPES.EndIf))) {580 body.push(parseAny());581 }582 if (tokens[current]?.type === TOKEN_TYPES.OpenStatement && tokens[current + 1]?.type !== TOKEN_TYPES.EndIf) {583 ++current;584 if (is(TOKEN_TYPES.ElseIf)) {585 expect(TOKEN_TYPES.ElseIf, "Expected elseif token");586 alternate.push(parseIfStatement());587 } else {588 expect(TOKEN_TYPES.Else, "Expected else token");589 expect(TOKEN_TYPES.CloseStatement, "Expected closing statement token");590 while (!(tokens[current]?.type === TOKEN_TYPES.OpenStatement && tokens[current + 1]?.type === TOKEN_TYPES.EndIf)) {591 alternate.push(parseAny());592 }593 }594 }595 return new If(test, body, alternate);596 }597 function parseExpressionSequence(primary = false) {598 const fn = primary ? parsePrimaryExpression : parseExpression;599 const expressions = [fn()];600 const isTuple = is(TOKEN_TYPES.Comma);601 while (isTuple) {602 ++current;603 expressions.push(fn());604 if (!is(TOKEN_TYPES.Comma)) {605 break;606 }607 }608 return isTuple ? new TupleLiteral(expressions) : expressions[0];609 }610 function parseForStatement() {611 const loopVariable = parseExpressionSequence(true);612 if (!(loopVariable instanceof Identifier || loopVariable instanceof TupleLiteral)) {613 throw new SyntaxError(`Expected identifier/tuple for the loop variable, got ${loopVariable.type} instead`);614 }615 expect(TOKEN_TYPES.In, "Expected `in` keyword following loop variable");616 const iterable = parseExpression();617 expect(TOKEN_TYPES.CloseStatement, "Expected closing statement token");618 const body = [];619 while (not(TOKEN_TYPES.OpenStatement, TOKEN_TYPES.EndFor)) {620 body.push(parseAny());621 }622 return new For(loopVariable, iterable, body);623 }624 function parseExpression() {625 return parseTernaryExpression();626 }627 function parseTernaryExpression() {628 const a = parseLogicalOrExpression();629 if (is(TOKEN_TYPES.If)) {630 ++current;631 const predicate = parseLogicalOrExpression();632 expect(TOKEN_TYPES.Else, "Expected else token");633 const b = parseLogicalOrExpression();634 return new If(predicate, [a], [b]);635 }636 return a;637 }638 function parseLogicalOrExpression() {639 let left = parseLogicalAndExpression();640 while (is(TOKEN_TYPES.Or)) {641 const operator = tokens[current];642 ++current;643 const right = parseLogicalAndExpression();644 left = new BinaryExpression(operator, left, right);645 }646 return left;647 }648 function parseLogicalAndExpression() {649 let left = parseLogicalNegationExpression();650 while (is(TOKEN_TYPES.And)) {651 const operator = tokens[current];652 ++current;653 const right = parseLogicalNegationExpression();654 left = new BinaryExpression(operator, left, right);655 }656 return left;657 }658 function parseLogicalNegationExpression() {659 let right;660 while (is(TOKEN_TYPES.Not)) {661 const operator = tokens[current];662 ++current;663 const arg = parseLogicalNegationExpression();664 right = new UnaryExpression(operator, arg);665 }666 return right ?? parseComparisonExpression();667 }668 function parseComparisonExpression() {669 let left = parseAdditiveExpression();670 while (is(TOKEN_TYPES.ComparisonBinaryOperator) || is(TOKEN_TYPES.In) || is(TOKEN_TYPES.NotIn)) {671 const operator = tokens[current];672 ++current;673 const right = parseAdditiveExpression();674 left = new BinaryExpression(operator, left, right);675 }676 return left;677 }678 function parseAdditiveExpression() {679 let left = parseMultiplicativeExpression();680 while (is(TOKEN_TYPES.AdditiveBinaryOperator)) {681 const operator = tokens[current];682 ++current;683 const right = parseMultiplicativeExpression();684 left = new BinaryExpression(operator, left, right);685 }686 return left;687 }688 function parseCallMemberExpression() {689 const member = parseMemberExpression();690 if (is(TOKEN_TYPES.OpenParen)) {691 return parseCallExpression(member);692 }693 return member;694 }695 function parseCallExpression(callee) {696 let callExpression = new CallExpression(callee, parseArgs());697 if (is(TOKEN_TYPES.OpenParen)) {698 callExpression = parseCallExpression(callExpression);699 }700 return callExpression;701 }702 function parseArgs() {703 expect(TOKEN_TYPES.OpenParen, "Expected opening parenthesis for arguments list");704 const args = parseArgumentsList();705 expect(TOKEN_TYPES.CloseParen, "Expected closing parenthesis for arguments list");706 return args;707 }708 function parseArgumentsList() {709 const args = [];710 while (!is(TOKEN_TYPES.CloseParen)) {711 let argument = parseExpression();712 if (is(TOKEN_TYPES.Equals)) {713 ++current;714 if (!(argument instanceof Identifier)) {715 throw new SyntaxError(`Expected identifier for keyword argument`);716 }717 const value = parseExpression();718 argument = new KeywordArgumentExpression(argument, value);719 }720 args.push(argument);721 if (is(TOKEN_TYPES.Comma)) {722 ++current;723 }724 }725 return args;726 }727 function parseMemberExpressionArgumentsList() {728 const slices = [];729 let isSlice = false;730 while (!is(TOKEN_TYPES.CloseSquareBracket)) {731 if (is(TOKEN_TYPES.Colon)) {732 slices.push(void 0);733 ++current;734 isSlice = true;735 } else {736 slices.push(parseExpression());737 if (is(TOKEN_TYPES.Colon)) {738 ++current;739 isSlice = true;740 }741 }742 }743 if (slices.length === 0) {744 throw new SyntaxError(`Expected at least one argument for member/slice expression`);745 }746 if (isSlice) {747 if (slices.length > 3) {748 throw new SyntaxError(`Expected 0-3 arguments for slice expression`);749 }750 return new SliceExpression(...slices);751 }752 return slices[0];753 }754 function parseMemberExpression() {755 let object = parsePrimaryExpression();756 while (is(TOKEN_TYPES.Dot) || is(TOKEN_TYPES.OpenSquareBracket)) {757 const operator = tokens[current];758 ++current;759 let property;760 const computed = operator.type !== TOKEN_TYPES.Dot;761 if (computed) {762 property = parseMemberExpressionArgumentsList();763 expect(TOKEN_TYPES.CloseSquareBracket, "Expected closing square bracket");764 } else {765 property = parsePrimaryExpression();766 if (property.type !== "Identifier") {767 throw new SyntaxError(`Expected identifier following dot operator`);768 }769 }770 object = new MemberExpression(object, property, computed);771 }772 return object;773 }774 function parseMultiplicativeExpression() {775 let left = parseTestExpression();776 while (is(TOKEN_TYPES.MultiplicativeBinaryOperator)) {777 const operator = tokens[current];778 ++current;779 const right = parseTestExpression();780 left = new BinaryExpression(operator, left, right);781 }782 return left;783 }784 function parseTestExpression() {785 let operand = parseFilterExpression();786 while (is(TOKEN_TYPES.Is)) {787 ++current;788 const negate = is(TOKEN_TYPES.Not);789 if (negate) {790 ++current;791 }792 let filter = parsePrimaryExpression();793 if (filter instanceof BooleanLiteral) {794 filter = new Identifier(filter.value.toString());795 }796 if (!(filter instanceof Identifier)) {797 throw new SyntaxError(`Expected identifier for the test`);798 }799 operand = new TestExpression(operand, negate, filter);800 }801 return operand;802 }803 function parseFilterExpression() {804 let operand = parseCallMemberExpression();805 while (is(TOKEN_TYPES.Pipe)) {806 ++current;807 let filter = parsePrimaryExpression();808 if (!(filter instanceof Identifier)) {809 throw new SyntaxError(`Expected identifier for the filter`);810 }811 if (is(TOKEN_TYPES.OpenParen)) {812 filter = parseCallExpression(filter);813 }814 operand = new FilterExpression(operand, filter);815 }816 return operand;817 }818 function parsePrimaryExpression() {819 const token = tokens[current];820 switch (token.type) {821 case TOKEN_TYPES.NumericLiteral:822 ++current;823 return new NumericLiteral(Number(token.value));824 case TOKEN_TYPES.StringLiteral:825 ++current;826 return new StringLiteral(token.value);827 case TOKEN_TYPES.BooleanLiteral:828 ++current;829 return new BooleanLiteral(token.value === "true");830 case TOKEN_TYPES.Identifier:831 ++current;832 return new Identifier(token.value);833 case TOKEN_TYPES.OpenParen: {834 ++current;835 const expression = parseExpressionSequence();836 if (tokens[current].type !== TOKEN_TYPES.CloseParen) {837 throw new SyntaxError(`Expected closing parenthesis, got ${tokens[current].type} instead`);838 }839 ++current;840 return expression;841 }842 case TOKEN_TYPES.OpenSquareBracket: {843 ++current;844 const values = [];845 while (!is(TOKEN_TYPES.CloseSquareBracket)) {846 values.push(parseExpression());847 if (is(TOKEN_TYPES.Comma)) {848 ++current;849 }850 }851 ++current;852 return new ArrayLiteral(values);853 }854 case TOKEN_TYPES.OpenCurlyBracket: {855 ++current;856 const values = /* @__PURE__ */ new Map();857 while (!is(TOKEN_TYPES.CloseCurlyBracket)) {858 const key = parseExpression();859 expect(TOKEN_TYPES.Colon, "Expected colon between key and value in object literal");860 const value = parseExpression();861 values.set(key, value);862 if (is(TOKEN_TYPES.Comma)) {863 ++current;864 }865 }866 ++current;867 return new ObjectLiteral(values);868 }869 default:870 throw new SyntaxError(`Unexpected token: ${token.type}`);871 }872 }873 while (current < tokens.length) {874 program.body.push(parseAny());875 }876 return program;877}878 879// src/utils.ts880function range(start, stop, step = 1) {881 if (stop === void 0) {882 stop = start;883 start = 0;884 }885 const result = [];886 for (let i = start; i < stop; i += step) {887 result.push(i);888 }889 return result;890}891function slice(array, start, stop, step = 1) {892 const direction = Math.sign(step);893 if (direction >= 0) {894 start = (start ??= 0) < 0 ? Math.max(array.length + start, 0) : Math.min(start, array.length);895 stop = (stop ??= array.length) < 0 ? Math.max(array.length + stop, 0) : Math.min(stop, array.length);896 } else {897 start = (start ??= array.length - 1) < 0 ? Math.max(array.length + start, -1) : Math.min(start, array.length - 1);898 stop = (stop ??= -1) < -1 ? Math.max(array.length + stop, -1) : Math.min(stop, array.length - 1);899 }900 const result = [];901 for (let i = start; direction * i < direction * stop; i += step) {902 result.push(array[i]);903 }904 return result;905}906function titleCase(value) {907 return value.replace(/\b\w/g, (c) => c.toUpperCase());908}909 910// src/runtime.ts911var RuntimeValue = class {912 type = "RuntimeValue";913 value;914 /**915 * A collection of built-in functions for this type.916 */917 builtins = /* @__PURE__ */ new Map();918 /**919 * Creates a new RuntimeValue.920 */921 constructor(value = void 0) {922 this.value = value;923 }924 /**925 * Determines truthiness or falsiness of the runtime value.926 * This function should be overridden by subclasses if it has custom truthiness criteria.927 * @returns {BooleanValue} BooleanValue(true) if the value is truthy, BooleanValue(false) otherwise.928 */929 __bool__() {930 return new BooleanValue(!!this.value);931 }932};933var NumericValue = class extends RuntimeValue {934 type = "NumericValue";935};936var StringValue = class extends RuntimeValue {937 type = "StringValue";938 builtins = /* @__PURE__ */ new Map([939 [940 "upper",941 new FunctionValue(() => {942 return new StringValue(this.value.toUpperCase());943 })944 ],945 [946 "lower",947 new FunctionValue(() => {948 return new StringValue(this.value.toLowerCase());949 })950 ],951 [952 "strip",953 new FunctionValue(() => {954 return new StringValue(this.value.trim());955 })956 ],957 [958 "title",959 new FunctionValue(() => {960 return new StringValue(titleCase(this.value));961 })962 ],963 ["length", new NumericValue(this.value.length)]964 ]);965};966var BooleanValue = class extends RuntimeValue {967 type = "BooleanValue";968};969var ObjectValue = class extends RuntimeValue {970 type = "ObjectValue";971 /**972 * NOTE: necessary to override since all JavaScript arrays are considered truthy,973 * while only non-empty Python arrays are consider truthy.974 *975 * e.g.,976 * - JavaScript: {} && 5 -> 5977 * - Python: {} and 5 -> {}978 */979 __bool__() {980 return new BooleanValue(this.value.size > 0);981 }982 builtins = /* @__PURE__ */ new Map([983 [984 "get",985 new FunctionValue(([key, defaultValue]) => {986 if (!(key instanceof StringValue)) {987 throw new Error(`Object key must be a string: got ${key.type}`);988 }989 return this.value.get(key.value) ?? defaultValue ?? new NullValue();990 })991 ],992 [993 "items",994 new FunctionValue(() => {995 return new ArrayValue(996 Array.from(this.value.entries()).map(([key, value]) => new ArrayValue([new StringValue(key), value]))997 );998 })999 ]1000 ]);1001};1002var ArrayValue = class extends RuntimeValue {1003 type = "ArrayValue";1004 builtins = /* @__PURE__ */ new Map([["length", new NumericValue(this.value.length)]]);1005 /**1006 * NOTE: necessary to override since all JavaScript arrays are considered truthy,1007 * while only non-empty Python arrays are consider truthy.1008 *1009 * e.g.,1010 * - JavaScript: [] && 5 -> 51011 * - Python: [] and 5 -> []1012 */1013 __bool__() {1014 return new BooleanValue(this.value.length > 0);1015 }1016};1017var TupleValue = class extends ArrayValue {1018 type = "TupleValue";1019};1020var FunctionValue = class extends RuntimeValue {1021 type = "FunctionValue";1022};1023var NullValue = class extends RuntimeValue {1024 type = "NullValue";1025};1026var UndefinedValue = class extends RuntimeValue {1027 type = "UndefinedValue";1028};1029var Environment = class {1030 constructor(parent) {1031 this.parent = parent;1032 }1033 /**1034 * The variables declared in this environment.1035 */1036 variables = /* @__PURE__ */ new Map([1037 [1038 "namespace",1039 new FunctionValue((args) => {1040 if (args.length === 0) {1041 return new ObjectValue(/* @__PURE__ */ new Map());1042 }1043 if (args.length !== 1 || !(args[0] instanceof ObjectValue)) {1044 throw new Error("`namespace` expects either zero arguments or a single object argument");1045 }1046 return args[0];1047 })1048 ]1049 ]);1050 /**1051 * The tests available in this environment.1052 */1053 tests = /* @__PURE__ */ new Map([1054 ["boolean", (operand) => operand.type === "BooleanValue"],1055 ["callable", (operand) => operand instanceof FunctionValue],1056 [1057 "odd",1058 (operand) => {1059 if (operand.type !== "NumericValue") {1060 throw new Error(`Cannot apply test "odd" to type: ${operand.type}`);1061 }1062 return operand.value % 2 !== 0;1063 }1064 ],1065 [1066 "even",1067 (operand) => {1068 if (operand.type !== "NumericValue") {1069 throw new Error(`Cannot apply test "even" to type: ${operand.type}`);1070 }1071 return operand.value % 2 === 0;1072 }1073 ],1074 ["false", (operand) => operand.type === "BooleanValue" && !operand.value],1075 ["true", (operand) => operand.type === "BooleanValue" && operand.value],1076 ["number", (operand) => operand.type === "NumericValue"],1077 ["integer", (operand) => operand.type === "NumericValue" && Number.isInteger(operand.value)],1078 ["iterable", (operand) => operand instanceof ArrayValue || operand instanceof StringValue],1079 [1080 "lower",1081 (operand) => {1082 const str = operand.value;1083 return operand.type === "StringValue" && str === str.toLowerCase();1084 }1085 ],1086 [1087 "upper",1088 (operand) => {1089 const str = operand.value;1090 return operand.type === "StringValue" && str === str.toUpperCase();1091 }1092 ],1093 ["none", (operand) => operand.type === "NullValue"],1094 ["defined", (operand) => operand.type !== "UndefinedValue"],1095 ["undefined", (operand) => operand.type === "UndefinedValue"],1096 ["equalto", (a, b) => a.value === b.value]1097 ]);1098 /**1099 * Set the value of a variable in the current environment.1100 */1101 set(name, value) {1102 return this.declareVariable(name, convertToRuntimeValues(value));1103 }1104 declareVariable(name, value) {1105 if (this.variables.has(name)) {1106 throw new SyntaxError(`Variable already declared: ${name}`);1107 }1108 this.variables.set(name, value);1109 return value;1110 }1111 // private assignVariable(name: string, value: AnyRuntimeValue): AnyRuntimeValue {1112 // const env = this.resolve(name);1113 // env.variables.set(name, value);1114 // return value;1115 // }1116 /**1117 * Set variable in the current scope.1118 * See https://jinja.palletsprojects.com/en/3.0.x/templates/#assignments for more information.1119 */1120 setVariable(name, value) {1121 this.variables.set(name, value);1122 return value;1123 }1124 /**1125 * Resolve the environment in which the variable is declared.1126 * @param {string} name The name of the variable.1127 * @returns {Environment} The environment in which the variable is declared.1128 */1129 resolve(name) {1130 if (this.variables.has(name)) {1131 return this;1132 }1133 if (this.parent) {1134 return this.parent.resolve(name);1135 }1136 throw new Error(`Unknown variable: ${name}`);1137 }1138 lookupVariable(name) {1139 try {1140 return this.resolve(name).variables.get(name) ?? new UndefinedValue();1141 } catch {1142 return new UndefinedValue();1143 }1144 }1145};1146var Interpreter = class {1147 global;1148 constructor(env) {1149 this.global = env ?? new Environment();1150 }1151 /**1152 * Run the program.1153 */1154 run(program) {1155 return this.evaluate(program, this.global);1156 }1157 /**1158 * Evaluates expressions following the binary operation type.1159 */1160 evaluateBinaryExpression(node, environment) {1161 const left = this.evaluate(node.left, environment);1162 switch (node.operator.value) {1163 case "and":1164 return left.__bool__().value ? this.evaluate(node.right, environment) : left;1165 case "or":1166 return left.__bool__().value ? left : this.evaluate(node.right, environment);1167 }1168 const right = this.evaluate(node.right, environment);1169 switch (node.operator.value) {1170 case "==":1171 return new BooleanValue(left.value == right.value);1172 case "!=":1173 return new BooleanValue(left.value != right.value);1174 }1175 if (left instanceof UndefinedValue || right instanceof UndefinedValue) {1176 throw new Error("Cannot perform operation on undefined values");1177 } else if (left instanceof NullValue || right instanceof NullValue) {1178 throw new Error("Cannot perform operation on null values");1179 } else if (left instanceof NumericValue && right instanceof NumericValue) {1180 switch (node.operator.value) {1181 case "+":1182 return new NumericValue(left.value + right.value);1183 case "-":1184 return new NumericValue(left.value - right.value);1185 case "*":1186 return new NumericValue(left.value * right.value);1187 case "/":1188 return new NumericValue(left.value / right.value);1189 case "%":1190 return new NumericValue(left.value % right.value);1191 case "<":1192 return new BooleanValue(left.value < right.value);1193 case ">":1194 return new BooleanValue(left.value > right.value);1195 case ">=":1196 return new BooleanValue(left.value >= right.value);1197 case "<=":1198 return new BooleanValue(left.value <= right.value);1199 }1200 } else if (left instanceof ArrayValue && right instanceof ArrayValue) {