UNPKG

python2igcse

Version:

Convert Python code to IGCSE Pseudocode format

1 lines 74.3 kB
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Python2IGCSE=t():e.Python2IGCSE=t()}(this,()=>(()=>{"use strict";var e={d:(t,s)=>{for(var i in s)e.o(s,i)&&!e.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:s[i]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};function s(e,t,s=[],i){const n={kind:e,text:t,children:s};return void 0!==i&&(n.meta=i),n}function i(e){return 1+e.children.reduce((e,t)=>e+i(t),0)}e.r(t),e.d(t,{Python2IGCSEBrowser:()=>f,convertPythonToIGCSE:()=>g,default:()=>x});class n{constructor(e={}){Object.defineProperty(this,"options",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"context",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"startTime",{enumerable:!0,configurable:!0,writable:!0,value:0}),this.options=this.getDefaultOptions(e),this.context=this.createInitialContext()}getDefaultOptions(e){return{debug:e.debug??!1,strictTypes:e.strictTypes??!0,strictMode:e.strictMode??!1,preserveComments:e.preserveComments??!0,includeComments:e.includeComments??!0,preserveWhitespace:e.preserveWhitespace??!1,indentSize:e.indentSize??3,maxDepth:e.maxDepth??50,maxNestingDepth:e.maxNestingDepth??50,maxErrors:e.maxErrors??100,timeout:e.timeout??3e4,allowExperimentalSyntax:e.allowExperimentalSyntax??!1}}createInitialContext(){const e={name:"global",variables:new Map,functions:new Map,type:"global"},t={currentScope:e,scopeStack:[e],indentLevel:0,errors:[],warnings:[],arrayInfo:{},parameterMapping:{},startTime:Date.now(),isClass:e=>!(!t.classDefinitions||void 0===t.classDefinitions[e])};return t}addError(e,t,s,i){const n=function(e,t,s,i,n="error"){const r={message:e,type:t,severity:n};return void 0!==s&&(r.line=s),void 0!==i&&(r.column=i),r}(e,t,s,i);this.context.errors.push(n),this.options.debug&&console.error(`Parse Error: ${e} at line ${s}:${i}`)}addWarning(e,t,s,i){const n=function(e,t,s,i){const n={message:e,type:t};return void 0!==s&&(n.line=s),void 0!==i&&(n.column=i),n}(e,t,s,i);this.context.warnings.push(n),this.options.debug&&console.warn(`Parse Warning: ${e} at line ${s}:${i}`)}enterScope(e,t){const s={name:e,parent:this.context.currentScope,variables:new Map,functions:new Map,type:t};this.context.scopeStack.push(s),this.context.currentScope=s}exitScope(){this.context.scopeStack.length>1&&(this.context.scopeStack.pop(),this.context.currentScope=this.context.scopeStack[this.context.scopeStack.length-1])}getCurrentLoopType(){for(let e=this.context.scopeStack.length-1;e>=0;e--){const t=this.context.scopeStack[e];if("while"===t.type||"for"===t.type)return t.type}return null}registerVariable(e,t,s){const i={name:e,type:t,scope:this.context.currentScope.name,initialized:!1,definedAt:s};this.context.currentScope.variables.set(e,i)}registerFunction(e,t,s,i){const n={name:e,parameters:t,returnType:s,isFunction:void 0!==s,hasReturn:void 0!==s,definedAt:i};this.context.currentScope.functions.set(e,n),this.context.currentFunction=n}findVariable(e){let t=this.context.currentScope;for(;t;){const s=t.variables.get(e);if(s)return s;t=t.parent}}findFunction(e){let t=this.context.currentScope;for(;t;){const s=t.functions.get(e);if(s)return s;t=t.parent}}registerClass(e,t){this.options.debug&&console.log(`Registering class: ${e} at line ${t}`)}increaseIndent(){this.context.indentLevel++,this.context.indentLevel>this.options.maxDepth&&this.addError(`Maximum nesting depth (${this.options.maxDepth}) exceeded`,"validation_error")}decreaseIndent(){this.context.indentLevel>0&&this.context.indentLevel--}createIRNode(e,t,i=[],n){return s(e,t,i,n)}createParseResult(e){const t=Date.now()-this.startTime;return{ir:e,errors:[...this.context.errors],warnings:[...this.context.warnings],stats:{linesProcessed:0,nodesGenerated:e.reduce((e,t)=>e+this.countNodes(t),0),parseTime:t,functionsFound:this.countFunctions(),classesFound:this.context.classDefinitions?Object.keys(this.context.classDefinitions).length:0,variablesFound:this.countVariables()},success:0===this.context.errors.length,parseTime:t}}countNodes(e){return 1+e.children.reduce((e,t)=>e+this.countNodes(t),0)}countFunctions(){let e=0;for(const t of this.context.scopeStack)e+=t.functions.size;return e}countVariables(){let e=0;for(const t of this.context.scopeStack)e+=t.variables.size;return e}startParsing(){this.startTime=Date.now()}debug(e){}resetContext(){this.context=this.createInitialContext()}getErrors(){return this.context.errors}getWarnings(){return this.context.warnings}}class r{visitExpression(e){if(!e)return"";if(e.raw){const t=this.parseRawExpression(e.raw);return e.keepParentheses?`(${t})`:t}switch(e.type){case"Name":return e.id;case"Constant":return this.formatConstant(e.value);case"Num":return e.n.toString();case"Str":return`"${e.s}"`;case"NameConstant":return this.formatNameConstant(e.value);case"BinOp":return this.visitBinOp(e);case"UnaryOp":return this.visitUnaryOp(e);case"Compare":return this.visitCompare(e);case"BoolOp":return this.visitBoolOp(e);case"Call":return this.visitCallExpression(e);case"Attribute":return this.visitAttribute(e);case"Subscript":return this.visitSubscript(e);case"List":case"Tuple":return this.visitList(e);case"Dict":return this.visitDict(e);case"ListComp":return this.visitListComp(e);case"IfExp":return this.visitIfExp(e);case"JoinedStr":return this.visitJoinedStr(e);case"Expr":return e.parenthesized?`(${this.visitExpression(e.value)})`:this.visitExpression(e.value);default:return`/* ${e.type} */`}}parseRawExpression(e){const t=[];let s=e.replace(/"([^"]*)"/g,(e,s)=>{const i=`__STRING_${t.length}__`;return t.push(s),`"${i}"`});return s=s.replace(/==/g," = ").replace(/!=/g," ≠ ").replace(/>=/g," ≥ ").replace(/<=/g," ≤ ").replace(/\band\b/g," AND ").replace(/\bor\b/g," OR ").replace(/\bnot\b/g,"NOT ").replace(/%/g," MOD ").replace(/\blen\(/g,"LENGTH(").replace(/\bstr\(/g,"STRING(").replace(/\bint\(/g,"INTEGER(").replace(/\bfloat\(/g,"REAL(").replace(/\babs\(/g,"ABS(").replace(/\bmax\(/g,"MAX(").replace(/\bmin\(/g,"MIN(").replace(/\bround\(/g,"ROUND("),s=s.replace(/"__STRING_(\d+)__"/g,(e,s)=>`"${t[parseInt(s)]}"`),s.trim()}formatConstant(e){return"string"==typeof e?`"${e}"`:"boolean"==typeof e?e?"TRUE":"FALSE":null===e?"NULL":e.toString()}formatNameConstant(e){return!0===e?"TRUE":!1===e?"FALSE":null===e?"NULL":e.toString()}visitBinOp(e){const t=this.visitExpression(e.left),s=this.visitExpression(e.right);return"Add"===e.op.type&&(this.isExplicitStringType(e.left)||this.isExplicitStringType(e.right))?`${t} & ${s}`:`${t} ${this.convertOperator(e.op)} ${s}`}visitUnaryOp(e){const t=this.visitExpression(e.operand);return`${this.convertUnaryOperator(e.op)} ${t}`}visitCompare(e){let t=this.visitExpression(e.left);for(let s=0;s<e.ops.length;s++)t+=` ${this.convertCompareOperator(e.ops[s])} ${this.visitExpression(e.comparators[s])}`;return t}visitBoolOp(e){const t="And"===e.op.type?" AND ":" OR ";return e.values.map(e=>this.visitExpression(e)).join(t)}visitCallExpression(e){if("Attribute"===e.func.type){const t=this.visitExpression(e.func.value),s=e.func.attr,i=e.args.map(e=>this.visitExpression(e));switch(s){case"upper":return`UCASE(${t})`;case"lower":return`LCASE(${t})`;case"strip":return`TRIM(${t})`;case"split":return i.length>0?`SPLIT(${t}, ${i[0]})`:`SPLIT(${t})`;case"replace":return i.length>=2?`REPLACE(${t}, ${i[0]}, ${i[1]})`:`${t}.${s}(${i.join(", ")})`;case"find":return i.length>0?`FIND(${t}, ${i[0]})`:`${t}.${s}(${i.join(", ")})`;case"startswith":return i.length>0?`STARTSWITH(${t}, ${i[0]})`:`${t}.${s}(${i.join(", ")})`;case"endswith":return i.length>0?`ENDSWITH(${t}, ${i[0]})`:`${t}.${s}(${i.join(", ")})`;default:return`${t}.${s}(${i.join(", ")})`}}const t=this.visitExpression(e.func),s=e.args.map(e=>this.visitExpression(e));return this.convertBuiltinFunction(t,s)||`${t}(${s.join(", ")})`}visitAttribute(e){if("Subscript"===e.value.type){const t=this.visitExpression(e.value.value),s=e.value.slice;return"Num"===s.type?`${t}[${s.n+1}].${e.attr}`:"Constant"===s.type&&"number"==typeof s.value?`${t}[${s.value+1}].${e.attr}`:"Name"===s.type?`${t}[${this.visitExpression(s)} + 1].${e.attr}`:`${t}[${this.visitExpression(s)}].${e.attr}`}const t=this.visitExpression(e.value);switch(e.attr){case"upper":return`UCASE(${t})`;case"lower":return`LCASE(${t})`;case"strip":return`TRIM(${t})`;case"length":case"__len__":return`LENGTH(${t})`;default:return`${t}.${e.attr}`}}visitSubscript(e){const t=this.visitExpression(e.value),s=this.visitExpression(e.slice);return"Num"===e.slice.type?`${t}[${e.slice.n+1}]`:"Constant"===e.slice.type&&"number"==typeof e.slice.value?`${t}[${e.slice.value+1}]`:"Name"===e.slice.type?`${t}[${s} + 1]`:`${t}[${s}]`}visitList(e){return`[${e.elts.map(e=>this.visitExpression(e)).join(", ")}]`}visitDict(e){const t=[];for(let s=0;s<e.keys.length;s++){const i=this.visitExpression(e.keys[s]),n=this.visitExpression(e.values[s]);t.push(`${i}: ${n}`)}return`{${t.join(", ")}}`}visitListComp(e){return"[/* list comprehension */]"}visitIfExp(e){return`IF ${this.visitExpression(e.test)} THEN ${this.visitExpression(e.body)} ELSE ${this.visitExpression(e.orelse)}`}visitJoinedStr(e){const t=[];for(const s of e.values)if("Constant"===s.type)t.push(`"${s.value}"`);else if("FormattedValue"===s.type){const e=this.visitExpression(s.value);t.push(e)}else t.push(this.visitExpression(s));return t.join(" & ")}convertBuiltinFunction(e,t){switch(e){case"print":return`OUTPUT ${t.join(", ")}`;case"input":return t.length>0?`input(${t[0]})`:"input()";case"len":return`LENGTH(${t[0]})`;case"str":return`STRING(${t[0]})`;case"int":return`INTEGER(${t[0]})`;case"float":return`REAL(${t[0]})`;case"abs":return`ABS(${t[0]})`;case"max":return`MAX(${t.join(", ")})`;case"min":return`MIN(${t.join(", ")})`;case"round":return`ROUND(${t[0]})`;case"range":return 1===t.length?`0 TO ${t[0]} - 1`:2===t.length?`${t[0]} TO ${t[1]} - 1`:3===t.length?`${t[0]} TO ${t[1]} - 1 STEP ${t[2]}`:null;default:return null}}convertOperator(e){switch(e.type){case"Add":default:return"+";case"Sub":return"-";case"Mult":return"*";case"Div":return"/";case"FloorDiv":return"DIV";case"Mod":return"MOD";case"Pow":case"BitXor":return"^";case"LShift":return"<<";case"RShift":return">>";case"BitOr":return"|";case"BitAnd":return"&"}}convertUnaryOperator(e){switch(e.type){case"UAdd":return"+";case"USub":return"-";case"Not":return"NOT";default:return""}}convertCompareOperator(e){switch(e.type){case"Eq":case"Is":default:return"=";case"NotEq":case"IsNot":return"≠";case"Lt":return"<";case"LtE":return"≤";case"Gt":return">";case"GtE":return"≥";case"In":return"IN";case"NotIn":return"NOT IN"}}inferTypeFromValue(e){if(!e)return"STRING";switch(e.type){case"Constant":if("number"==typeof e.value)return Number.isInteger(e.value)?"INTEGER":"REAL";if("string"==typeof e.value)return"STRING";if("boolean"==typeof e.value)return"BOOLEAN";break;case"Num":return Number.isInteger(e.n)?"INTEGER":"REAL";case"Str":return"STRING";case"NameConstant":if(!0===e.value||!1===e.value)return"BOOLEAN";break;case"List":case"Tuple":return"ARRAY";case"Name":return e.id&&/^\d+$/.test(e.id)?"INTEGER":e.id&&/^\d+\.\d+$/.test(e.id)?"REAL":"True"===e.id||"False"===e.id?"BOOLEAN":"STRING";case"BinOp":{const t=this.inferTypeFromValue(e.left),s=this.inferTypeFromValue(e.right);return["Add","Sub","Mult","Div","Mod","Pow"].includes(e.op.type)?"Add"===e.op.type&&("STRING"===t&&this.isExplicitStringType(e.left)||"STRING"===s&&this.isExplicitStringType(e.right))?"STRING":"INTEGER"!==t&&"REAL"!==t&&"INTEGER"!==s&&"REAL"!==s||!("Div"===e.op.type||"INTEGER"!==t&&"STRING"!==t||"INTEGER"!==s&&"STRING"!==s)?"INTEGER":"REAL":["Eq","NotEq","Lt","LtE","Gt","GtE"].includes(e.op.type)||["And","Or"].includes(e.op.type)?"BOOLEAN":"STRING"}}return"STRING"}isNumericConstant(e){return"Constant"===e.type&&"number"==typeof e.value||"Num"===e.type}getNumericValue(e){return"Constant"===e.type&&"number"==typeof e.value?e.value:"Num"===e.type?e.n:0}isArrayInitialization(e){return"List"===e.type||"Tuple"===e.type}isExplicitStringType(e){if(!e)return!1;switch(e.type){case"Constant":return"string"==typeof e.value;case"Str":case"JoinedStr":return!0;case"Name":return["name","str","text","message","title","description","label","id"].some(t=>e.id&&e.id.toLowerCase().includes(t));default:return!1}}}class o extends n{parse(e){throw new Error("StatementVisitor.parse() should not be called directly")}constructor(){super(),Object.defineProperty(this,"expressionVisitor",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"visitNode",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.expressionVisitor=new r}setContext(e){this.context=e}visitAssign(e){if(this.expressionVisitor.isArrayInitialization(e.value))return this.handleArrayInitialization(e);if(this.containsInputCall(e.value))return this.handleInputAssignment(e);if("Call"===e.value.type&&"Name"===e.value.func.type){const t=e.value.func.id;if(this.context.isClass(t))return this.handleClassInstantiation(e)}const t=e.targets[0];if("Subscript"===t.type)return this.handleElementAssign(t,e.value);if("Attribute"===t.type)return this.handleAttributeAssign(t,e.value);if("Call"===e.value.type){const t=this.expressionVisitor.visitExpression(e.value.func),s=e.value.args.map(e=>this.expressionVisitor.visitExpression(e));if(!this.expressionVisitor.convertBuiltinFunction(t,s)&&this.isClassInstantiation(e.value))return console.log("DEBUG: Processing as class instantiation"),this.handleClassInstantiation(e)}let s=`${this.expressionVisitor.visitExpression(t)} ← ${this.expressionVisitor.visitExpression(e.value)}`;e.inlineComment&&(s+=` // ${e.inlineComment}`);const i=this.expressionVisitor.inferTypeFromValue(e.value);return"Name"===t.type&&this.registerVariable(t.id,i,e.lineno),this.createIRNode("assign",s)}handleInputAssignment(e){const t=e.targets[0],s=this.expressionVisitor.visitExpression(t),i=this.findInputCall(e.value);if(!i){const t=`${s} ← ${this.expressionVisitor.visitExpression(e.value)}`;return this.createIRNode("assign",t)}const n=i.args.map(e=>this.expressionVisitor.visitExpression(e));if(n.length>0){const i=`OUTPUT ${n[0]}`,r=`INPUT ${s}`,o=this.createIRNode("output",i),a=this.createIRNode("input",r);return"Name"===t.type&&("Call"===e.value.type&&"Name"===e.value.func.type&&"int"===e.value.func.id?this.registerVariable(t.id,"INTEGER",e.lineno):this.registerVariable(t.id,"STRING",e.lineno)),this.createIRNode("compound","",[o,a])}{const i=`INPUT ${s}`;return"Name"===t.type&&("Call"===e.value.type&&"Name"===e.value.func.type&&"int"===e.value.func.id?this.registerVariable(t.id,"INTEGER",e.lineno):this.registerVariable(t.id,"STRING",e.lineno)),this.createIRNode("input",i)}}findInputCall(e){if("Call"===e.type&&"Name"===e.func.type&&"input"===e.func.id)return e;if("Call"===e.type&&e.args)for(const t of e.args){const e=this.findInputCall(t);if(e)return e}return null}containsInputCall(e){return null!==this.findInputCall(e)}visitAugAssign(e){const t=this.expressionVisitor.visitExpression(e.target),s=this.expressionVisitor.visitExpression(e.value),i=`${t} ← ${t} ${this.convertOperator(e.op)} ${s}`;return this.createIRNode("assign",i)}visitAnnAssign(e){const t=e.target.id;if(this.isListTypeAnnotation(e.annotation)){const s=this.extractListElementType(e.annotation);if(e.value&&"List"===e.value.type&&0===e.value.elts.length){const i=`DECLARE ${t} : ARRAY[1:100] OF ${s}`;return this.registerVariable(t,"ARRAY",e.lineno),this.createIRNode("array",i)}if(e.value){const t={type:"Assign",targets:[e.target],value:e.value,lineno:e.lineno||0};return this.handleArrayInitialization(t)}}const s=this.expressionVisitor.visitExpression(e.target),i=e.value?this.expressionVisitor.visitExpression(e.value):"";if(i){const e=`${s} ← ${i}`;return this.createIRNode("assign",e)}{const i=this.convertAnnotationToIGCSEType(e.annotation),n=`DECLARE ${s} : ${i}`;return this.registerVariable(t,i,e.lineno),this.createIRNode("statement",n)}}visitIf(e){const t=`IF ${this.expressionVisitor.visitExpression(e.test)} THEN`;this.enterScope("if","block"),this.increaseIndent();const s=e.body.map(e=>this.visitNode?this.visitNode(e):this.createIRNode("comment","// Unprocessed node"));this.decreaseIndent(),this.exitScope();let i=s;if(e.orelse&&e.orelse.length>0){const t=e.orelse[0];if("If"===t.type){const e=`ELSE IF ${this.expressionVisitor.visitExpression(t.test)} THEN`,n=this.createIRNode("elseif",e);this.enterScope("elseif","block"),this.increaseIndent();const r=t.body.map(e=>this.visitNode?this.visitNode(e):this.createIRNode("comment","// Unprocessed node"));if(this.decreaseIndent(),this.exitScope(),i=[...s,n,...r],t.orelse&&t.orelse.length>0){const e=this.visitIf({...t,body:[],test:null});e.children&&(i=[...i,...e.children])}}else{const t=this.createIRNode("else","ELSE");this.enterScope("else","block"),this.increaseIndent();const n=e.orelse.map(e=>this.visitNode?this.visitNode(e):this.createIRNode("comment","// Unprocessed node"));this.decreaseIndent(),this.exitScope(),i=[...s,t,...n]}}return this.createIRNode("if",t,i)}visitFor(e){const t=this.expressionVisitor.visitExpression(e.target);if("Call"===e.iter.type&&"range"===e.iter.func.id)return this.handleRangeFor(e,t);if("Name"===e.iter.type){const s=e.iter.id,i="i";let n="3";this.context&&this.context.arrayInfo&&this.context.arrayInfo[s]&&(n=this.context.arrayInfo[s].size.toString());const r=`FOR ${i} ← 1 TO ${n}`;this.enterScope("for","block"),this.increaseIndent();const o=e.body.map(e=>"Expr"===e.type&&"Call"===e.value.type&&e.value.func&&"Name"===e.value.func.type&&"print"===e.value.func.id&&1===e.value.args.length&&("Name"===e.value.args[0].type&&e.value.args[0].id===t||"Str"===e.value.args[0].type&&e.value.args[0].s===t)?this.createIRNode("output",`OUTPUT ${s}[${i}]`):this.visitNode?this.visitNode(e):this.createIRNode("comment","// Unprocessed node"));this.decreaseIndent(),this.exitScope();const a=this.createIRNode("statement",`NEXT ${i}`);return o.push(a),this.createIRNode("for",r,o)}const s=this.expressionVisitor.visitExpression(e.iter),i=`FOR ${t} IN ${s}`;this.enterScope("for","block"),this.increaseIndent();const n=e.body.map(e=>this.visitNode?this.visitNode(e):this.createIRNode("comment","// Unprocessed node"));this.decreaseIndent(),this.exitScope();const r=this.createIRNode("statement",`NEXT ${t}`);return n.push(r),this.createIRNode("for",i,n)}visitWhile(e){if(this.isRepeatUntilPattern(e))return this.createRepeatUntilIR(e);const t=`WHILE ${this.expressionVisitor.visitExpression(e.test)} DO`;this.enterScope("while","block"),this.increaseIndent();const s=e.body.map(e=>this.visitNode?this.visitNode(e):this.createIRNode("comment","// Unprocessed node"));this.decreaseIndent(),this.exitScope();const i=this.createIRNode("endwhile","ENDWHILE");return s.push(i),this.createIRNode("while",t,s)}isRepeatUntilPattern(e){if("Compare"===e.test.type&&"True"!==e.test.raw&&"NameConstant"===e.test.type&&!0!==e.test.value)return!1;const t=e.body[e.body.length-1];if(!t||"If"!==t.type)return!1;const s=t.body;return!(!s||0===s.length)&&1===s.length&&"Break"===s[0].type}createRepeatUntilIR(e){this.enterScope("repeat","block"),this.increaseIndent();const t=e.body.slice(0,-1),s=[];for(const e of t)if("Assign"===e.type&&e.value&&"Call"===e.value.type&&e.value.func&&"input"===e.value.func.id){const t=this.expressionVisitor.visitExpression(e.targets[0]),i=e.value.args||[];if(i.length>0){const e=this.expressionVisitor.visitExpression(i[0]),t=this.createIRNode("output",`OUTPUT ${e}`);s.push(t)}const n=this.createIRNode("input",`INPUT ${t}`);s.push(n)}else{const t=this.visitNode?this.visitNode(e):this.createIRNode("comment","// Unprocessed node");s.push(t)}const i=e.body[e.body.length-1],n=this.expressionVisitor.visitExpression(i.test);this.decreaseIndent(),this.exitScope();const r=this.createIRNode("until",`UNTIL ${n}`);return s.push(r),this.createIRNode("repeat","REPEAT",s)}visitCall(e){const t=this.expressionVisitor.visitExpression(e.func),s=e.args.map(e=>this.expressionVisitor.visitExpression(e));if("print"===t){if(1===s.length&&"JoinedStr"===e.args[0].type){const t=`OUTPUT ${this.expressionVisitor.visitExpression(e.args[0])}`;return this.createIRNode("output",t)}const t=`OUTPUT ${s.join(", ")}`;return this.createIRNode("output",t)}if("input"===t){const e=s.length>0?s[0]:"",t=e?`INPUT ${e}`:"INPUT";return this.createIRNode("input",t)}const i=`CALL ${this.capitalizeFirstLetter(t)}(${s.join(", ")})`;return this.createIRNode("statement",i)}visitReturn(e){if(e.value){const t=this.expressionVisitor.visitExpression(e.value);return this.createIRNode("return",`RETURN ${t}`)}return this.createIRNode("return","RETURN")}visitExpr(e){if(e.value&&"Call"===e.value.type)return this.visitCall(e.value);const t=this.expressionVisitor.visitExpression(e.value);return this.createIRNode("statement",t)}visitComment(e){return this.createIRNode("comment",`// ${e.value}`)}visitPass(e){return this.createIRNode("comment","// pass")}visitBreak(e){return this.createIRNode("break","BREAK")}visitContinue(e){return this.createIRNode("statement","CONTINUE")}visitImport(e){return this.createIRNode("comment","// import statement")}visitTry(e){return this.createIRNode("comment","// try-except statement")}visitRaise(e){return this.createIRNode("comment","// raise statement")}visitWith(e){return this.createIRNode("comment","// with statement")}visitAssert(e){return this.createIRNode("comment","// assert statement")}visitGlobal(e){return this.createIRNode("comment","// global statement")}visitDelete(e){return this.createIRNode("comment","// delete statement")}handleRangeFor(e,t){const s=e.iter.args;let i="0",n="0",r="1";if(1===s.length?n=this.expressionVisitor.visitExpression(s[0]):2===s.length?(i=this.expressionVisitor.visitExpression(s[0]),n=this.expressionVisitor.visitExpression(s[1])):3===s.length&&(i=this.expressionVisitor.visitExpression(s[0]),n=this.expressionVisitor.visitExpression(s[1]),r=this.expressionVisitor.visitExpression(s[2])),"1"===r)n=n.startsWith("LENGTH(")||n.includes("(")?`${n} - 1`:this.expressionVisitor.isNumericConstant(s[s.length-1])?(this.expressionVisitor.getNumericValue(s[s.length-1])-1).toString():`${n} - 1`;else if(3===s.length&&this.expressionVisitor.isNumericConstant(s[0])&&this.expressionVisitor.isNumericConstant(s[1])&&this.expressionVisitor.isNumericConstant(s[2])){const e=this.expressionVisitor.getNumericValue(s[0]),t=this.expressionVisitor.getNumericValue(s[1]),i=this.expressionVisitor.getNumericValue(s[2]);let r=e;if(i>0)for(;r+i<t;)r+=i;else for(;r+i>t;)r+=i;n=r.toString()}const o="1"===r?`FOR ${t} ← ${i} TO ${n}`:`FOR ${t} ← ${i} TO ${n} STEP ${r}`;this.enterScope("for","block"),this.increaseIndent();const a=e.body.map(e=>this.visitNode?this.visitNode(e):this.createIRNode("comment","// Unprocessed node"));this.decreaseIndent(),this.exitScope();const c=this.createIRNode("statement",`NEXT ${t}`);return a.push(c),this.createIRNode("for",o,a)}handleArrayInitialization(e){const t=this.expressionVisitor.visitExpression(e.targets[0]),s=e.value.elts,i=s.length,n=this.reconstructObjectCalls(s);if(n.length>0&&this.isObjectCall(n[0])){const e=n[0],s=this.extractClassName(e),i=`${s}Record`,r=[],o=n.length,a=`DECLARE ${t} : ARRAY[1:${o}] OF ${i}`;return r.push(this.createIRNode("statement",a)),this.context&&this.context.arrayInfo&&(this.context.arrayInfo[t]={size:o,elementType:i,currentIndex:0}),n.forEach((e,i)=>{const n=this.extractArguments(e);"Point"===s&&n.length>=2?(r.push(this.createIRNode("assign",`${t}[${i+1}].x ← ${n[0]}`)),r.push(this.createIRNode("assign",`${t}[${i+1}].y ← ${n[1]}`))):n.forEach((e,s)=>{const n=`field${s+1}`;r.push(this.createIRNode("assign",`${t}[${i+1}].${n} ← ${e}`))})}),this.createIRNode("statement","",r)}{const e=s.length>0?this.expressionVisitor.inferTypeFromValue(s[0]):"STRING",n=`DECLARE ${t} : ARRAY[1:${i}] OF ${e}`,r=this.createIRNode("array",n);this.context&&this.context.arrayInfo&&(this.context.arrayInfo[t]={size:i,elementType:e,currentIndex:0});const o=[];return s.forEach((e,s)=>{const i=this.expressionVisitor.visitExpression(e),n=`${t}[${s+1}] ← ${i}`;o.push(this.createIRNode("assign",n))}),this.createIRNode("statement","",[r,...o])}}reconstructObjectCalls(e){const t=[];let s=0;for(;s<e.length;){const i=e[s];if("Name"===i.type&&i.id){const n=i.id;if(/^[A-Z]\w*\(/.test(n)){let i=n;for(s++;s<e.length&&!i.includes(")");){const t=e[s];"Name"===t.type&&t.id&&(i+=", "+t.id),s++}t.push(i)}else t.push(n),s++}else t.push(this.expressionVisitor.visitExpression(i)),s++}return t}isObjectCall(e){return/^[A-Z]\w*\(.+\)$/.test(e)}extractClassName(e){const t=e.match(/^([A-Z]\w*)\(/);return t?t[1]:"Unknown"}extractArguments(e){const t=e.match(/\((.+)\)$/);return t?t[1].split(",").map(e=>e.trim()):[]}isClassInstantiation(e){if("Name"===e.func.type){const t=/^[A-Z]/.test(e.func.id);return console.log(`DEBUG: Checking if ${e.func.id} is class: ${t}`),t}return console.log("DEBUG: Function type is not Name:",e.func.type),!1}handleClassInstantiation(e){const t=this.expressionVisitor.visitExpression(e.value.func),s=this.expressionVisitor.visitExpression(e.targets[0]),i=e.value.args.map(e=>this.expressionVisitor.visitExpression(e)),n=[],r=`DECLARE ${s} : ${t}Record`;console.log("DEBUG: Adding declaration:",r),n.push(this.createIRNode("statement",r));const o=this.getClassAttributes(t);console.log("DEBUG: classAttributes:",o);for(let e=0;e<Math.min(i.length,o.length);e++){const t=`${s}.${o[e]} ← ${i[e]}`;console.log("DEBUG: Adding assignment:",t),n.push(this.createIRNode("assign",t))}return console.log("DEBUG: Returning block with",n.length,"children"),this.createIRNode("block","",n)}convertOperator(e){switch(e.type){case"Add":default:return"+";case"Sub":return"-";case"Mult":return"*";case"Div":return"/";case"FloorDiv":return"DIV";case"Mod":return"MOD";case"Pow":return"^"}}handleElementAssign(e,t){const s=this.expressionVisitor.visitExpression(e.value),i=this.expressionVisitor.visitExpression(t);let n,r=e.slice;if("Index"===r.type&&(r=r.value),"Constant"===r.type&&"number"==typeof r.value)n=String(r.value+1);else if("Num"===r.type)n=String(r.n+1);else if("Name"===r.type)n=`${r.id} + 1`;else{const t=this.expressionVisitor.visitExpression(e.slice);n=this.convertIndexToOneBased(t)}const o=`${s}[${n}] ← ${i}`;return this.createIRNode("element_assign",o)}handleAttributeAssign(e,t){const s=`${this.expressionVisitor.visitExpression(e.value)}.${e.attr} ← ${this.expressionVisitor.visitExpression(t)}`;return this.createIRNode("attribute_assign",s)}convertIndexToOneBased(e){return/^\d+$/.test(e)?String(parseInt(e)+1):`${e} + 1`}isListTypeAnnotation(e){return!!e&&("Subscript"===e.type&&"Name"===e.value.type&&"list"===e.value.id||"Subscript"===e.type&&"Name"===e.value.type&&"List"===e.value.id)}extractListElementType(e){if("Subscript"===e.type&&e.slice){const t=e.slice;if("Name"===t.type)return this.convertPythonTypeToIGCSE(t.id)}return"STRING"}convertAnnotationToIGCSEType(e){return e?"Name"===e.type?this.convertPythonTypeToIGCSE(e.id):this.isListTypeAnnotation(e)?`ARRAY[1:100] OF ${this.extractListElementType(e)}`:"STRING":"STRING"}convertPythonTypeToIGCSE(e){switch(e){case"int":return"INTEGER";case"str":default:return"STRING";case"bool":return"BOOLEAN";case"float":return"REAL"}}getClassAttributes(e){if(this.context&&this.context.classDefinitions){const t=this.context.classDefinitions[e];if(t&&t.attributes)return t.attributes.map(e=>e.split(" : ")[0])}return"Student"===e?["name","age"]:["x","y"]}capitalizeFirstLetter(e){return e?e.charAt(0).toUpperCase()+e.slice(1):e}createIRNode(e,t,i=[],n){return s(e,t,i,n)}}class a extends n{parse(e){throw new Error("DefinitionVisitor.parse() should not be called directly")}constructor(){super(),Object.defineProperty(this,"expressionVisitor",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"visitNode",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.expressionVisitor=new r}setContext(e){this.context=e}visitFunctionDef(e){const t=this.capitalizeFirstLetter(e.name),s=this.extractParameters(e.args),i=s.map(e=>`${e.name} : ${e.type}`).join(", "),n=this.hasReturnStatement(e.body)?this.inferReturnType(e):null;let r;r=n?`FUNCTION ${t}(${i}) RETURNS ${n}`:`PROCEDURE ${t}(${i})`,this.enterScope(t,"function"),this.increaseIndent(),s.forEach(t=>{this.registerVariable(t.name,t.type,e.lineno)});const o=e.body.map(e=>this.visitNode?this.visitNode(e):this.createIRNode("comment","// Unprocessed node"));this.decreaseIndent(),this.exitScope();const a=n?"ENDFUNCTION":"ENDPROCEDURE",c=this.createIRNode("statement",a);return o.push(c),this.createIRNode("function",r,o)}visitClassDef(e){const t=e.name;return this.shouldTreatAsRecordType(e)?this.createRecordType(e,t):this.createClass(e,t)}createRecordType(e,t){const s=`TYPE ${t}Record`,i=e.body.find(e=>"FunctionDef"===e.type&&"__init__"===e.name),n=[];if(i){const e=this.extractAttributesFromConstructor(i);for(const t of e){const e=`DECLARE ${t}`;n.push(this.createIRNode("statement",e))}}return this.createIRNode("type",s,n)}createClass(e,t){const s=e.bases.length>0?e.bases[0].id:null;let i=`CLASS ${t}`;s&&(i+=` INHERITS ${s}`),this.enterScope(t,"class"),this.increaseIndent();const n=[];for(const t of e.body)if("FunctionDef"===t.type)"__init__"===t.name&&this.extractAttributesFromConstructor(t).forEach(e=>{n.push(this.createIRNode("statement",`PRIVATE ${e}`))}),n.push(this.visitNode?this.visitNode(t):this.createIRNode("comment","// Unprocessed node"));else if("Assign"===t.type){const e=this.visitNode?this.visitNode(t):this.createIRNode("comment","// Unprocessed node");e.text=`PRIVATE ${e.text}`,n.push(e)}this.decreaseIndent(),this.exitScope();const r=this.createIRNode("statement","ENDCLASS");return n.push(r),this.createIRNode("class",i,n)}extractParameters(e){const t=[];return e.args&&e.args.forEach(e=>{const s=e.arg;let i=this.convertPythonTypeToIGCSE(e.annotation);e.annotation||(i="INTEGER"),t.push({name:s,type:i})}),t}convertPythonTypeToIGCSE(e){if(!e)return"INTEGER";if("Name"===e.type)switch(e.id){case"int":default:return"INTEGER";case"str":return"STRING";case"bool":return"BOOLEAN";case"float":return"REAL"}return"INTEGER"}extractAttributesFromConstructor(e){const t=[],s=new Map;e.args&&e.args.args&&e.args.args.forEach(e=>{if("self"!==e.arg){const t=this.convertPythonTypeToIGCSE(e.annotation);s.set(e.arg,t)}});for(const i of e.body)if("Assign"===i.type){const e=i.targets[0];if("Attribute"===e.type&&"self"===e.value.id){const n=e.attr;let r="STRING";r="Name"===i.value.type&&s.has(i.value.id)?s.get(i.value.id):this.expressionVisitor.inferTypeFromValue(i.value),t.push(`${n} : ${r}`)}}return t}shouldTreatAsRecordType(e){if(e.bases&&e.bases.length>0)return!1;if(this.isUsedAsBaseClass(e.name))return!1;const t=e.body.filter(e=>"FunctionDef"===e.type);if(1===t.length&&"__init__"===t[0].name){const e=t[0];return this.isSimpleConstructor(e)}return 0===t.length&&e.body.every(e=>"Assign"===e.type||"AnnAssign"===e.type)}isSimpleConstructor(e){for(const t of e.body){if("Assign"===t.type){const e=t.targets[0];if("Attribute"===e.type&&"Name"===e.value.type&&"self"===e.value.id)continue;return!1}if("Expr"!==t.type||"Constant"!==t.value.type)return!1}return!0}isUsedAsBaseClass(e){if(this.context&&this.context.classDefinitions)for(const[,t]of Object.entries(this.context.classDefinitions))if(t.bases&&t.bases.includes(e))return!0;return!1}hasReturnStatement(e){return e.some(e=>"Return"===e.type||e.body&&this.hasReturnStatement(e.body))}inferReturnType(e){if(e.returns&&e.returns.id)switch(e.returns.id){case"int":return"INTEGER";case"str":default:return"STRING";case"bool":return"BOOLEAN";case"float":return"REAL"}const t=this.extractParameters(e.args),s=new Map;t.forEach(e=>{s.set(e.name,e.type)});const i=e=>{for(const t of e){if("Return"===t.type&&t.value)return this.inferReturnTypeFromExpression(t.value,s);if(t.body&&Array.isArray(t.body)){const e=i(t.body);if(e)return e}if(t.orelse&&Array.isArray(t.orelse)){const e=i(t.orelse);if(e)return e}}return null};return i(e.body)||"INTEGER"}inferReturnTypeFromExpression(e,t){if(!e)return"INTEGER";switch(e.type){case"Constant":if("number"==typeof e.value)return Number.isInteger(e.value)?"INTEGER":"REAL";if("string"==typeof e.value)return"STRING";if("boolean"==typeof e.value)return"BOOLEAN";break;case"Num":return Number.isInteger(e.n)?"INTEGER":"REAL";case"Str":return"STRING";case"Name":return t.has(e.id)?t.get(e.id):e.id&&/^\d+$/.test(e.id)?"INTEGER":e.id&&/^\d+\.\d+$/.test(e.id)?"REAL":"INTEGER";case"BinOp":const s=this.inferReturnTypeFromExpression(e.left,t),i=this.inferReturnTypeFromExpression(e.right,t);return["Add","Sub","Mult","Div","Mod","Pow"].includes(e.op.type)?"Add"===e.op.type&&("STRING"===s&&this.isExplicitStringNode(e.left)||"STRING"===i&&this.isExplicitStringNode(e.right))?"STRING":"INTEGER"===s||"REAL"===s||"INTEGER"===i||"REAL"===i?"Div"===e.op.type?"REAL":"INTEGER"===s&&"INTEGER"===i?"INTEGER":"REAL"===s||"REAL"===i?"REAL":"INTEGER":"INTEGER":["Eq","NotEq","Lt","LtE","Gt","GtE"].includes(e.op.type)?"BOOLEAN":"INTEGER"}return"INTEGER"}isExplicitStringNode(e){if(!e)return!1;switch(e.type){case"Constant":return"string"==typeof e.value;case"Str":case"JoinedStr":return!0;default:return!1}}createIRNode(e,t,i=[],n){return s(e,t,i,n)}capitalizeFirstLetter(e){return e?e.charAt(0).toUpperCase()+e.slice(1):e}}class c extends n{constructor(){super(),Object.defineProperty(this,"statementVisitor",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"definitionVisitor",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.statementVisitor=new o,this.definitionVisitor=new a,this.statementVisitor.setContext(this.context),this.definitionVisitor.setContext(this.context)}parse(e){this.startParsing(),this.resetContext();try{const t=this.parseToAST(e);this.preRegisterAllClasses(t.body),this.statementVisitor.setContext(this.context),this.definitionVisitor.setContext(this.context);const s=this.visitNode(t);return"compound"===s.kind&&s.children?this.createParseResult(s.children):this.createParseResult([s])}catch(e){this.addError(`Parse failed: ${e instanceof Error?e.message:"Unknown error"}`,"syntax_error");const t=s("statement","",[]);return this.createParseResult([t])}}parseToAST(e){const t=e.split("\n"),s=[],i=new Set;let n=0;for(;n<t.length;){if(i.has(n)){n++;continue}const e=t[n].trim();if(e.startsWith("#")){const t={type:"Comment",value:e.substring(1).trim(),lineno:n+1};s.push(t),i.add(n),n++}else if(e){const e=this.parseStatement(t,n);if(e.node){s.push(e.node);for(let t=n;t<e.nextIndex;t++)i.add(t)}n=e.nextIndex}else i.add(n),n++}return{type:"Module",body:s}}parseStatement(e,t){const s=e[t],i=s.trim(),n=s.length-s.trimStart().length,r=this.parseLineToASTNode(i,t+1);if(!r)return{node:null,nextIndex:t+1};if(i.endsWith(":")){const s=[];let i=t+1;for(;i<e.length;){const t=e[i],o=t.trim(),a=t.length-t.trimStart().length;if(!o||o.startsWith("#")){i++;continue}if("If"===r.type&&a===n){if(o.startsWith("elif ")){const t=this.parseStatement(e,i);t.node&&(r.orelse=[t.node]),i=t.nextIndex;break}if(o.startsWith("else:")){const t=[];for(i++;i<e.length;){const s=e[i],r=s.trim(),o=s.length-s.trimStart().length;if(!r||r.startsWith("#")){i++;continue}if(o<=n)break;const a=this.parseStatement(e,i);a.node&&t.push(a.node),i=a.nextIndex}r.orelse=t;break}}if(a<=n)break;const c=this.parseStatement(e,i);c.node&&s.push(c.node),i=c.nextIndex}return"If"!==r.type&&"For"!==r.type&&"While"!==r.type&&"FunctionDef"!==r.type&&"ClassDef"!==r.type||(r.body=s),{node:r,nextIndex:i}}return{node:r,nextIndex:t+1}}parseLineToASTNode(e,t){const s=e.trim();if(s.startsWith("if "))return this.parseIfStatement(s,t);if(s.startsWith("elif ")){const e="if "+s.substring(5);return this.parseIfStatement(e,t)}if(s.startsWith("for "))return this.parseForStatement(s,t);if(s.startsWith("while "))return this.parseWhileStatement(s,t);if(s.startsWith("class "))return this.parseClassDef(s,t);if(s.startsWith("def "))return this.parseFunctionDef(s,t);if(s.includes(": ")&&s.includes(" = ")){const e=s.indexOf(": "),i=s.indexOf(" = ");if(e<i){const n=s.substring(0,e).trim(),r=s.substring(e+2,i).trim(),o=s.substring(i+3).trim();if(/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(n))return{type:"AnnAssign",target:{type:"Name",id:n,ctx:"Store"},annotation:{type:"Subscript",value:{type:"Name",id:r.includes("[")?r.substring(0,r.indexOf("[")):r},slice:r.includes("[")?{type:"Name",id:r.substring(r.indexOf("[")+1,r.indexOf("]"))}:null},value:o?this.parseExpression(o):null,lineno:t}}}if(s.includes(" = ")){const e=s.indexOf(" = "),i=s.substring(0,e).trim(),n=s.substring(e+3).trim(),r=i.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\[(.+)\]$/);if(r&&n.length>0){const[,e,s]=r;return{type:"Assign",targets:[{type:"Subscript",value:{type:"Name",id:e,ctx:"Load"},slice:{type:"Index",value:{type:"Constant",value:parseInt(s),kind:null}},ctx:"Store"}],value:this.parseExpression(n),lineno:t}}const o=i.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\.([a-zA-Z_][a-zA-Z0-9_]*)$/);if(o&&n.length>0){const[,e,s]=o;return{type:"Assign",targets:[{type:"Attribute",value:{type:"Name",id:e,ctx:"Load"},attr:s,ctx:"Store"}],value:this.parseExpression(n),lineno:t}}if(/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(i)&&n.length>0)return this.parseAssignStatement(s,t)}if(s.startsWith("print("))return this.parsePrintStatement(s,t);if(s.startsWith("def "))return this.parseFunctionDef(s,t);if(s.startsWith("class "))return this.parseClassDef(s,t);if(s.startsWith("return"))return this.parseReturnStatement(s,t);if("break"===s)return{type:"Break",lineno:t};if("continue"===s)return{type:"Continue",lineno:t};if(/^[a-zA-Z_][a-zA-Z0-9_]*\s*[+\-*/%]=/.test(s))return this.parseAugAssignStatement(s,t);const i=s.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\((.*)\)$/);if(i){const e=i[1],s=i[2];return{type:"Expr",lineno:t,value:{type:"Call",func:{type:"Name",id:e},args:this.parseArguments(s)}}}return{type:"Expr",lineno:t,value:{type:"Call",func:{type:"Name",id:"unknown"},args:[],raw:s}}}parseAugAssignStatement(e,t){const s=e.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*([+\-*/%])=\s*(.+)$/);if(!s)return{type:"Expr",lineno:t,value:{type:"Call",func:{type:"Name",id:"unknown"},args:[],raw:e}};const[,i,n,r]=s;return{type:"AugAssign",lineno:t,target:{type:"Name",id:i},op:{type:this.getAugAssignOpType(n)},value:{type:"Num",n:isNaN(Number(r))?r:Number(r),raw:r}}}getAugAssignOpType(e){switch(e){case"+":default:return"Add";case"-":return"Sub";case"*":return"Mult";case"/":return"Div";case"%":return"Mod"}}parseIfStatement(e,t){const s=e.match(/^if\s+(.+):\s*$/);return{type:"If",lineno:t,test:{type:"Compare",left:{type:"Name",id:"condition"},ops:[">"],comparators:[{type:"Num",n:0}],raw:s?s[1]:e.substring(3,e.length-1)},body:[],orelse:[]}}parseForStatement(e,t){const s=e.match(/^for\s+(\w+)\s+in\s+(.+):\s*$/),i=s?s[1]:"i",n=s?s[2]:"range(1)";let r=[];if(n.startsWith("range(")&&n.endsWith(")")){const e=n.slice(6,-1);e.trim()&&(r=e.split(",").map(e=>e.trim()).map(e=>({type:"Num",n:isNaN(Number(e))?e:Number(e),raw:e})))}return n.startsWith("range(")?{type:"For",lineno:t,target:{type:"Name",id:i},iter:{type:"Call",func:{type:"Name",id:"range"},args:r,raw:n},body:[],orelse:[]}:{type:"For",lineno:t,target:{type:"Name",id:i},iter:{type:"Name",id:n},body:[],orelse:[]}}parseWhileStatement(e,t){const s=e.match(/^while\s+(.+):\s*$/);return{type:"While",lineno:t,test:{type:"Compare",raw:s?s[1]:e.substring(6,e.length-1)},body:[],orelse:[]}}parseAssignStatement(e,t){const s=e.split(" = "),i=s[0].trim();let n=s.slice(1).join(" = ").trim(),r="";const o=n.indexOf("#");if(-1!==o&&(r=n.substring(o+1).trim(),n=n.substring(0,o).trim()),n.startsWith("[")&&n.endsWith("]")){const e=n.slice(1,-1).trim();return{type:"Assign",lineno:t,targets:[{type:"Name",id:i}],value:{type:"List",elts:e?e.split(",").map(e=>{const t=e.trim();return/^-?\d+(\.\d+)?$/.test(t)?{type:"Num",n:parseFloat(t)}:t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?{type:"Str",s:t.slice(1,-1)}:{type:"Name",id:t}}):[]}}}const a=n.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\[(\d+)\]$/);if(a){const[,e,s]=a;return{type:"Assign",lineno:t,targets:[{type:"Name",id:i}],value:{type:"Subscript",value:{type:"Name",id:e},slice:{type:"Num",n:parseInt(s)}}}}const c={type:"Assign",lineno:t,targets:[{type:"Name",id:i}],value:this.parseExpression(n)};return r&&(c.inlineComment=r),c}parseExpression(e){const t=e.trim();if("[]"===t)return{type:"List",elts:[],ctx:"Load"};if(t.startsWith("[")&&t.endsWith("]")){const e=t.slice(1,-1).trim();return e?{type:"List",elts:e.split(",").map(e=>{const t=e.trim();return/^\d+$/.test(t)?{type:"Constant",value:parseInt(t),kind:null}:t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?{type:"Constant",value:t.slice(1,-1),kind:null}:(/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(t),{type:"Name",id:t,ctx:"Load"})}),ctx:"Load"}:{type:"List",elts:[],ctx:"Load"}}if(t.startsWith("not ")){const e=t.substring(4).trim();return{type:"UnaryOp",op:{type:"Not"},operand:this.parseExpression(e)}}if(t.startsWith("(")&&t.endsWith(")")){const e=t.slice(1,-1);return{type:"Expr",value:this.parseExpression(e),parenthesized:!0}}const s=["==","!=","<=",">=","<",">"];for(const e of s){const s=t.indexOf(e);if(-1!==s){const i=t.substring(0,s).trim(),n=t.substring(s+e.length).trim();return{type:"Compare",left:this.parseSimpleExpression(i),ops:[this.getCompareOpNode(e)],comparators:[this.parseSimpleExpression(n)]}}}if(t.includes(" and "))return{type:"BoolOp",op:{type:"And"},values:t.split(" and ").map(e=>this.parseExpression(e.trim()))};if(t.includes(" or "))return{type:"BoolOp",op:{type:"Or"},values:t.split(" or ").map(e=>this.parseExpression(e.trim()))};const i=t.match(/^(.+)\.([a-zA-Z_][a-zA-Z0-9_]*)\((.*)\)$/);if(i){const[,e,t,s]=i,n=this.parseArguments(s);return{type:"Call",func:{type:"Attribute",value:this.parseSimpleExpression(e),attr:t,ctx:"Load"},args:n}}const n=t.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\((.*)\)$/);if(n){const[,e,t]=n;return{type:"Call",func:{type:"Name",id:e},args:this.parseArguments(t)}}const r=["//","+","-","*","/","%"];for(const e of r){const s=t.indexOf(e);if(-1!==s){const i=t.substring(0,s).trim(),n=t.substring(s+e.length).trim();return{type:"BinOp",left:this.parseSimpleExpression(i),op:this.getArithOpNode(e),right:this.parseSimpleExpression(n)}}}return this.parseSimpleExpression(t)}parseSimpleExpression(e){const t=e.trim(),s=t.match(/^(.+)\.([a-zA-Z_][a-zA-Z0-9_]*)$/);if(s){const[,e,t]=s;return{type:"Attribute",value:this.parseSimpleExpression(e),attr:t,ctx:"Load"}}const i=t.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\[(.+)\]$/);if(i){const[,e,t]=i;return{type:"Subscript",value:{type:"Name",id:e,ctx:"Load"},slice:this.parseSimpleExpression(t),ctx:"Load"}}return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?{type:"Str",s:t.slice(1,-1)}:t.startsWith('"')&&!t.endsWith('"')||t.startsWith("'")&&!t.endsWith("'")?(this.context.errors.push({message:`Unterminated string literal: ${t}`,line:0,column:0,type:"syntax_error",severity:"error"}),{type:"Str",s:t}):/^-?\d+(\.\d+)?$/.test(t)?{type:"Num",n:parseFloat(t)}:"True"===t||"False"===t?{type:"NameConstant",value:"True"===t}:{type:"Name",id:t}}getCompareOpNode(e){switch(e){case"==":default:return{type:"Eq"};case"!=":return{type:"NotEq"};case"<":return{type:"Lt"};case"<=":return{type:"LtE"};case">":return{type:"Gt"};case">=":return{type:"GtE"}}}getArithOpNode(e){switch(e){case"+":default:return{type:"Add"};case"-":return{type:"Sub"};case"*":return{type:"Mult"};case"/":return{type:"Div"};case"//":return{type:"FloorDiv"};case"%":return{type:"Mod"}}}parsePrintStatement(e,t){const s=e.match(/^print\((.*)\)\s*$/),i=s?s[1]:"";return{type:"Expr",lineno:t,value:{type:"Call",func:{type:"Name",id:"print"},args:[{type:"Str",s:i,raw:i}]}}}visitNode(e){if(!e)return s("statement","",[]);switch(this.statementVisitor.visitNode=this.visitNode.bind(this),this.definitionVisitor.visitNode=this.visitNode.bind(this),e.type){case"Module":return this.visitModule(e);case"Assign":return this.statementVisitor.visitAssign(e);case"AugAssign":return this.statementVisitor.visitAugAssign(e);case"AnnAssign":return this.statementVisitor.visitAnnAssign(e);case"If":return this.statementVisitor.visitIf(e);case"For":return this.statementVisitor.visitFor(e);case"While":return this.statementVisitor.visitWhile(e);case"Return":return this.statementVisitor.visitReturn(e);case"Call":return this.statementVisitor.visitCall(e);case"Expr":return this.statementVisitor.visitExpr(e);case"Comment":return this.statementVisitor.visitComment(e);case"Pass":return this.statementVisitor.visitPass(e);case"Break":return this.statementVisitor.visitBreak(e);case"Continue":return this.statementVisitor.visitContinue(e);case"Import":case"ImportFrom":return this.statementVisitor.visitImport(e);case"Try":return this.statementVisitor.visitTry(e);case"Raise":return this.statementVisitor.visitRaise(e);case"With":return this.statementVisitor.visitWith(e);case"Assert":return this.statementVisitor.visitAssert(e);case"Global":case"Nonlocal":return this.statementVisitor.visitGlobal(e);case"Delete":return this.statementVisitor.visitDelete(e);case"FunctionDef":return this.definitionVisitor.visitFunctionDef(e);case"ClassDef":return this.definitionVisitor.visitClassDef(e);default:return this.createIRNode("comment",`// Unsupported node type: ${e.type}`)}}visitModule(e){const t=[];if(e.body&&Array.isArray(e.body))for(const s of e.body){const e=this.visitNode(s);t.push(e)}return this.createIRNode("compound","",t)}parseFunctionDef(e,t){const s=e.match(/^def\s+(\w+)\s*\(([^)]*)\)\s*(?:->\s*([^:]+))?:\s*$/);if(!s)return{type:"FunctionDef",name:"unknown_function",args:{args:[]},returns:null,body:[],lineno:t};const[,i,n,r]=s;return{type:"FunctionDef",name:i,args:{args:this.parseParameters(n)},returns:r?{type:"Name",id:r.trim()}:null,body:[],lineno:t}}parseArguments(e){return e.trim()?this.splitArgumentsRespectingParentheses(e).map(e=>{const t=e.trim();return t.includes("(")&&t.includes(")")?this.parseExpression(t):t.startsWith('"')&&t.endsWith('"')?{type:"Str",s:t.slice(1,-1)}:/^\d+$/.test(t)?{type:"Num",n:parseInt(t)}:{type:"Name",id:t}}):[]}splitArgumentsRespectingParentheses(e){const t=[];let s="",i=0,n=!1,r="";for(let o=0;o<e.length;o++){const a=e[o];if(n)a!==r||0!==o&&"\\"===e[o-1]||(n=!1,r="");else if('"'===a||"'"===a)n=!0,r=a;else if("("===a)i++;else if(")"===a)i--;else if(","===a&&0===i){t.push(s.trim()),s="";continue}s+=a}return s.trim()&&t.push(s.trim()),t}parseParameters(e){return e.trim()?e.split(",").map(e=>{const t=e.trim(),s=t.match(/^(\w+)\s*:\s*(.+)$/);if(s){const[,e,t]=s;return{arg:e,annotation:{type:"Name",id:t.trim()}}}return{arg:t,annotation:null}}):[]}parseReturnStatement(e,t){const s=e.match(/^return\s*(.*)$/),i=s?s[1].trim():"";return{type:"Return",value:i?{type:"Name",id:i,raw:i}:null,lineno:t}}parseClassDef(e,t){const s=e.match(/^class\s+(\w+)(?:\s*\(([^)]*)\))?\s*:/);if(!s)return this.addError(`Invalid class definition: ${e}`,"syntax_error"),{type:"Unknown",lineno:t};const[,i,n]=s;return{type:"ClassDef",name:i,bases:n?n.split(",").map(e=>({type:"Name",id:e.trim()})):[],body:[],lineno:t}}registerClassDefinition(e){const t=e.name,s=e.body.find(e=>"FunctionDef"===e.type&&"__init__"===e.name),i=[];s&&s.args&&s.args.args&&s.args.args.forEach(e=>{"self"!==e.arg&&i.push(e.arg)});const n=[];e.bases&&e.bases.length>0&&e.bases.forEach(e=>{"Name"===e.type&&n.push(e.id)}),this.context.classDefinitions||(this.context.classDefinitions={}),this.context.classDefinitions[t]={attributes:i,bases:n}}preRegisterAllClasses(e){if(e&&Array.isArray(e))for(const t of e)t&&"ClassDef"===t.type&&this.registerClassDefinition(t)}createIRNode(e,t,i=[],n){return s(e,t,i,n)}createParseResult(e){const t=Date.now()-this.context.startTime;return{ir:e,errors:this.getErrors(),warnings:this.getWarnings(),stats:{parseTime:t,linesProcessed:0,nodesGenerated:e.reduce((e,t)=>e+i(t),0),functionsFound:0,classesFound:0,variablesFound:0},success:0===this.getErrors().length,parseTime:t}}}class u extends n{constructor(e={}){super(e)}parse(e){this.resetContext();const t=this.preprocessSource(e),s=this.parseToIR(t);return s.stats.parseTime=Date.now()-this.context.startTime,s}parseToIR(e){this.context.startTime=Date.now();const t=this.preprocessSource(e),s=(new c).parse(t),n=Date.now()-this.context.startTime;return{ir:s.ir,errors:[...this.context.errors,...s.errors],warnings:[...this.context.warnings,...s.warnings],stats:{parseTime:n,linesProcessed:t.split("\n").length,nodesGenerated:Array.isArray(s.ir)?s.ir.reduce((e,t)=>e+i(t),0):i(s.ir),functionsFound:Array.isArray(s.ir)?s.ir.reduce((e,t)=>e+this.countFunctionsFromIR(t),0):this.countFunctionsFromIR(s.ir),classesFound:Array.isArray(s.ir)?s.ir.reduce((e,t)=>e+this.countClassesFromIR(t),0):this.countClassesFromIR(s.ir),variablesFound:Array.isArray(s.ir)?s.ir.reduce((e,t)=>e+this.countVariablesFromIR(t),0):this.countVariablesFromIR(s.ir)},success:0===this.context.errors.length&&0===s.errors.length,parseTime:n}}preprocessSource(e){return this.preprocess(e)}countFunctionsFromIR(e){let t=0;if("function"!==e.kind&&"procedure"!==e.kind||(t=1),e.children)for(const s of e.children)t+=this.countFunctionsFromIR(s);return t}countClassesFromIR(e){let t=0;if("class"===e.kind&&(t=1),e.children)for(const s of e.children)t+=this.countClassesFromIR(s);return t}countVariablesFromIR(e){let t=0;if("assign"===e.kind&&e.meta?.name&&(t=1),e.children)for(const s of e.children)t+=this.countVariablesFromIR(s);return t}preprocess(e){let t=e;return t=t.replace(/\r\n/g,"\n"),t=t.replace(/\r/g,"\n"),t=t.replace(/\t/g," ".repeat(this.options.indentSize)),t=t.split("\n").map(e=>e.trimEnd()).join("\n"),t=t.replace(/\n\s*\n\s*\n/g,"\n\n"),this.debug(`Preprocessed ${e.split("\n").length} lines`),t}optimizeIR(e){const t=e.children.map(e=>this.optimizeIR(e)).filter(e=>""!==e.text.trim()||"statement"===