UNPKG

luma-lang

Version:

The Embeddable Luma Language Compiler and Runtime

23 lines (22 loc) 87.8 kB
var z=Object.defineProperty;var X=(u,t,e)=>t in u?z(u,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):u[t]=e;var c=(u,t,e)=>X(u,typeof t!="symbol"?t+"":t,e);var E=class extends Error{constructor(e){super(e.message,{cause:e.cause});c(this,"moduleName");c(this,"position");this.moduleName=e.moduleName,this.position=e.position}};var $=["fn","on","if","else","do","while","for","in","break","continue","return","true","false","null","not","this","and","or","local","public","import","wait","new","class","extends","parent"];var M={ASSIGN:"=",PLUS:"+",MINUS:"-",MULTIPLY:"*",DIVIDE:"/",MODULO:"%",EXPONENTIATION:"^",EQUALS:"==",NOT_EQUALS:"!=",GREATER_THAN:">",LESS_THAN:"<",GREATER_EQUAL:">=",LESS_EQUAL:"<=",NOT:"!",RANGE:"..",IS:"is"};var y={MEMBER_ACCESS:".",COMMA:",",COLON:":",QUESTION_MARK:"?",OPEN_PAREN:"(",CLOSE_PAREN:")",OPEN_BRACKET:"[",CLOSE_BRACKET:"]",OPEN_BRACE:"{",CLOSE_BRACE:"}",BANG:"!"};var x=class{constructor(t){c(this,"_tokens");c(this,"_index",0);this._tokens=t}get tokens(){return[...this._tokens]}get length(){return this._tokens.length}peek(t=0){let e=this._index+t;return e<0||e>=this._tokens.length?null:this._tokens[e]}consume(){let t=this.peek(0);if(!t)throw new Error("Unexpected End of File");return this._index++,t}get isEof(){return this._index>=this._tokens.length}};var o={IDENTIFIER:"IDENTIFIER",KEYWORD:"KEYWORD",OPERATOR:"OPERATOR",PUNCTUATION:"PUNCTUATION",STRING:"STRING",NUMBER:"NUMBER",COMMENT:"COMMENT",BLOCK_COMMENT:"BLOCK_COMMENT",NEWLINE:"NEWLINE",INDENT:"INDENT",DEDENT:"DEDENT",EOF:"EOF"};var _=class _{constructor(t,e){c(this,"_tokens",[]);c(this,"_source");c(this,"_moduleName");c(this,"index",0);c(this,"line",1);c(this,"col",1);c(this,"indentStack",[0]);c(this,"isAtStartOfLine",!0);this._source=t.replace(/\r\n/g,` `),this._moduleName=e}static tokenize(t,e=void 0){return t.endsWith(` `)||(t+=` `),new _(t,e).tokenize()}tokenize(){for(;!this.isEof;){if(this.isAtStartOfLine&&this.handleIndentation())continue;let t=this._source[this.index];if(t===` `){this.handleNewline();continue}if(t===" "||t===" "){this.advance(1);continue}this.parseComment()||this.parseBlockComment()||this.parseSymbol()||this.parseNumberLiteral()||this.parseStringLiteral()||this.parseWord()||this.throwUnexpectedCharacterError()}for(;this.indentStack.length>1;)this.indentStack.pop(),this._tokens.push(this.createToken(o.DEDENT,""));return new x(this._tokens)}handleNewline(){let t=this._tokens[this._tokens.length-1];t&&t.type!==o.NEWLINE&&t.type!==o.INDENT&&t.type!==o.DEDENT&&this._tokens.push(this.createToken(o.NEWLINE,"\\n")),this.index++,this.line++,this.col=1,this.isAtStartOfLine=!0}handleIndentation(){let t=0,e=this.index;for(;e<this._source.length&&(this._source[e]===" "||this._source[e]===" ");)t+=this._source[e]===" "?4:1,e++;let s=this._source[e];if(e>=this._source.length||s===` `||this._source.startsWith("//",e)||this._source.startsWith("/*",e))return this.isAtStartOfLine=!1,!1;this.advance(e-this.index);let r=this.indentStack[this.indentStack.length-1];if(t>r)this.indentStack.push(t),this._tokens.push(this.createToken(o.INDENT,t.toString()));else if(t<r){for(;t<this.indentStack[this.indentStack.length-1];)this.indentStack.pop(),this._tokens.push(this.createToken(o.DEDENT,""));t!==this.indentStack[this.indentStack.length-1]&&this.throwError("Indentation error: Indent level does not match any outer block")}return this.isAtStartOfLine=!1,!1}parseWord(){let t=this.index;if(!/[a-zA-Z_]/.test(this._source[t]))return!1;for(;t<this._source.length&&/[a-zA-Z0-9_]/.test(this._source[t]);)t++;let e=this._source.slice(this.index,t),s=_.KEYWORD_SET.has(e)?o.KEYWORD:o.IDENTIFIER;return this._tokens.push(this.createToken(s,e)),this.advance(e.length),!0}parseSymbol(){for(let t of _.SORTED_SYMBOLS)if(this._source.startsWith(t,this.index)){let e=_.PUNCTUATION_SET.has(t)?o.PUNCTUATION:o.OPERATOR;return this._tokens.push(this.createToken(e,t)),this.advance(t.length),!0}return!1}parseNumberLiteral(){let t=this._source[this.index],e=this._source[this.index+1],s=t>="0"&&t<="9",r=t==="."&&e>="0"&&e<="9";if(!s&&!r)return!1;let i=this.index,n=!1;for(;i<this._source.length;){let p=this._source[i],l=this._source[i+1];if(p>="0"&&p<="9"){i++;continue}if(p==="_"){i++;continue}if(p==="."){if(l==="."||n)break;n=!0,i++;continue}if(p==="e"||p==="E"){i++,(this._source[i]==="+"||this._source[i]==="-")&&i++;continue}break}let h=this._source.substring(this.index,i);return this._tokens.push(this.createToken(o.NUMBER,h)),this.advance(i-this.index),!0}parseStringLiteral(){let t=this._source[this.index];if(t!=='"'&&t!=="'")return!1;let e=this.line,s=this.col;this.advance(1);let r="",i=0,n=!1,h=!1,p=!1;for(;!this.isEof;){let f=this._source[this.index];if(f==="\\"){if(r+=f,this.advance(1),!this.isEof){let d=this._source[this.index];r+=d,this.advance(1)}continue}if(f==="{"?(i++,n=!0):f==="}"&&i>0&&i--,f===t){if(this.advance(1),n&&i===0&&(h=!0),n&&i>0){r+=f;continue}break}f===` `&&(p=!0,this.line++,this.col=1),r+=f,this.advance(1)}if(this.isEof&&this._source[this.index-1]!==t&&this.throwError("Unterminated string literal"),p&&(r=this.stripIndentation(r)),i!==0)throw new Error(`Unterminated interpolation expression in string literal at line ${e}, column ${s}`);if(!h)return this._tokens.push({type:o.STRING,value:this.unescapeString(r),position:{lineStart:e,columnStart:s,lineEnd:this.line,columnEnd:this.col}}),!0;let l=this.parseInterpolationSegments(r),m=!1;for(let f of l){if(m&&this._tokens.push({type:o.OPERATOR,value:M.PLUS,position:this.currentPos()}),f.type==="text"){let d=this.unescapeString(f.value);m=!0,this._tokens.push({type:o.STRING,value:d,position:{lineStart:e,columnStart:s,lineEnd:this.line,columnEnd:this.col}});continue}if(f.type==="expr"){m=!0;let d=this.tokenizeExpression(f.value);d.length===0&&this.throwError("Empty expression in string interpolation"),this._tokens.push({type:o.PUNCTUATION,value:"(",position:{...this.currentPos()}});for(let b of d)this._tokens.push(b);this._tokens.push({type:o.PUNCTUATION,value:")",position:{...this.currentPos()}})}}return!0}parseInterpolationSegments(t){let e=[],s="",r=0,i=!1;for(;r<t.length;){let n=t[r];if(n==="\\"){s+=n,r++,r<t.length&&(s+=t[r],r++);continue}if(n==="{"){let h=this.extractBalancedExpression(t,r+1);if(h!==null){i=i||s.trim().length>0,e.push({type:"text",value:s}),s="",e.push({type:"expr",value:h.code}),r=h.endIndex+1;continue}}s+=n,i=i||s.trim().length>0,r++}return e.push({type:"text",value:s}),i&&this.stripInterpolatedIndentation(e),e}extractBalancedExpression(t,e){for(let s=e,r=1;s<t.length;s++){let i=t[s];if(i==="\\"){s++;continue}if(i==="{")r++;else if(i==="}"&&(r--,r===0))return{code:t.slice(e,s),endIndex:s}}return null}unescapeString(t){let e="",s=0;for(;s<t.length;)if(t[s]==="\\"&&s+1<t.length){let r=t[s+1];switch(r){case"n":e+=` `;break;case"t":e+=" ";break;case"r":e+="\r";break;case'"':e+='"';break;case"'":e+="'";break;case"\\":e+="\\";break;case"{":e+="{";break;case"}":e+="}";break;default:e+="\\"+r}s+=2}else e+=t[s],s++;return e}currentPos(){return{lineStart:this.line,columnStart:this.col,lineEnd:this.line,columnEnd:this.col+1}}stripInterpolatedIndentation(t){let e=1/0;for(let r of t){if(r.type!=="text")continue;let i=r.value.split(` `);for(let n=1;n<i.length;n++){let h=i[n];if(h.trim().length===0)continue;let p=0;for(;p<h.length&&(h[p]===" "||h[p]===" ");)p++;p<e&&(e=p)}}e===1/0&&(e=0);for(let r of t){if(r.type!=="text")continue;let i=r.value.split(` `);for(let n=1;n<i.length;n++)i[n].length>=e&&(i[n]=i[n].slice(e));r.value=i.join(` `)}t[0].type==="text"&&t[0].value.startsWith(` `)&&(t[0].value=t[0].value.slice(1));let s=t[t.length-1];if(s.type==="text"){let r=s.value.split(` `);r.length>0&&r[r.length-1].trim()===""&&(r.pop(),s.value=r.join(` `))}}stripIndentation(t){let e=t.split(` `);e.length>0&&e[0].trim()===""&&e.shift(),e.length>0&&e[e.length-1].trim()===""&&e.pop();let s=1/0;for(let r of e){if(r.trim().length===0)continue;let i=0;for(;i<r.length&&(r[i]===" "||r[i]===" ");)i++;i<s&&(s=i)}return s===1/0&&(s=0),e.map(r=>r.length<s?r.trim():r.slice(s)).join(` `)}parseComment(){if(!this._source.startsWith("//",this.index))return!1;for(;!this.isEof&&this._source[this.index]!==` `;)this.advance(1);return!0}parseBlockComment(){if(!this._source.startsWith("/*",this.index))return!1;for(this.advance(2);!this.isEof&&!this._source.startsWith("*/",this.index);)this._source[this.index]===` `?(this.line++,this.col=1,this.index++):this.advance(1);return this.isEof||this.advance(2),!0}createToken(t,e){return{type:t,value:e,position:{lineStart:this.line,columnStart:this.col,lineEnd:this.line,columnEnd:this.col+e.length}}}advance(t){this.index+=t,this.col+=t}get isEof(){return this.index>=this._source.length}throwError(t){throw new E({message:`${t} at line ${this.line}, column ${this.col}`,moduleName:this._moduleName,position:{lineStart:this.line,columnStart:this.col,lineEnd:this.line,columnEnd:this.col+1}})}throwUnexpectedCharacterError(){this.throwError(`Unexpected character "${this._source[this.index]}"`)}tokenizeExpression(t){return _.tokenize(t.trim()).tokens.filter(s=>s.type!==o.NEWLINE&&s.type!==o.INDENT&&s.type!==o.DEDENT)}};c(_,"KEYWORD_SET",new Set($)),c(_,"PUNCTUATION_SET",new Set(Object.values(y))),c(_,"SYMBOL_MAP",new Map([...Object.entries(M).map(([t,e])=>[e,t]),...Object.entries(y).map(([t,e])=>[e,t])])),c(_,"SORTED_SYMBOLS",Array.from(_.SYMBOL_MAP.keys()).sort((t,e)=>e.length-t.length));var N=_;var k=class u{constructor(t,e){c(this,"stream");c(this,"moduleName");c(this,"lastToken");this.stream=t,this.moduleName=e}static parse(t,e=void 0){return new u(t,e).parse()}parse(){try{let t=[];for(;!this.stream.isEof;)this.match(o.NEWLINE)||t.push(this.parseStatement());return{type:"Script",body:t,position:{lineStart:1,lineEnd:1,columnStart:1,columnEnd:1}}}catch(t){throw t instanceof Error?new E({message:t.message,moduleName:this.moduleName,position:this.lastToken?.position??{lineStart:1,lineEnd:1,columnStart:1,columnEnd:1},cause:t}):(console.warn("Parser did not throw an instance of Error!",t),t)}}parseStatement(){let t=this.stream.peek();if(!t)throw new Error("Unexpected EOF");let e=!1,s=!1;if(this.match(o.KEYWORD,"public")&&(e=!0),this.match(o.KEYWORD,"local")&&(s=!0),this.check(o.KEYWORD,"fn")){if(s)throw new Error("Functions cannot be declared as 'local'. They are local by default unless marked 'public'.");return this.parseFunctionDeclaration(e)}if(this.check(o.KEYWORD,"class")){if(s)throw new Error("Classes cannot be declared as 'local'. They are local by default unless marked 'public'.");return this.parseClassStatement(e)}if(e||s)return this.parseExpressionStatement(e,s);if(t.type===o.KEYWORD)switch(t.value){case"import":return this.parseImportStatement();case"wait":return this.parseWaitStatement();case"on":return this.parseEventHook();case"return":return this.parseReturnStatement();case"if":return this.parseIfStatement();case"for":return this.parseForStatement();case"while":return this.parseWhileStatement();case"do":return this.parseDoWhileStatement();case"break":return this.parseBreakStatement();case"continue":return this.parseContinueStatement()}return this.parseExpressionStatement()}parseEventHook(){let t=this.currentPos();this.consume(o.KEYWORD,"on");let e=this.parseIdentifier(),s=[];if(this.match(o.PUNCTUATION,"(")){if(!this.check(o.PUNCTUATION,")"))do s.push(this.parseIdentifier());while(this.match(o.PUNCTUATION,","));this.consume(o.PUNCTUATION,")")}this.consume(o.PUNCTUATION,":");let r=this.parseBlock();return{type:"EventHook",name:e,params:s,body:r,position:t}}parseClassStatement(t=!1){let e=this.currentPos();this.consume(o.KEYWORD,"class");let s=this.parseIdentifier(),r=[];if(this.match(o.PUNCTUATION,"(")){if(!this.check(o.PUNCTUATION,")"))do if(this.match(o.KEYWORD,"this")){this.consume(o.PUNCTUATION,".");let l=this.parseIdentifier();r.push({type:"PromotedParameter",value:l.value,position:l.position})}else r.push(this.parseIdentifier());while(this.match(o.PUNCTUATION,","));this.consume(o.PUNCTUATION,")")}let i,n=[];if(this.match(o.KEYWORD,"extends")){let l=this.parsePrimary();for(;this.match(o.PUNCTUATION,".");){let m=this.parseIdentifier();l={type:"MemberExpression",object:l,property:m,computed:!1,position:l.position}}if(i=l,this.match(o.PUNCTUATION,"(")){if(!this.check(o.PUNCTUATION,")"))do n.push(this.parseExpression());while(this.match(o.PUNCTUATION,","));this.consume(o.PUNCTUATION,")")}}if(!this.check(o.PUNCTUATION,":"))return{type:"ClassStatement",name:s,properties:[],params:r,methods:[],position:e,isPublic:t,parent:i,parentArgs:n};this.consume(o.PUNCTUATION,":"),this.consume(o.NEWLINE),this.consume(o.INDENT);let h=[],p=[];for(;!this.match(o.DEDENT)&&!this.stream.isEof;)if(!this.match(o.NEWLINE)){if(this.check(o.KEYWORD,"fn")){let l=this.parseFunctionDeclaration(!1);if(l.type!=="FunctionDeclaration")throw new Error("Methods inside classes cannot be defined as method definitions.");p.push(l);continue}if(this.check(o.IDENTIFIER)){let l=this.parseIdentifier();if(this.match(o.PUNCTUATION,":")||this.match(o.OPERATOR,"=")){let m=this.parseExpression();h.push({key:l,value:m}),this.check(o.NEWLINE)&&this.consume(o.NEWLINE);continue}else throw new Error("Expected ':' for property definition.")}throw new Error("Expected 'fn' or property definition inside class body")}return{type:"ClassStatement",name:s,properties:h,params:r,methods:p,position:e,isPublic:t,parent:i,parentArgs:n}}parseFunctionDeclaration(t=!1){let e=this.currentPos();this.consume(o.KEYWORD,"fn");let s=this.parseIdentifier(),r=null;this.match(o.PUNCTUATION,y.MEMBER_ACCESS)&&(r=this.consume(o.IDENTIFIER).value);let i=[];if(this.match(o.PUNCTUATION,"(")){if(!this.check(o.PUNCTUATION,")"))do i.push(this.parseIdentifier());while(this.match(o.PUNCTUATION,","));this.consume(o.PUNCTUATION,")")}this.consume(o.PUNCTUATION,":");let n=this.parseBlock();if(r&&t)throw new Error("Method definitions cannot be public. You should mark the object as public instead.");return r?{type:"MethodDefinition",objectName:s,methodName:r,params:i,body:n,position:e}:{type:"FunctionDeclaration",name:s,params:i,body:n,position:e,isPublic:t}}parseBlock(){if(this.consume(o.NEWLINE),!this.check(o.INDENT)){let s=this.currentPos();return{type:"Block",body:[],position:s}}let t=this.currentPos();this.consume(o.INDENT);let e=[];for(;!this.check(o.DEDENT)&&!this.stream.isEof;)this.match(o.NEWLINE)||e.push(this.parseStatement());return this.consume(o.DEDENT),{type:"Block",body:e,position:t}}parseImportStatement(){let t=this.currentPos();this.consume(o.KEYWORD,"import");let s=this.consume(o.STRING).value;return this.consume(o.NEWLINE),{type:"ImportStatement",moduleName:s,position:t}}parseWaitStatement(){let t=this.currentPos();this.consume(o.KEYWORD,"wait");let e=this.parseExpression();return this.consume(o.NEWLINE),{type:"WaitStatement",duration:e,position:t}}parseReturnStatement(){let t=this.currentPos();this.consume(o.KEYWORD,"return");let e;return this.check(o.NEWLINE)||(e=this.parseExpression()),this.consume(o.NEWLINE),{type:"ReturnStatement",argument:e,position:t}}parseIfStatement(){let t=this.currentPos();this.consume(o.KEYWORD,"if");let e=this.parseExpression();this.consume(o.PUNCTUATION,":");let s=this.parseBlock(),r;return this.match(o.KEYWORD,"else")&&(this.consume(o.PUNCTUATION,":"),r=this.parseBlock()),{type:"IfStatement",test:e,consequent:s,alternate:r,position:t}}parseForStatement(){let t=this.currentPos();this.consume(o.KEYWORD,"for");let e=this.match(o.PUNCTUATION,"("),s=this.parseIdentifier();if(!this.match(o.KEYWORD,"in"))throw new Error("Expected 'in' after for-loop iterator");let r=this.parseExpression();e&&this.consume(o.PUNCTUATION,")"),this.consume(o.PUNCTUATION,":");let i=this.parseBlock();return{type:"ForStatement",iterator:s,collection:r,body:i,position:t}}parseWhileStatement(){let t=this.currentPos();this.consume(o.KEYWORD,"while");let e=this.parseExpression();this.consume(o.PUNCTUATION,":");let s=this.parseBlock();return{type:"WhileStatement",condition:e,body:s,position:t}}parseDoWhileStatement(){let t=this.currentPos();this.consume(o.KEYWORD,"do"),this.consume(o.PUNCTUATION,":");let e=this.parseBlock();this.consume(o.KEYWORD,"while");let s=this.parseExpression();return{type:"DoWhileStatement",body:e,condition:s,position:t}}parseBreakStatement(){let t=this.currentPos();return this.consume(o.KEYWORD,"break"),this.stream.isEof||this.match(o.NEWLINE),{type:"BreakStatement",position:t}}parseContinueStatement(){let t=this.currentPos();return this.consume(o.KEYWORD,"continue"),this.stream.isEof||this.match(o.NEWLINE),{type:"ContinueStatement",position:t}}parseExpressionStatement(t=!1,e=!1){let s=this.currentPos(),r=this.parseExpression(t,e);return this.stream.isEof||this.consume(o.NEWLINE),{type:"ExpressionStatement",expression:r,position:s}}parseExpression(t=!1,e=!1){let s=this.parseLogicalOr();if(t||e){if(s.type!=="Identifier")throw new Error("Only identifiers can be marked as public or local in assignments.");if(!this.check(o.OPERATOR,"="))throw new Error(`Expected assignment operator '=' after public/local identifier "${s.value}".`)}if(this.match(o.OPERATOR,"=")){let r=this.parseExpression();return{type:"AssignmentExpression",left:s,operator:"=",right:r,isPublic:t,isLocal:e}}return s}parseLogicalOr(){let t=this.parseLogicalAnd();for(;this.match(o.KEYWORD,"or");){let e=this.parseLogicalAnd();t={type:"LogicalExpression",operator:"or",left:t,right:e}}return t}parseLogicalAnd(){let t=this.parseEquality();for(;this.match(o.KEYWORD,"and");){let e=this.parseEquality();t={type:"LogicalExpression",operator:"and",left:t,right:e}}return t}parseEquality(){let t=this.parseRelational();for(;this.check(o.OPERATOR,"==")||this.check(o.OPERATOR,"!=");){let e=this.stream.consume().value,s=this.parseRelational();t={type:"BinaryExpression",left:t,operator:e,right:s}}return t}parseRelational(){let t=this.parseRange();for(;this.check(o.OPERATOR,"<")||this.check(o.OPERATOR,">")||this.check(o.OPERATOR,"<=")||this.check(o.OPERATOR,">=")||this.check(o.OPERATOR,"is")||this.check(o.KEYWORD,"in")||this.check(o.KEYWORD,"not");){if(this.match(o.KEYWORD,"not")){if(!this.match(o.KEYWORD,"in"))throw new Error("Unexpected token 'not'. Did you mean 'not in'?");let i="not in",n=this.parseAdditive();t={type:"BinaryExpression",left:t,operator:i,right:n};continue}let s=this.stream.consume().value,r=this.parseAdditive();t={type:"BinaryExpression",left:t,operator:s,right:r}}return t}parseRange(){let t=this.parseAdditive();for(;this.check(o.OPERATOR,"..");){let e=this.stream.consume().value,s=this.parseAdditive();t={type:"BinaryExpression",left:t,operator:e,right:s}}return t}parseAdditive(){let t=this.parseMultiplicative();for(;this.check(o.OPERATOR,"+")||this.check(o.OPERATOR,"-");){let e=this.stream.consume().value,s=this.parseMultiplicative();t={type:"BinaryExpression",left:t,operator:e,right:s}}return t}parseMultiplicative(){let t=this.parseUnary();for(;this.check(o.OPERATOR,"*")||this.check(o.OPERATOR,"/")||this.check(o.OPERATOR,"%");){let e=this.stream.consume().value,s=this.parseUnary();t={type:"BinaryExpression",left:t,operator:e,right:s}}return t}parseUnary(){return this.match(o.KEYWORD,"not")||this.match(o.PUNCTUATION,"!")?{type:"UnaryExpression",operator:"not",argument:this.parseUnary()}:this.match(o.OPERATOR,"-")?{type:"UnaryExpression",operator:"-",argument:this.parseUnary()}:this.parseExponentiation()}parseExponentiation(){let t=this.parsePostfix();if(this.match(o.OPERATOR,"^")){let s=this.parseUnary();return{type:"BinaryExpression",left:t,operator:"^",right:s}}return t}parsePostfix(){let t=this.parsePrimary();for(;;)if(this.match(o.PUNCTUATION,"(")){let e=[];if(!this.check(o.PUNCTUATION,")"))do e.push(this.parseExpression());while(this.match(o.PUNCTUATION,","));this.consume(o.PUNCTUATION,")"),t={type:"CallExpression",callee:t,arguments:e}}else if(this.match(o.PUNCTUATION,".")){let e=this.parseIdentifier();t={type:"MemberExpression",object:t,property:e,computed:!1}}else if(this.match(o.PUNCTUATION,"[")){let e=this.parseExpression();this.consume(o.PUNCTUATION,"]"),t={type:"MemberExpression",object:t,property:e,computed:!0}}else break;return t}parsePrimary(){let t=this.stream.peek();if(t?.type===o.NUMBER)return this.stream.consume(),{type:"Literal",value:Number(t.value),raw:t.value};if(t?.type===o.STRING)return this.stream.consume(),{type:"Literal",value:t.value,raw:t.value};if(t?.type===o.KEYWORD){if(t.value==="this")return this.stream.consume(),{type:"ThisExpression"};if(t.value==="parent"){this.stream.consume();let e=this.currentPos();this.consume(o.PUNCTUATION,".");let s=this.parseIdentifier(),r=[];if(this.consume(o.PUNCTUATION,"("),!this.check(o.PUNCTUATION,")"))do r.push(this.parseExpression());while(this.match(o.PUNCTUATION,","));return this.consume(o.PUNCTUATION,")"),{type:"ParentMethodCallExpression",methodName:s,arguments:r,position:e}}if(t.value==="true")return this.stream.consume(),{type:"Literal",value:!0,raw:"true"};if(t.value==="false")return this.stream.consume(),{type:"Literal",value:!1,raw:"false"};if(t.value==="null")return this.stream.consume(),{type:"Literal",value:null,raw:"null"};if(t.value==="new"){this.stream.consume();let e=this.currentPos(),s=this.parseIdentifier();for(;this.match(o.PUNCTUATION,".");){let i=this.parseIdentifier();s={type:"MemberExpression",object:s,property:i,computed:!1}}let r=[];if(this.match(o.PUNCTUATION,"(")){if(!this.check(o.PUNCTUATION,")"))do r.push(this.parseExpression());while(this.match(o.PUNCTUATION,","));this.consume(o.PUNCTUATION,")")}return{type:"NewExpression",className:s,arguments:r,position:e}}}if(this.match(o.PUNCTUATION,"["))return this.parseArrayExpression();if(this.match(o.PUNCTUATION,"{"))return this.parseObjectExpression();if(t?.type===o.IDENTIFIER)return this.parseIdentifier();if(this.match(o.PUNCTUATION,"(")){let e=this.parseExpression();return this.consume(o.PUNCTUATION,")"),e}throw new Error(`Unexpected token in Expression: ${t?.value}`)}skipFormatting(){for(;this.match(o.NEWLINE)||this.match(o.INDENT)||this.match(o.DEDENT););}parseArrayExpression(){this.skipFormatting();let t=this.currentPos();if(this.check(o.PUNCTUATION,"]"))return this.consume(o.PUNCTUATION,"]"),{type:"ArrayExpression",elements:[],position:t};let e=this.parseExpression();if(this.skipFormatting(),this.match(o.KEYWORD,"for")){let r=this.consume(o.IDENTIFIER);this.consume(o.KEYWORD,"in");let i=this.parseExpression();return this.skipFormatting(),this.consume(o.PUNCTUATION,"]"),{type:"ArrayComprehension",expression:e,iterator:{type:"Identifier",value:r.value,position:r.position},collection:i,position:t}}let s=[e];for(;this.match(o.PUNCTUATION,",")&&(this.skipFormatting(),!this.check(o.PUNCTUATION,"]"));)s.push(this.parseExpression()),this.skipFormatting();return this.consume(o.PUNCTUATION,"]"),{type:"ArrayExpression",elements:s,position:t}}parseObjectExpression(){this.skipFormatting();let t=this.currentPos();if(this.check(o.PUNCTUATION,"}"))return this.consume(o.PUNCTUATION,"}"),{type:"ObjectExpression",properties:[],position:t};let e=this.parseIdentifier();this.consume(o.PUNCTUATION,":");let s=this.parseExpression();if(this.match(o.KEYWORD,"for")){let i=this.parseIdentifier();this.consume(o.KEYWORD,"in");let n=this.parseExpression();return this.consume(o.PUNCTUATION,"}"),{type:"ObjectComprehension",key:e,value:s,iterator:i,collection:n,position:t}}let r=[];for(r.push({type:"Property",key:e,value:s,position:t});!this.check(o.PUNCTUATION,"}")&&(this.match(o.PUNCTUATION,","),this.skipFormatting(),!this.check(o.PUNCTUATION,"}"));){let i=this.parseIdentifier();this.consume(o.PUNCTUATION,":");let n=this.parseExpression();r.push({type:"Property",key:i,value:n,position:this.currentPos()})}return this.consume(o.PUNCTUATION,"}"),{type:"ObjectExpression",properties:r,position:t}}parseIdentifier(){let t=this.currentPos();return{type:"Identifier",value:this.consume(o.IDENTIFIER).value,position:t}}consume(t,e){let s=this.stream.peek();if(!s||s.type!==t||e&&s.value!==e){let r=`Expected ${t} ${e||""}, but found ${s?.type} ${s?.value}`,i="";throw s?.position&&(i=` at line ${s.position.lineStart}, column ${s.position.columnStart}`),new Error(r+i)}return this.lastToken=s,this.stream.consume()}match(t,e){return this.check(t,e)?(this.stream.consume(),!0):!1}check(t,e){let s=this.stream.peek();return!s||s.type!==t?!1:!(e&&s.value!==e)}currentPos(){let t=this.stream.peek();return t?t.position:{lineStart:0,lineEnd:0,columnStart:0,columnEnd:0}}};var D=(a=>(a.HALT="HALT",a.CONST="CONST",a.SWAP="SWAP",a.EXPORT="EXPORT",a.IMPORT="IMPORT",a.WAIT="WAIT",a.NEW="NEW",a.SUPER="SUPER",a.ADD="ADD",a.SUB="SUB",a.MUL="MUL",a.DIV="DIV",a.MOD="MOD",a.EXP="EXP",a.NEG="NEG",a.EQ="EQ",a.NEQ="NEQ",a.GT="GT",a.GTE="GTE",a.LT="LT",a.LTE="LTE",a.IN="IN",a.IS="IS",a.NOT="NOT",a.JMP="JMP",a.JMP_IF_FALSE="JMP_IF_FALSE",a.JMP_IF_TRUE="JMP_IF_TRUE",a.DUP="DUP",a.POP="POP",a.LOAD="LOAD",a.STORE="STORE",a.LOAD_LOCAL="LOAD_LOCAL",a.STORE_LOCAL="STORE_LOCAL",a.CALL="CALL",a.CALL_METHOD="CALL_METHOD",a.CALL_PARENT="CALL_PARENT",a.RET="RET",a.MAKE_ARRAY="MAKE_ARRAY",a.MAKE_RANGE="MAKE_RANGE",a.MAKE_OBJECT="MAKE_OBJECT",a.MAKE_FUNCTION="MAKE_FUNCTION",a.MAKE_CLASS="MAKE_CLASS",a.MAKE_METHOD="MAKE_METHOD",a.GET_PROP="GET_PROP",a.SET_PROP="SET_PROP",a.ITER_INIT="ITER_INIT",a.ITER_NEXT="ITER_NEXT",a.ARRAY_PUSH="ARRAY_PUSH",a))(D||{}),v=(a=>(a[a.HALT=0]="HALT",a[a.CONST=1]="CONST",a[a.SWAP=2]="SWAP",a[a.EXPORT=3]="EXPORT",a[a.IMPORT=4]="IMPORT",a[a.WAIT=5]="WAIT",a[a.NEW=6]="NEW",a[a.SUPER=7]="SUPER",a[a.ADD=16]="ADD",a[a.SUB=17]="SUB",a[a.MUL=18]="MUL",a[a.DIV=19]="DIV",a[a.MOD=20]="MOD",a[a.EXP=21]="EXP",a[a.NEG=22]="NEG",a[a.EQ=32]="EQ",a[a.NEQ=33]="NEQ",a[a.GT=34]="GT",a[a.GTE=35]="GTE",a[a.LT=36]="LT",a[a.LTE=37]="LTE",a[a.IN=38]="IN",a[a.IS=39]="IS",a[a.NOT=48]="NOT",a[a.JMP=64]="JMP",a[a.JMP_IF_FALSE=65]="JMP_IF_FALSE",a[a.JMP_IF_TRUE=66]="JMP_IF_TRUE",a[a.DUP=67]="DUP",a[a.POP=68]="POP",a[a.LOAD=80]="LOAD",a[a.STORE=81]="STORE",a[a.LOAD_LOCAL=82]="LOAD_LOCAL",a[a.STORE_LOCAL=83]="STORE_LOCAL",a[a.CALL=96]="CALL",a[a.CALL_METHOD=97]="CALL_METHOD",a[a.CALL_PARENT=98]="CALL_PARENT",a[a.RET=99]="RET",a[a.MAKE_ARRAY=112]="MAKE_ARRAY",a[a.MAKE_RANGE=113]="MAKE_RANGE",a[a.MAKE_OBJECT=114]="MAKE_OBJECT",a[a.MAKE_FUNCTION=115]="MAKE_FUNCTION",a[a.MAKE_CLASS=116]="MAKE_CLASS",a[a.MAKE_METHOD=117]="MAKE_METHOD",a[a.GET_PROP=128]="GET_PROP",a[a.SET_PROP=129]="SET_PROP",a[a.ITER_INIT=144]="ITER_INIT",a[a.ITER_NEXT=145]="ITER_NEXT",a[a.ARRAY_PUSH=146]="ARRAY_PUSH",a))(v||{});var T=class{constructor(t){c(this,"buffer");c(this,"view");c(this,"offset");c(this,"decoder");this.buffer=t,this.view=new DataView(t.buffer,t.byteOffset,t.byteLength),this.offset=0,this.decoder=new TextDecoder("utf-8")}readUInt8(){let t=this.view.getUint8(this.offset);return this.offset+=1,t}readUInt16(){let t=this.view.getUint16(this.offset,!0);return this.offset+=2,t}readUInt32(){let t=this.view.getUint32(this.offset,!0);return this.offset+=4,t}readFloat64(){let t=this.view.getFloat64(this.offset,!0);return this.offset+=8,t}readString(){let t=this.readUInt32();if(t===0)return"";let e=this.buffer.subarray(this.offset,this.offset+t);return this.offset+=t,this.decoder.decode(e)}get position(){return this.offset}get isEof(){return this.offset>=this.buffer.byteLength}};var S=class u{constructor(){c(this,"valueToId",new Map);c(this,"idToValue",new Map)}static fromProgram(t){let e=new u;for(let s of t.instructions)u._add(e,s.arg);for(let s of t.exported.functions)e.add(s);for(let s of t.exported.variables)e.add(s);return e}static fromBinary(t){let e=new u,s=t instanceof T?t:new T(t),r=s.readUInt32();for(let i=0;i<r;i++){let n=s.readUInt8();if(n===0)e.add(s.readString(),!0);else if(n===1)e.add(s.readFloat64(),!0);else throw new Error(`Corrupt binary: Unknown constant type tag ${n} at offset ${s.position}`)}return e}static _add(t,e){if(e!=null){if(typeof e=="string"||typeof e=="number"){t.add(e);return}if(Array.isArray(e)){for(let s of e)u._add(t,s);return}if(typeof e=="object")for(let s of Object.keys(e))(typeof s=="string"||typeof s=="number")&&(t.add(s),u._add(t,e[s]))}}getId(t){return this.valueToId.get(t)??null}getValue(t){return this.idToValue.get(t)??null}getAll(){return Array.from(this.idToValue.values())}add(t,e=!1){if(e){let r=this.valueToId.size;return this.valueToId.set(t,r),this.idToValue.set(r,t),r}if(this.valueToId.has(t))return this.valueToId.get(t);let s=this.valueToId.size;return this.valueToId.set(t,s),this.idToValue.set(s,t),s}};var j=class u{constructor(t){c(this,"reader");c(this,"pool");c(this,"withDebugInfo",!1);this.reader=new T(t)}static read(t){return new u(t).read()}read(){let{hash:t,moduleName:e}=this.readHeader();this.readConstants();let s=this.readExports(),r=this.readReferences(),i=this.readInstructions(),n=this.readSource();return{hash:t,source:n,moduleName:e,instructions:i,references:r,exported:s}}readHeader(){let t=[this.reader.readUInt8(),this.reader.readUInt8(),this.reader.readUInt8()];if(t[0]!==76||t[1]!==85||t[2]!==88)throw new Error("Invalid file format.");let e=this.reader.readUInt8();if(e!==1)throw new Error(`Unsupported version ${e}. Expected 1.`);this.withDebugInfo=this.reader.readUInt8()===1;let r=this.reader.readUInt8()>0?this.reader.readString():void 0;return{hash:this.reader.readUInt8()>0?this.reader.readString():"",moduleName:r}}readConstants(){this.pool=new S;let t=this.reader.readUInt16();for(let e=0;e<t;e++){let s=this.reader.readUInt8();if(s===1)this.pool.add(this.reader.readFloat64(),!0);else if(s===2)this.pool.add(this.reader.readString(),!0);else throw new Error(`Corrupt binary: Unknown constant type tag ${s} at offset ${this.reader.position}`)}}readExports(){let t=[],e=[],s=this.reader.readUInt16();for(let i=0;i<s;i++)t.push(this.getPoolString(this.reader.readUInt16()));let r=this.reader.readUInt16();for(let i=0;i<r;i++)e.push(this.getPoolString(this.reader.readUInt16()));return{functions:t,variables:e}}readReferences(){let t={},e={},s=this.reader.readUInt16();for(let i=0;i<s;i++){let n=this.getPoolString(this.reader.readUInt16()),h=this.reader.readUInt16(),p=this.reader.readUInt8();t[n]={address:h,numArgs:p}}let r=this.reader.readUInt16();for(let i=0;i<r;i++){let n=this.getPoolString(this.reader.readUInt16()),h=this.reader.readUInt16(),p=this.reader.readUInt8();e[n]={address:h,numArgs:p}}return{functions:t,events:e}}readInstructions(){let t=this.reader.readUInt16(),e=[];for(let s=0;s<t;s++){let r={op:v[this.reader.readUInt8()]},i=this.readValueArg();i!==void 0&&(r.arg=i),this.withDebugInfo&&(this.reader.readUInt8()===1&&(r.pos={lineStart:this.reader.readUInt16(),columnStart:this.reader.readUInt16(),lineEnd:this.reader.readUInt16(),columnEnd:this.reader.readUInt16()}),this.reader.readUInt16()>0&&(r.comment=this.reader.readString())),e.push(r)}return e}readSource(){return this.withDebugInfo?this.reader.readString():(this.reader.readUInt32(),"")}readValueArg(){let t=this.reader.readUInt8();switch(t){case 0:return;case 1:return this.getPoolString(this.reader.readUInt16());case 2:let e=this.reader.readUInt16();return this.pool.getValue(e);case 3:return this.reader.readUInt8()===1;case 4:{let s=this.reader.readUInt16(),r=[];for(let i=0;i<s;i++)r.push(this.readValueArg());return r}case 5:{let s=this.reader.readUInt16(),r={};for(let i=0;i<s;i++)r[this.readValueArg()]=this.readValueArg();return r}case 6:return null;default:throw new Error(`Unknown argument type tag: ${t} at offset ${this.reader.position}`)}}getPoolString(t){let e=this.pool.getValue(t);if(typeof e!="string")throw new Error(`Expected string constant at pool ID ${t}, got ${typeof e}`);return e}};var P=class{constructor(t=1024){c(this,"buffer");c(this,"view");c(this,"offset");this.buffer=new Uint8Array(t),this.view=new DataView(this.buffer.buffer),this.offset=0}writeUInt8(t){this.ensureCapacity(1),this.view.setUint8(this.offset,t),this.offset+=1}writeUInt16(t){this.ensureCapacity(2),this.view.setUint16(this.offset,t,!0),this.offset+=2}writeUInt32(t){this.ensureCapacity(4),this.view.setUint32(this.offset,t,!0),this.offset+=4}writeFloat64(t){this.ensureCapacity(8),this.view.setFloat64(this.offset,t,!0),this.offset+=8}writeString(t){let s=new TextEncoder().encode(t);this.writeUInt32(s.length),this.ensureCapacity(s.length),this.buffer.set(s,this.offset),this.offset+=s.length}toBuffer(){return this.buffer.slice(0,this.offset)}ensureCapacity(t){if(this.offset+t>this.buffer.length){let e=Math.max(this.buffer.length*2,this.offset+t),s=new Uint8Array(e);s.set(this.buffer),this.buffer=s,this.view=new DataView(this.buffer.buffer)}}};var W=class u{constructor(t,e=!1){c(this,"program");c(this,"writer");c(this,"pool");c(this,"withDebugInfo");this.program=t,this.pool=S.fromProgram(t),this.writer=new P,this.withDebugInfo=e}static write(t,e){return new u(t,e).write()}write(){return this.writeHeader(),this.writeConstants(),this.writeExports(),this.writeReferences(),this.writeInstructions(),this.writeSource(),this.writer.toBuffer()}writeHeader(){this.writer.writeUInt8(76),this.writer.writeUInt8(85),this.writer.writeUInt8(88),this.writer.writeUInt8(1),this.writer.writeUInt8(this.withDebugInfo?1:0),this.writer.writeUInt8(this.program.moduleName?.length??0),this.program.moduleName&&this.writer.writeString(this.program.moduleName),this.writer.writeUInt8(this.program.hash.length),this.writer.writeString(this.program.hash)}writeConstants(){let t=this.pool.getAll();this.writer.writeUInt16(t.length);for(let e of t)switch(typeof e){case"number":this.writer.writeUInt8(1),this.writer.writeFloat64(e);break;case"string":this.writer.writeUInt8(2),this.writer.writeString(e);break;default:throw new Error(`Unsupported constant type: ${typeof e}`)}}writeExports(){this.writer.writeUInt16(this.program.exported.functions.length);for(let t of this.program.exported.functions)this.writer.writeUInt16(this.getPoolId(t));this.writer.writeUInt16(this.program.exported.variables.length);for(let t of this.program.exported.variables)this.writer.writeUInt16(this.getPoolId(t))}writeReferences(){let t=Object.keys(this.program.references.functions);this.writer.writeUInt16(t.length);for(let s of t){let r=this.program.references.functions[s];this.writer.writeUInt16(this.getPoolId(s)),this.writer.writeUInt16(r.address),this.writer.writeUInt8(r.numArgs)}let e=Object.keys(this.program.references.events);this.writer.writeUInt16(e.length);for(let s of e){let r=this.program.references.events[s];this.writer.writeUInt16(this.getPoolId(s)),this.writer.writeUInt16(r.address),this.writer.writeUInt8(r.numArgs)}}writeInstructions(){this.writer.writeUInt16(this.program.instructions.length);for(let t of this.program.instructions)this.writer.writeUInt8(v[t.op]),this.writeValueArg(t.arg),this.withDebugInfo&&(t.pos?(this.writer.writeUInt8(1),this.writer.writeUInt16(t.pos.lineStart),this.writer.writeUInt16(t.pos.columnStart),this.writer.writeUInt16(t.pos.lineEnd),this.writer.writeUInt16(t.pos.columnEnd)):this.writer.writeUInt8(0),this.writer.writeUInt16(t.comment?.length??0),t.comment&&this.writer.writeString(t.comment))}writeSource(){if(!this.withDebugInfo){this.writer.writeUInt32(0);return}this.writer.writeString(this.program.source)}writeValueArg(t){if(t===void 0){this.writer.writeUInt8(0);return}if(t===null){this.writer.writeUInt8(6);return}if(typeof t=="string"){this.writer.writeUInt8(1),this.writer.writeUInt16(this.getPoolId(t));return}if(typeof t=="number"){this.writer.writeUInt8(2),this.writer.writeUInt16(this.getPoolId(t));return}if(typeof t=="boolean"){this.writer.writeUInt8(3),this.writer.writeUInt8(t?1:0);return}if(Array.isArray(t)){this.writer.writeUInt8(4),this.writer.writeUInt16(t.length);for(let e of t)this.writeValueArg(e);return}if(typeof t=="object"){this.writer.writeUInt8(5);let e=Object.keys(t);this.writer.writeUInt16(e.length);for(let s of e)this.writeValueArg(s),this.writeValueArg(t[s]);return}throw new Error(`Unsupported instruction argument type: ${typeof t}`)}getPoolId(t){let e=this.pool.getId(t);if(e===null)throw new Error(`Value "${t}" not found in constant pool.`);return e}};var H=class u{constructor(){c(this,"loopStack",[]);c(this,"currentPos",null);c(this,"pendingCalls",{});c(this,"currentClassName",null);c(this,"localScopes",[]);c(this,"program",{hash:"",source:"",moduleName:void 0,instructions:[],references:{functions:{},events:{}},exported:{functions:[],variables:[]}})}static compile(t,e){let s=N.tokenize(t,e),r=k.parse(s,e);return new u().compile(e,t,r)}compile(t,e,s){this.program.moduleName=t,this.program.source=e,this.hoistFunctions(s),this.hoistEventHooks(s);for(let r of s.body)this.visit(r);return this.emit("RET"),this.program.hash=this.createHash(),this.program}visit(t){switch(t.position&&(this.currentPos=t.position),t.type){case"Block":t.body.forEach(s=>this.visit(s));break;case"ExpressionStatement":this.visit(t.expression),this.emit("POP");break;case"ThisExpression":this.emit("LOAD","this");break;case"ImportStatement":{let s=t.moduleName;this.emit("IMPORT",s),this.emit("STORE",[s]);break}case"ReturnStatement":let e=t;e.argument?this.visit(e.argument):this.emit("CONST",null),this.emit("RET");break;case"IfStatement":this.visitIfStatement(t);break;case"WaitStatement":this.visit(t.duration),this.emit("WAIT");break;case"FunctionDeclaration":case"EventHook":break;case"MethodDefinition":this.visitMethodDefinition(t);break;case"Literal":this.emit("CONST",t.value);break;case"Identifier":this.emitLoadByName(t.value);break;case"BinaryExpression":this.visitBinaryExpression(t);break;case"LogicalExpression":this.visitLogicalExpression(t);break;case"UnaryExpression":this.visitUnaryExpression(t);break;case"CallExpression":this.visitCallExpression(t);break;case"ForStatement":this.visitForStatement(t);break;case"WhileStatement":this.visitWhileStatement(t);break;case"DoWhileStatement":this.visitDoWhileStatement(t);break;case"BreakStatement":this.visitBreakStatement(t);break;case"ContinueStatement":this.visitContinueStatement(t);break;case"ArrayExpression":this.visitArrayExpression(t);break;case"ArrayComprehension":this.visitArrayComprehension(t);break;case"ObjectExpression":this.visitObjectExpression(t);break;case"ObjectComprehension":this.visitObjectComprehension(t);break;case"MemberExpression":this.visitMemberExpression(t);break;case"AssignmentExpression":this.visitAssignmentExpression(t);break;case"ClassStatement":this.visitClassStatement(t);break;case"NewExpression":this.visitNewExpression(t);break;case"ParentMethodCallExpression":this.visitParentMethodCallExpression(t);break;default:this.throwError(`Compiler: Unknown node type ${t.type}`,t)}}visitBinaryExpression(t){switch(this.visit(t.left),this.visit(t.right),t.operator){case"+":this.emit("ADD");break;case"-":this.emit("SUB");break;case"*":this.emit("MUL");break;case"/":this.emit("DIV");break;case"%":this.emit("MOD");break;case"^":this.emit("EXP");break;case"==":this.emit("EQ");break;case"!=":this.emit("NEQ");break;case">=":this.emit("GTE");break;case">":this.emit("GT");break;case"<=":this.emit("LTE");break;case"<":this.emit("LT");break;case"in":this.emit("IN");break;case"not in":this.emit("IN"),this.emit("NOT");break;case"..":this.emit("MAKE_RANGE");break;case"is":this.visit(t.left),this.visit(t.right),this.emit("IS");break;default:this.throwError(`Compiler: Unknown binary operator ${t.operator}`,t)}}visitLogicalExpression(t){if(this.visit(t.left),this.emit("DUP"),t.operator==="or"){let e=this.emit("JMP_IF_TRUE",-1);this.emit("POP"),this.visit(t.right),this.patch(e,this.program.instructions.length)}else if(t.operator==="and"){let e=this.emit("JMP_IF_FALSE",-1);this.emit("POP"),this.visit(t.right),this.patch(e,this.program.instructions.length)}}visitUnaryExpression(t){switch(this.visit(t.argument),t.operator){case"not":case"!":this.emit("NOT");break;case"-":this.emit("NEG");break;default:this.throwError(`Compiler: Unknown unary operator ${t.operator}`,t)}}visitMethodDefinition(t){let e=this.emit("JMP",0),s=this.program.instructions.length;this.enterLocalScope();for(let r=t.params.length-1;r>=0;r--)this.emitStoreByName(t.params[r].value,!0);this.visit(t.body),this.exitLocalScope(),this.emit("CONST",null),this.emit("RET"),this.patch(e,this.program.instructions.length),this.emit("LOAD",t.objectName.value),this.emit("CONST",t.methodName),this.emit("MAKE_FUNCTION",{name:t.methodName,addr:s,args:t.params.length}),this.emit("SET_PROP"),this.emit("POP")}visitIfStatement(t){this.visit(t.test);let e=this.emit("JMP_IF_FALSE",-1);this.visit(t.consequent);let s=this.emit("JMP",-1);this.patch(e,this.program.instructions.length),t.alternate&&this.visit(t.alternate),this.patch(s,this.program.instructions.length)}visitCallExpression(t){if(t.callee.type==="MemberExpression"){let n=t.callee.property.value;t.arguments.forEach(h=>this.visit(h)),this.visit(t.callee.object),this.emit("CALL_METHOD",{name:n,args:t.arguments.length});return}t.arguments.forEach(n=>this.visit(n));let e=t.callee.value,s=this.program.references.functions[e],r=s?s.address:null,i=this.emit("CALL",{name:e,addr:r,args:t.arguments.length});s&&s.address===-1&&(this.pendingCalls[e]||(this.pendingCalls[e]=[]),this.pendingCalls[e].push(i))}visitArrayExpression(t){for(let e of t.elements)this.visit(e);this.emit("MAKE_ARRAY",t.elements.length)}visitObjectExpression(t){for(let e of t.properties)this.emit("CONST",e.key.value),this.visit(e.value);this.emit("MAKE_OBJECT",t.properties.length)}visitObjectComprehension(t){let e=`$comp_${this.program.instructions.length}`,s=structuredClone(t.key),r=structuredClone(t.value);this.replaceIdentifier(s,t.iterator.value,e),this.replaceIdentifier(r,t.iterator.value,e),this.emit("MAKE_OBJECT"),this.emit("STORE",["$comp_obj_result",!0]),this.visit(t.collection),this.emit("ITER_INIT");let i=this.program.instructions.length,n=this.emit("ITER_NEXT",-1);this.emit("STORE",[e,!0]),this.emit("LOAD","$comp_obj_result"),this.visit(s),this.visit(r),this.emit("SET_PROP"),this.emit("POP"),this.emit("JMP",i);let h=this.program.instructions.length;this.patch(n,h),this.emit("POP"),this.emit("LOAD","$comp_obj_result")}visitMemberExpression(t){this.visit(t.object),t.computed?this.visit(t.property):(t.property.type!=="Identifier"&&this.throwError("Dot notation requires an identifier.",t),this.emit("CONST",t.property.value));let e;t.object.type==="Identifier"&&(e=t.object.value),this.emit("GET_PROP",e)}visitAssignmentExpression(t){if(t.left.type==="Identifier"){if(this.visit(t.right),this.emit("DUP"),this.emitStoreByName(t.left.value,t.isLocal),t.isPublic){let e=t.left.value;this.program.exported.variables.push(e),this.emit("CONST",e),this.emit("CONST",e),this.emit("EXPORT")}return}if(t.left.type==="MemberExpression"){let e=t.left;this.visit(e.object),e.computed?this.visit(e.property):this.emit("CONST",e.property.value),this.visit(t.right),this.emit("SET_PROP");return}this.throwError("Invalid assignment target",t.left??t)}visitArrayComprehension(t){let e=`$comp_${this.program.instructions.length}`,s=structuredClone(t.expression);this.replaceIdentifier(s,t.iterator.value,e),this.emit("MAKE_ARRAY",0),this.emit("STORE",["$comp_result",!0]),this.visit(t.collection),this.emit("ITER_INIT");let r=this.program.instructions.length,i=this.emit("ITER_NEXT",-1);this.emit("STORE",[e,!0]),this.emit("LOAD","$comp_result"),this.visit(s),this.emit("ARRAY_PUSH"),this.emit("JMP",r);let n=this.program.instructions.length;this.patch(i,n),this.emit("POP"),this.emit("LOAD","$comp_result")}visitForStatement(t){let e=`$loop_${t.iterator.value}_${this.program.instructions.length}`;this.visit(t.collection),this.emit("ITER_INIT");let s=this.program.instructions.length;this.loopStack.push({type:"for",continueAddress:s,breakPatchList:[]});let r=this.emit("ITER_NEXT",-1);this.emit("STORE",[e,!0]);let i=structuredClone(t.body);this.replaceIdentifier(i,t.iterator.value,e),this.visit(i),this.emit("JMP",s);let n=this.program.instructions.length;this.patch(r,n);let h=this.loopStack.pop();if(h)for(let p of h.breakPatchList)this.patch(p,n)}visitWhileStatement(t){let e=this.program.instructions.length;this.visit(t.condition);let s=this.emit("JMP_IF_FALSE",0);this.loopStack.push({type:"while",continueAddress:e,breakPatchList:[]}),this.visit(t.body);let r=this.loopStack.pop();this.emit("JMP",e),this.patch(s,this.program.instructions.length);for(let i of r.breakPatchList)this.patch(i,this.program.instructions.length)}visitDoWhileStatement(t){let e=this.program.instructions.length,s={continueAddress:-1,breakPatchList:[],continuePatchList:[],type:"do-while"};this.loopStack.push(s),this.visit(t.body);let r=this.program.instructions.length;for(let n of s.continuePatchList??[])this.patch(n,r);this.visit(t.condition),this.emit("JMP_IF_TRUE",e),this.loopStack.pop();let i=this.program.instructions.length;for(let n of s.breakPatchList)this.patch(n,i)}visitBreakStatement(t){this.loopStack.length===0&&this.throwError("Compiler Error: 'break' used outside of loop",t);let e=this.loopStack[this.loopStack.length-1];e.type==="for"&&this.emit("POP");let s=this.emit("JMP",-1);e.breakPatchList.push(s)}visitContinueStatement(t){this.loopStack.length===0&&this.throwError("Compiler Error: 'continue' used outside of loop",t);let e=this.loopStack[this.loopStack.length-1];if(e.type==="do-while"){let s=this.emit("JMP",-1);e.continuePatchList||(e.continuePatchList=[]),e.continuePatchList.push(s)}else this.emit("JMP",e.continueAddress)}visitClassStatement(t){let e=this.emit("JMP",0),s=this.program.instructions.length;this.currentClassName=t.name.value,this.enterLocalScope();let r=t.params,i=t.methods.find(p=>p.name.value==="init"),n=t.params.length===0&&i;t.params.length>0&&i&&i.params.length>0&&this.throwError(`Class '${t.name.value}' has an ambiguous constructor definition. It defines parameters in the class header (${t.params.length}) AND in the 'init' method (${i.params.length}). Please use only one style: 1. Header params: class ${t.name.value}(...) + fn init() 2. Init params: class ${t.name.value} + fn init(...)`,t),n&&(r=i.params);for(let p=r.length-1;p>=0;p--)this.emitStoreByName(r[p].value,!0);for(let p of t.params)p.type==="PromotedParameter"&&(this.emit("LOAD","this"),this.emit("CONST",p.value),this.emitLoadByName(p.value),this.emit("SET_PROP"),this.emit("POP"));if(t.parent){this.emit("LOAD","this");for(let p of t.parentArgs??[])this.visit(p);this.visit(t.parent),this.emit("CALL_PARENT",t.parentArgs?.length??0),this.emit("POP")}for(let p of t.properties)this.emit("LOAD","this"),this.emit("CONST",p.key.value),this.visit(p.value),this.emit("SET_PROP"),this.emit("POP");if(i){let p=r.length;if(n){for(let l of r)this.emitLoadByName(l.value);p=r.length}this.emit("LOAD","this"),this.emit("CALL_METHOD",{name:"init",args:p}),this.emit("POP")}this.emit("LOAD","this"),this.emit("RET"),this.exitLocalScope();let h=this.program.instructions.length;this.patch(e,h),t.parent?this.visit(t.parent):this.emit("CONST",null),this.emit("MAKE_CLASS",[t.name.value,s,r.length]),this.emit("STORE",[t.name.value]);for(let p of t.methods){let l=this.emit("JMP",0),m=this.program.instructions.length;this.enterLocalScope();for(let d=p.params.length-1;d>=0;d--)this.emitStoreByName(p.params[d].value,!0);this.visit(p.body),this.exitLocalScope(),this.program.instructions[this.program.instructions.length-1].op!=="RET"&&(this.emit("CONST",0),this.emit("RET"));let f=this.program.instructions.length;this.patch(l,f),this.emit("LOAD",t.name.value),this.emit("MAKE_FUNCTION",{name:p.name.value,addr:m,args:p.params.length}),this.emit("MAKE_METHOD")}this.currentClassName=null,t.isPublic&&(this.program.exported.functions.push(t.name.value),this.emit("CONST",t.name.value),this.emit("CONST",t.name.value),this.emit("EXPORT"))}visitNewExpression(t){for(let e of t.arguments)this.visit(e);this.visit(t.className),this.emit("NEW",t.arguments.length)}visitParentMethodCallExpression(t){this.emit("LOAD","this");for(let e of t.arguments)this.visit(e);this.emit("SUPER",{name:t.methodName.value,args:t.arguments.length,callee:this.currentClassName})}hoistFunctions(t){let e=t.body.filter(r=>r.type==="FunctionDeclaration");if(e.length===0)return;this.currentPos={lineStart:1,lineEnd:1,columnStart:1,columnEnd:3};let s=this.emit("JMP",-1);for(let r of e)this.program.references.functions[r.name.value]={address:-1,numArgs:r.params.length},r.isPublic&&this.program.exported.functions.push(r.name.value);for(let r of e){let i=r.name.value,n=this.program.instructions.length;this.program.references.functions[i].address=n,this.currentPos=r.position,this.enterLocalScope();let h=[],p=this.program.instructions.length;for(let m=r.params.length-1;m>=0;m--){let f=r.params[m].value;h.push(f),this.emitStoreByName(f,!0)}this.visit(r.body),this.exitLocalScope(),this.program.instructions[p].comment=`DECL ${i}(${h.reverse().join(", ")})`;let l=r.body.body[r.body.body.length-1];(!l||l.type!=="ReturnStatement")&&(this.emit("CONST",null),this.emit("RET"))}for(let[r,i]of Object.entries(this.pendingCalls)){let n=this.program.references.functions[r].address;if(n===-1)throw new Error(`Compiler Error: Function '${r}' was called but never defined.`);for(let h of i)this.program.instructions[h].arg.addr=n}this.pendingCalls={},this.patch(s,this.program.instructions.length);for(let r of e){if(!r.isPublic)continue;let i=r.name.value,n=this.program.references.functions[i];this.emit("MAKE_FUNCTION",{name:i,addr:n.address,args:n.numArgs}),this.emit("DUP"),this.emit("STORE",[i]),this.emit("CONST",i),this.emit("CONST",i),this.emit("EXPORT")}}hoistEventHooks(t){let e=t.body.filter(r=>r.type==="EventHook");if(e.length===0)return;let s=this.emit("JMP",-1);for(let r of e){this.program.references.events[r.name.value]={address:this.program.instructions.length,numArgs:r.params.length},this.enterLocalScope();let i=[],n=this.program.instructions.length;for(let p=r.params.length-1;p>=0;p--){let l=r.params[p].value;i.push(l),this.emitStoreByName(l,!0)}this.visit(r.body),this.exitLocalScope(),this.program.instructions[n].comment=`HOOK ${r.name.value}(${i.reverse().join(", ")})`;let h=r.body.body[r.body.body.length-1];(!h||h.type!=="ReturnStatement")&&(this.emit("CONST",null),this.emit("RET"))}this.patch(s,this.program.instructions.le