UNPKG

pxt-core

Version:

Microsoft MakeCode provides Blocks / JavaScript / Python tools and editors

1 lines • 321 kB
var pxt,pxt,ts,ts,ts,ts,ts,ts,ts,ts,ts,ts,ts,pxt,pxt,ts,ts,ts,ts,ts,ts,ts,ts,ts,ts,ts;!function(e){let t,n=!1;class r{constructor(e){this.db=e}loadAsync(n,r,s,i){if(!/^v\d+\.\d+\.\d+$/.test(r))return i(n,r);const a=`gh-${s}-${n}#${r}`;return t.cacheGet(a).then((s=>{if(s){const t=e.Util.jsonTryParse(s);if(t)return e.debug(`cache hit ${a}`),Promise.resolve(t)}return i(n,r).then((n=>n?(e.debug(`cached ${a}`),t.cacheSet(a,JSON.stringify(n)).then((()=>n))):n))}))}latestVersionAsync(e,t){return this.db.latestVersionAsync(e,t)}loadConfigAsync(e,t){return this.loadAsync(e,t,"pxt",((e,t)=>this.db.loadConfigAsync(e,t)))}loadPackageAsync(e,t){return this.loadAsync(e,t,"pkg",((e,t)=>this.db.loadPackageAsync(e,t)))}loadTutorialMarkdown(e,t){return this.loadAsync(e,t,"tutorial",((e,t)=>this.db.loadTutorialMarkdown(e,t)))}cacheReposAsync(e){return this.db.cacheReposAsync(e)}}class s{constructor(e){this.packageFiles=e}resolve(e,t){return""}readFile(t,n){const r="this"==t.id?n:"pxt_modules/"+t.id+"/"+n;return void 0!==this.packageFiles[r]?this.packageFiles[r]:e.appTarget.bundledpkgs[t.id]?e.appTarget.bundledpkgs[t.id][n]:null}writeFile(t,n,r){const s="this"==t.id?"":"pxt_modules/"+t.id+"/";e.debug(`write file ${s+n}`),this.packageFiles[s+n]=r}getHexInfoAsync(e){return Promise.resolve({hex:["SKIP"]})}cacheStoreAsync(e,n){return(null==t?void 0:t.cacheSet)?t.cacheSet(e,n):Promise.resolve()}cacheGetAsync(e){return(null==t?void 0:t.cacheGet)?t.cacheGet(e):Promise.resolve("")}downloadPackageAsync(r){return n?function(e){const n=null==t?void 0:t.pkgOverrideAsync;return(n?n(e.id):Promise.resolve(void 0)).then((t=>t||e.commonDownloadAsync()))}(r).then((t=>{t&&e.U.iterMap(t,((e,t)=>{this.writeFile(r,e,t)}))})):Promise.resolve()}resolveVersionAsync(e){return Promise.resolve("*")}}function i(t){if(t.target.preferredEditor==e.PYTHON_PROJECT_NAME){const n=e.U.clone(t);n.ast=!0,n.target.preferredEditor=e.JAVASCRIPT_PROJECT_NAME;for(let t of n.sourceFiles)e.U.endsWith(t,".py")&&(n.fileSystem[t.slice(0,-3)+".ts"]=" ");const r=pxtc.compile(n);t.apisInfo=pxtc.getApiInfo(r.ast,n.jres)}}function a(t,n){const r=new s(t),a=new e.MainPackage(r);return a.loadAsync().then((()=>{let e=a.getTargetOptions();return e.hasHex&&(e.isNative=n.native),a.getCompileOptionsAsync(e)})).then((t=>(o(a.targetVersion(),t),a.getPreferredEditor()===e.PYTHON_PROJECT_NAME&&l(a.targetVersion(),t),i(t),t)))}function o(t,n){if(t){e.debug(`applying TS patches relative to ${t}`);for(let r of Object.keys(n.fileSystem))if(-1==r.indexOf("/")&&e.U.endsWith(r,".ts")){const s=n.fileSystem[r],i=e.patching.patchJavaScript(t,s);s!=i&&(e.debug(`applying TS patch to ${r}`),n.fileSystem[r]=i)}}}function l(t,n){if(t){e.debug(`applying PY patches relative to ${t}`);for(let r of Object.keys(n.fileSystem))if(-1==r.indexOf("/")&&e.U.endsWith(r,".py")){const s=n.fileSystem[r],i=e.patching.patchPython(t,s);s!=i&&(e.debug(`applying PY patch to ${r}`),n.fileSystem[r]=i)}}}e.SimpleHost=s,e.prepPythonOptions=i,e.simpleInstallPackagesAsync=function(t){const n=new s(t);return new e.MainPackage(n).loadAsync(!0)},e.simpleGetCompileOptionsAsync=a,e.simpleCompileAsync=function(e,t){return a(e,"boolean"==typeof t?{native:t}:t||{}).then((e=>pxtc.compile(e))).then((e=>(e.success||(e.errors=e.diagnostics.map(ts.pxtc.getDiagnosticString).join("")||"Unknown error."),e)))},e.patchTS=o,e.patchPY=l,e.setupSimpleCompile=function(s){"undefined"==typeof global||global.btoa||(global.btoa=function(e){return Buffer.from(e,"binary").toString("base64")},global.atob=function(e){return Buffer.from(e,"base64").toString("binary")}),"undefined"!=typeof pxtTargetBundle&&(e.debug("setup app bundle"),e.setAppTarget(pxtTargetBundle)),s&&(t=s,n=!0,s.httpRequestAsync&&(e.Util.httpRequestCoreAsync=s.httpRequestAsync),e.github.forceProxy=!0,e.github.db=new r(new e.github.MemoryGithubDb)),e.debug("simple setup done")}}(pxt||(pxt={})),function(e){e.simshim=function(t,n){let r,s=ts.SyntaxKind,i=t.getTypeChecker(),a=e.cpp.nsWriter("declare namespace"),o="";for(let i of t.getSourceFiles()){if(n){let t=n(i.fileName);if(e.debug("SimShim[1]: "+t.dir),!e.U.endsWith(t.dir,"/sim")&&!e.U.startsWith(i.fileName,"sim/"))continue}else if(!e.U.startsWith(i.fileName,"sim/"))continue;e.debug("SimShim[2]: "+i.fileName);for(let e of i.statements){let t=e;e.kind==s.ModuleDeclaration&&"pxsim"==t.name.text&&(r=t,h(t.body))}}let l={};return l[e.appTarget.corepkg]=a.finish(),l;function c(e){let t;return ts.isExpression(e)&&(t=i.getContextualType(e)),t||(t=i.getTypeAtLocation(e)),t}function u(e){let t=i.typeToString(e,r,ts.TypeFormatFlags.UseFullyQualifiedType);switch(t=t.replace(/^pxsim\./,""),t){case"RefAction":return"() => void";case"RefBuffer":return"Buffer";default:return t}}function p(e){let t=pxtc.getComments(e);return/^\s*\/\/%/m.test(t)?t:null}function d(e){let t=p(e);if(!t)return;let n=e.name.getText(),r="//% shim=."+n,s=i.getTypeAtLocation(e);a.write(t),a.write(r),a.write(`public ${n}: ${u(s)};`),a.write("")}function f(e){let t=p(e);if(!t)return;i.getTypeAtLocation(e);let n=e.parameters.map((e=>e.name.getText()+": "+u(c(e))));a.write(t),a.write(`//% shim="new ${o}"`),a.write(`constructor(${n.join(", ")});`),a.write("")}function m(t,n=!1){let r=p(t);if(!r)return;let l=t.name.getText(),d=t.kind==s.MethodDeclaration||t.kind==s.GetAccessor||t.kind==s.SetAccessor,f="//% shim="+(d?"."+l:o+"::"+l),m=i.getSignatureFromDeclaration(t),h=i.getReturnTypeOfSignature(m),g=/Async$/.test(l),b=(x=h,pxtc.isObjectType(x)&&x.objectFlags&ts.ObjectFlags.Reference&&"Promise"==x.symbol.name?x.typeArguments[0]:null);var x;b?(f+=" promise",h=b,g||e.U.userError(`${o}::${l} should be called ${l}Async`)):g&&e.U.userError(`${o}::${l} doesn't return a promise`),e.debug("emitFun: "+l);let y=t.parameters.map((e=>`${e.name.getText()}${e.questionToken?"?":""}: ${u(c(e))}`)),k=l.replace(/Async$/,""),S=d?"public":"function",T=`(${y.join(", ")})`;t.kind==s.GetAccessor&&(S=n?"public":"readonly",T="",f+=" property"),d||a.setNs(o),a.write(r),a.write(f),a.write(`${S} ${k}${T}: ${u(h)};`),a.write("")}function h(e){switch(e.kind){case s.ModuleDeclaration:return function(e){let t=o;o&&(o+="."),o+=e.name.text,h(e.body),o=t}(e);case s.ModuleBlock:return e.statements.forEach(h);case s.FunctionDeclaration:return m(e);case s.ClassDeclaration:return function(e){let t=p(e);if(!t)return;a.setNs(o),a.write(t);let n=o;o&&(o+="."),o+=e.name.text;let r=n?"":"declare",i="";if(e.heritageClauses)for(let t of e.heritageClauses)t.token==s.ExtendsKeyword&&(i=" extends "+u(c(t.types[0])));a.write(`${r} class ${e.name.text}${i} {`),a.incrIndent();for(let t of e.members)switch(t.kind){case s.MethodDeclaration:m(t);break;case s.PropertyDeclaration:d(t);break;case s.Constructor:f(t);break;case s.GetAccessor:let n=e.members.some((e=>e.kind==s.SetAccessor&&e.name.getText()==t.name.getText()));m(t,n)}o=n,a.decrIndent(),a.write("}")}(e)}}}}(pxt||(pxt={})),function(e){!function(t){t.annotate=function(n,r,s){const i=t.target;t.target=s;let a=n.getSourceFiles().filter((e=>e.fileName===r))[0],o=n.getTypeChecker();function l(n,r,s=!1,i=null){let a=s||!(u(n).flags&e.TypeFlags.Void),l=i||c(n);if(n.expression&&l){let e=!1;switch(l.kind){case t.SK.PropertySignature:case t.SK.PropertyAssignment:case t.SK.PropertyDeclaration:t.isStatic(l)||(e=!0);break;case t.SK.Parameter:t.isCtorField(l)&&(e=!0);break;case t.SK.GetAccessor:case t.SK.SetAccessor:case t.SK.MethodDeclaration:case t.SK.MethodSignature:t.isStatic(l)||(e=!0)}if(e){const e=n.expression;e.kind===t.SK.PropertyAccessExpression?r.unshift(e.expression):r.unshift(n.expression)}}let p={decl:l,qName:l?t.getNodeFullName(o,l):"?",args:r,isExpression:a};t.pxtInfo(n).callInfo=p}function c(n){if(!n)return null;let r,s=o.getSymbolAtLocation(n);if(s&&(r=s.valueDeclaration,!r&&s.declarations)){let t=s.declarations[0];t&&t.kind==e.SyntaxKind.ImportEqualsDeclaration&&(s=o.getSymbolAtLocation(t.moduleReference),s&&(r=s.valueDeclaration))}if(!r&&n.kind==t.SK.PropertyAccessExpression){const e=n;r={kind:t.SK.PropertySignature,symbol:{isBogusSymbol:!0,name:e.name.getText()},name:e.name},t.pxtInfo(r).flags|=2}return r}function u(n){let r;const s=t.pxtInfo(n);return s.typeCache?s.typeCache:(e.isExpression(n)&&(r=o.getContextualType(n)),r||(r=o.getTypeAtLocation(n)),r?e.isStringLiteral(n)?r:t.checkType(r):r)}!function n(r){e.forEachChild(r,(r=>{switch(r.kind){case e.SyntaxKind.CallExpression:l(r,r.arguments.slice(0),null,c(r.expression));break;case e.SyntaxKind.PropertyAccessExpression:l(r,[]);break;case e.SyntaxKind.TaggedTemplateExpression:l(r,[r.template],!0,c(r.tag));break;case e.SyntaxKind.BinaryExpression:!function(n){const r=n.left,s=n.right;let i=u(n.left),a=u(n.right);n.operatorToken.kind!=t.SK.PlusToken&&n.operatorToken.kind!=t.SK.PlusEqualsToken||(t.isStringType(i)||t.isStringType(a)&&n.operatorToken.kind==t.SK.PlusToken)&&(t.pxtInfo(n).exprInfo={leftType:o.typeToString(i),rightType:o.typeToString(a)});switch(n.operatorToken.kind){case e.SyntaxKind.EqualsToken:case e.SyntaxKind.PlusEqualsToken:case e.SyntaxKind.MinusEqualsToken:if(r.kind==t.SK.PropertyAccessExpression){let n=c(r);n&&n.kind==t.SK.GetAccessor?(n=e.getDeclarationOfKind(n.symbol,t.SK.SetAccessor),l(r,[s],!1,n)):n&&(n.kind==t.SK.PropertySignature||n.kind==t.SK.PropertyAssignment||t.target&&t.target.switches.slowFields)&&l(r,[s])}}}(r);break;case e.SyntaxKind.Identifier:const n=c(r);if(n&&n.getSourceFile().fileName!==pxt.MAIN_TS&&n.kind==e.SyntaxKind.VariableDeclaration){const e=t.pxtInfo(r);e.flags|=4,e.commentAttrs||(e.commentAttrs=t.parseComments(n))}}n(r)}))}(a),t.target=i}}(e.pxtc||(e.pxtc={}))}(ts||(ts={})),function(e){!function(e){function t(e){let t='"';for(let n=0;n<e.length;++n){let r=255&e.charCodeAt(n),s=String.fromCharCode(r);t+="\\"==s||'"'==s?"\\"+s:"\n"==s?"\\n":r<=15?"\\x0"+r.toString(16):r<32||r>127?"\\x"+r.toString(16):s}return t+'"'}e.asmStringLiteral=t;function n(n){let r="pxt::string_inline_ascii_vt",s=e.target.utf8?e.U.toUTF8(n,!0):n,i="";if(s!==n)if(n.length>16){r="pxt::string_skiplist16_packed_vt";let a=[],o=0;for(let t=0;t+16<=n.length;t+=16)o+=e.U.toUTF8(n.slice(t,t+16),!0).length,a.push(o);i=`\n .short ${s.length}, ${n.length}\n .short ${a.map((e=>e.toString())).join(", ")}\n .string ${t(s)}\n`}else r="pxt::string_inline_utf8_vt";return i||(i=`\n .short ${s.length}\n .string ${t(s)}\n`),{vt:r,asm:i}}function r(e,t=""){return`\n .word ${e.length>>1}${t}\n .hex ${e}${e.length%4==0?"":"00"}\n `}e.AssemblerSnippets=class{nop(){return"TBD(nop)"}reg_gets_imm(e,t){return"TBD(reg_gets_imm)"}proc_setup(e,t){return"TBD(proc_setup)"}push_fixed(e){return"TBD(push_fixed)"}push_local(e){return"TBD(push_local)"}push_locals(e){return"TBD(push_locals)"}pop_fixed(e){return"TBD(pop_fixed)"}pop_locals(e){return"TBD(pop_locals)"}proc_return(){return"TBD(proc_return)"}debugger_stmt(e){return""}debugger_bkpt(e){return""}debugger_proc(e){return""}unconditional_branch(e){return"TBD(unconditional_branch)"}beq(e){return"TBD(beq)"}bne(e){return"TBD(bne)"}cmp(e,t){return"TBD(cmp)"}cmp_zero(e){return"TBD(cmp_zero)"}arithmetic(){return""}load_reg_src_off(e,t,n,r,s,i){return"TBD(load_reg_src_off)"}rt_call(e,t,n){return"TBD(rt_call)"}call_lbl(e,t){return"TBD(call_lbl)"}call_reg(e){return"TBD(call_reg)"}helper_prologue(){return"TBD(lambda_prologue)"}helper_epilogue(){return"TBD(lambda_epilogue)"}pop_clean(e){return"TBD"}load_ptr_full(e,t){return"TBD(load_ptr_full)"}emit_int(e,t){return"TBD(emit_int)"}obj_header(e){return`.word ${e}`}string_literal(e,t){const r=n(t);return`\n .balign 4\n .object ${e}\n ${e}: ${this.obj_header(r.vt)}\n ${r.asm}\n`}hex_literal(e,t){return`\n.balign ${/f{16}/i.test(t)?8:4}\n.object ${e}\n${e}: ${this.obj_header("pxt::buffer_vt")}\n${r(t)}\n`}},e.utf8AsmStringLiteral=n,e.hexLiteralAsm=r,e.numBytes=function(e){let t=0;for(let n=e;n>0;n>>>=8)t++;return t||1};e.ProctoAssembler=class{constructor(t,n,r){this.resText="",this.exprStack=[],this.calls=[],this.proc=null,this.baseStackSize=0,this.labelledHelpers={},this.write=t=>{this.resText+=e.asmline(t)},this.t=t,this.bin=n,this.proc=r,this.proc&&this.work()}emitHelpers(){this.emitLambdaTrampoline(),this.emitArrayMethods(),this.emitFieldMethods(),this.emitBindHelper()}redirectOutput(t){let n=this.write,r="";this.write=t=>r+=e.asmline(t);try{t()}finally{this.write=n}return r}stackSize(){return this.baseStackSize+this.exprStack.length}stackAlignmentNeeded(t=0){if(!e.target.stackAlign)return 0;let n=e.target.stackAlign-(this.stackSize()+t&e.target.stackAlign-1);return n==e.target.stackAlign?0:n}getAssembly(){return this.resText}work(){this.write(`\n;\n; Function ${this.proc.getFullName()}\n;\n`);let t=this.proc.label();this.write(`.object ${t} ${JSON.stringify(this.proc.getFullName())}`);let n=t+"_pre",r=t+"_bkpt",s=t+"_locals",i=t+"_end";this.write(`${n}:`),this.emitLambdaWrapper(this.proc.isRoot),this.write(".section code"),this.write(`${t}:`),this.proc.classInfo&&this.proc.info.thisParameter&&!e.target.switches.skipClassCheck&&!e.target.switches.noThisCheckOpt&&(this.write("mov r7, lr"),this.write("ldr r0, [sp, #0]"),this.emitInstanceOf(this.proc.classInfo,"validate"),this.write("mov lr, r7")),this.write(`\n${t}_nochk:\n @stackmark func\n @stackmark args\n`),this.proc.fillDebugInfo=t=>{let a=t.getLabels();this.proc.debugInfo={locals:(1==this.proc.seqNo?this.bin.globals:this.proc.locals).map((e=>e.getDebugInfo())),args:this.proc.args.map((e=>e.getDebugInfo())),name:this.proc.getName(),codeStartLoc:e.U.lookup(a,s),codeEndLoc:e.U.lookup(a,i),bkptLoc:e.U.lookup(a,r),localsMark:e.U.lookup(t.stackAtLabel,s),idx:this.proc.seqNo,calls:this.calls,size:e.U.lookup(a,i)+2-e.U.lookup(a,n)};for(let n of this.calls)n.addr=e.U.lookup(a,n.callLabel),n.stack=e.U.lookup(t.stackAtLabel,n.callLabel),n.callLabel=void 0;for(let n=0;n<this.proc.body.length;++n){let r=this.proc.body[n].breakpointInfo;if(r){let n=e.U.lookup(t.stackAtLabel,`__brkp_${r.id}`);n!==this.proc.debugInfo.localsMark&&(pxt.log(r),pxt.log(t.stackAtLabel),e.U.oops(`offset doesn't match: ${n} != ${this.proc.debugInfo.localsMark}`))}}},this.bin.breakpoints&&this.write(this.t.debugger_proc(r)),this.baseStackSize=1;let a=this.proc.locals.length;this.write("push {lr}"),this.write(".locals:\n"),this.proc.perfCounterNo&&(this.write(this.t.emit_int(this.proc.perfCounterNo,"r0")),this.write("bl pxt::startPerfCounter")),this.write(this.t.proc_setup(a)),this.baseStackSize+=a,this.write("@stackmark locals"),this.write(`${s}:`);for(let t=0;t<this.proc.body.length;++t){let n=this.proc.body[t];switch(n.stmtKind){case e.ir.SK.Expr:this.emitExpr(n.expr);break;case e.ir.SK.StackEmpty:if(this.exprStack.length>0){for(let e of this.proc.body.slice(t-4,t+1))pxt.log(`PREVSTMT ${e.toString().trim()}`);for(let e of this.exprStack)pxt.log(`EXPRSTACK ${e.currUses}/${e.totalUses} E: ${e.toString()}`);e.oops("stack should be empty")}this.write("@stackempty locals");break;case e.ir.SK.Jmp:this.emitJmp(n);break;case e.ir.SK.Label:this.write(n.lblName+":"),this.validateJmpStack(n);break;case e.ir.SK.Comment:this.write(`; ${n.expr.data}`);break;case e.ir.SK.Breakpoint:if(this.bin.breakpoints){let e=`__brkp_${n.breakpointInfo.id}`;n.breakpointInfo.isDebuggerStmt?this.write(this.t.debugger_stmt(e)):this.write(this.t.debugger_bkpt(e))}break;default:e.oops()}}e.assert(0<=a&&a<127),a>0&&this.write(this.t.pop_locals(a)),this.proc.perfCounterNo&&(this.write("mov r4, r0"),this.write(this.t.emit_int(this.proc.perfCounterNo,"r0")),this.write("bl pxt::stopPerfCounter"),this.write("mov r0, r4")),this.write(`${i}:`),this.write(this.t.proc_return()),this.write("@stackempty func"),this.write("@stackempty args"),this.write("; endfun")}mkLbl(e){let t=e+this.bin.lblNo++;return"_"!=t[0]&&(t="."+t),t}dumpStack(){let e="[";for(let t of this.exprStack)e+=t.sharingInfo()+": "+t.toString()+"; ";return e+="]",e}terminate(t){e.assert(t.exprKind==e.ir.EK.SharedRef);let n=t.args[0];e.U.assert(n.currUses!=n.totalUses),e.U.assert(this.exprStack[0]===n,"term at top");let r=1;for(;r<this.exprStack.length;){let e=this.exprStack[r];if(e.currUses!=e.totalUses)break;r++}return this.write(`@dummystack ${r}`),this.write(this.t.pop_locals(r)),r}validateJmpStack(t,n=0){let r=this.exprStack.length-n;null==t.lblStackSize?t.lblStackSize=r:t.lblStackSize!=r&&(pxt.log(t.lblStackSize,r),pxt.log(this.dumpStack()),e.U.oops("stack misaligned at: "+t.lblName))}emitJmp(t){let n=0;if(t.jmpMode==e.ir.JmpMode.Always)t.expr&&this.emitExpr(t.expr),t.terminateExpr&&(n=this.terminate(t.terminateExpr)),this.write(this.t.unconditional_branch(t.lblName)+" ; with expression");else{let r=this.mkLbl("jmpz");this.emitExpr(t.expr),(t.expr.exprKind!=e.ir.EK.RuntimeCall||"thumb::subs"!==t.expr.data&&!e.U.startsWith(t.expr.data,"_cmp_"))&&this.write(this.t.cmp_zero("r0")),t.jmpMode==e.ir.JmpMode.IfNotZero?this.write(this.t.beq(r)):this.write(this.t.bne(r)),t.terminateExpr&&(n=this.terminate(t.terminateExpr)),this.write(this.t.unconditional_branch(t.lblName)),this.write(r+":")}this.validateJmpStack(t.lbl,n)}clearStack(e=!1){let t=0;for(;this.exprStack.length>0&&this.exprStack[0].currUses==this.exprStack[0].totalUses;)t++,this.exprStack.shift();if(t&&this.write(this.t.pop_locals(t)),!e){let e=this.exprStack.filter((e=>e.currUses==e.totalUses&&-1!=e.irCurrUses));if(e.length>0){this.write(this.t.reg_gets_imm("r7",0));for(let t of e)t.irCurrUses=-1,this.write(this.loadFromExprStack("r7",t,0,!0))}}}emitExprInto(t,n){switch(t.exprKind){case e.ir.EK.NumberLiteral:"number"==typeof t.data?this.write(this.t.emit_int(t.data,n)):e.oops();break;case e.ir.EK.PointerLiteral:this.write(this.t.load_ptr_full(t.data,n));break;case e.ir.EK.SharedRef:let r=t.args[0];e.U.assert(!!r.currUses),e.U.assert(r.currUses<r.totalUses),r.currUses++;let s=this.exprStack.indexOf(r);if(e.U.assert(s>=0),0==s&&r.totalUses==r.currUses)this.write(this.t.pop_fixed([n])+` ; tmpref @${this.exprStack.length}`),this.exprStack.shift(),this.clearStack();else{let e=s.toString()+":"+this.exprStack.length;this.write(this.t.load_reg_src_off(n,"sp",e,!0)+" ; tmpref @"+(this.exprStack.length-s))}break;case e.ir.EK.CellRef:let i=t.data;if(i.isGlobal()){let e=this.bitSizeInfo(i.bitSize),t="#"+i.index;(e.needsSignExt||i.index>=e.immLimit)&&(this.write(this.t.emit_int(i.index,n)),t=n),this.write(this.t.load_reg_src_off("r7","r6","#0")),this.write(this.t.load_reg_src_off(n,"r7",t,!1,!1,e))}else{let[e,t,r]=this.cellref(i);this.write(this.t.load_reg_src_off(n,e,t,r))}break;default:e.oops()}}bitSizeInfo(t){let n={size:e.sizeOfBitSize(t),immLimit:128};return 1==n.size?n.immLimit=32:2==n.size&&(n.immLimit=64),1!=t&&3!=t||(n.needsSignExt=!0),n}emitExpr(t){switch(t.exprKind){case e.ir.EK.JmpValue:this.write("; jmp value (already in r0)");break;case e.ir.EK.Nop:this.write(this.t.nop());break;case e.ir.EK.FieldAccess:return this.emitExpr(t.args[0]),this.emitFieldAccess(t);case e.ir.EK.Store:return this.emitStore(t.args[0],t.args[1]);case e.ir.EK.RuntimeCall:return this.emitRtCall(t);case e.ir.EK.ProcCall:return this.emitProcCall(t);case e.ir.EK.SharedDef:return this.emitSharedDef(t);case e.ir.EK.Sequence:return t.args.forEach((e=>this.emitExpr(e))),this.clearStack();case e.ir.EK.InstanceOf:return this.emitExpr(t.args[0]),this.emitInstanceOf(t.data,t.jsInfo);default:return this.emitExprInto(t,"r0")}}emitFieldAccess(t,n=!1){let r=t.data,s=(n?"st":"ld")+"fld_"+r.classInfo.id+"_"+r.name;r.needsCheck&&!e.target.switches.skipClassCheck&&(this.emitInstanceOf(r.classInfo,"validate"),s+="_chk");let i=4*r.idx+4,a="#"+i;i>124&&(this.write(this.t.emit_int(i,"r3")),a="r3"),n?this.write(`str r1, [r0, ${a}]`):this.write(`ldr r0, [r0, ${a}]`)}writeFailBranch(){this.write(".fail:"),this.write("mov r1, lr"),this.write(this.t.callCPP("pxt::failedCast"))}emitClassCall(t){let n=t.virtualIndex+e.firstMethodOffset();this.write(this.t.emit_int(4*n,"r1"));let r=t.classInfo,s="";t.isThis&&(s+="_this"),this.emitLabelledHelper("classCall_"+r.id+s,(()=>{this.write("ldr r0, [sp, #0] ; ld-this"),this.loadVTable(),e.target.switches.skipClassCheck||t.isThis||this.checkSubtype(r),this.write("ldr r1, [r3, r1] ; ld-method"),this.write("bx r1 ; keep lr from caller"),this.writeFailBranch()}))}helperObject(e){return`.object _pxt_helper_${e.replace(/[^\w]+/g,"_")} "helper: ${e}"`}emitBindHelper(){this.write(`\n ${this.helperObject("bind")}\n .section code\n _pxt_bind_helper:\n push {r0, r2}\n movs r0, #2\n ldlit r1, _pxt_bind_lit\n ${this.t.callCPP("pxt::mkAction")}\n pop {r1, r2}\n str r1, [r0, #12]\n str r2, [r0, #16]\n bx r4 ; return\n\n _pxt_bind_lit:\n ${this.t.obj_header("pxt::RefAction_vtable")}\n .short 0, 0 ; no captured vars\n .word .bindCode@fn\n .bindCode:\n ; r0-bind object, r4-#args\n cmp r4, #12\n bge .fail\n lsls r3, r4, #2\n ldlit r2, _pxt_copy_list\n ldr r1, [r2, r3]\n\n ldr r3, [r0, #12]\n ldr r2, [r0, #16]\n adds r4, r4, #1\n bx r1\n `),this.writeFailBranch(),this.write("_pxt_copy_list:"),this.write(e.U.range(12).map((e=>`.word _pxt_bind_${e}@fn`)).join("\n"));for(let e=0;e<12;e++){this.write(`\n _pxt_bind_${e}:\n sub sp, #4\n `);for(let t=0;t<e;++t)this.write(`ldr r1, [sp, #4*${t+1}]`),this.write(`str r1, [sp, #4*${t}]`);this.write(`\n push {r3} ; this-ptr\n mov r1, lr\n str r1, [sp, #4*${e+1}] ; store LR\n blx r2\n ldr r1, [sp, #4*${e+1}]\n add sp, #8\n bx r1\n `)}}ifaceCallCore(t,n,r=!1){this.write("\n ldr r2, [r3, #12] ; load mult\n movs r7, r2\n beq .objlit ; built-in types have mult=0\n muls r7, r1\n lsrs r7, r2\n lsls r7, r7, #1 ; r7 - hash offset\n ldr r3, [r3, #4] ; iface table\n adds r3, r3, r7\n ; r0-this, r1-method idx, r2-free, r3-hash entry, r4-num args, r7-free\n ");for(let t=0;t<e.vtLookups;++t)t>0&&this.write(" adds r3, #2"),this.write("\n ldrh r2, [r3, #0] ; r2-offset of descriptor\n ldrh r7, [r2, r3] ; r7-method idx\n cmp r7, r1\n beq .hit\n ");"get"==n?(this.write("movs r0, #0 ; undefined"),this.write("bx lr")):this.write("b .fail2"),this.write("\n .hit:\n adds r3, r3, r2 ; r3-descriptor\n ldr r2, [r3, #4]\n lsls r7, r2, #31\n beq .field\n ");const s=this.t.emit_int(t,"r4")+"\n bx r2";if("set"==n?this.write(`\n ; check for next descriptor\n ldrh r7, [r3, #8]\n cmp r7, r1\n bne .fail2 ; no setter!\n ldr r2, [r3, #12]\n ${s}\n `):(this.write("\n ; check if it's getter\n ldrh r7, [r3, #2]\n cmp r7, #1\n "),"get"==n?this.write(`\n bne .bind\n ${s}\n .bind:\n mov r4, lr\n bl _pxt_bind_helper\n `):this.write(`\n beq .doublecall\n ${s}\n .doublecall:\n ; call getter\n movs r4, #1\n push {r0, lr}\n blx r2\n pop {r1, r2}\n mov lr, r2\n b .moveArgs\n `)),r||(this.write(`\n .objlit:\n ldrh r2, [r3, #8]\n cmp r2, #${pxt.BuiltInType.RefMap}\n bne .fail\n mov r4, lr\n `),"set"==n&&this.write("ldr r2, [sp, #4] ; ld-val"),this.write(this.t.callCPP("set"==n?"pxtrt::mapSet":"pxtrt::mapGet")),n?this.write("bx r4"):(this.write("mov lr, r4"),this.write("b .moveArgs"))),this.write(".field:"),"set"==n?this.write("\n ldr r3, [sp, #4] ; ld-val\n str r3, [r0, r2] ; store field\n bx lr\n "):"get"==n?this.write("\n ldr r0, [r0, r2] ; load field\n bx lr\n "):this.write("\n ldr r0, [r0, r2] ; load field\n "),!n){this.write(".moveArgs:");for(let e=0;e<t;++e)e==t-1?this.write("movs r1, r0"):this.write(`ldr r1, [sp, #4*${e+1}]`),this.write(`str r1, [sp, #4*${e}]`);this.lambdaCall(t-1)}r&&this.write(".objlit:"),this.writeFailBranch(),this.write(`\n .fail2:\n ${this.t.callCPP("pxt::missingProperty")}\n `)}emitIfaceCall(t,n,r=""){e.U.assert(t.ifaceIndex>0),this.write(this.t.emit_int(t.ifaceIndex,"r1")),this.emitLabelledHelper("ifacecall"+n+"_"+r,(()=>{this.write("ldr r0, [sp, #0] ; ld-this"),this.loadVTable(),this.ifaceCallCore(n,r)}))}checkSubtype(e,t=".fail",n="r2"){e.classNo?(this.write(`ldrh ${n}, [r3, #8]`),this.write(`cmp ${n}, #${e.classNo}`),e.classNo==e.lastSubtypeNo?this.write(`bne ${t}`):(this.write(`blt ${t}`),this.write(`cmp ${n}, #${e.lastSubtypeNo}`),this.write(`bgt ${t}`))):this.write(`b ${t} ; always fails; class never instantiated`)}loadVTable(e="r2",t=".fail",n=".fail"){this.write(`lsls ${e}, r0, #30`),this.write(`bne ${t}`),this.write("cmp r0, #0"),this.write(`beq ${n}`),this.write("ldr r3, [r0, #0]"),this.write("; vtable in R3")}emitInstanceOf(t,n){let r="inst_"+t.id+"_"+n;this.emitLabelledHelper(r,(()=>{"validateNullable"==n?this.loadVTable("r2",".tagged",".undefined"):this.loadVTable("r2",".fail",".fail"),this.checkSubtype(t),"bool"==n?(this.write(`movs r0, #${e.taggedTrue}`),this.write("bx lr"),this.write(".fail:"),this.write(`movs r0, #${e.taggedFalse}`),this.write("bx lr")):"validate"==n?(this.write("bx lr"),this.writeFailBranch()):"validateNullable"==n?(this.write(".undefined:"),this.write("bx lr"),this.write(".tagged:"),this.write(`cmp r0, #${e.taggedNull} ; check for null`),this.write("bne .fail"),this.write("movs r0, #0"),this.write("bx lr"),this.writeFailBranch()):e.U.oops()}))}emitSharedDef(t){let n=t.args[0];if(e.U.assert(n.totalUses>=1),e.U.assert(0===n.currUses),n.currUses=1,1==n.totalUses)return this.emitExpr(n);this.emitExpr(n),this.exprStack.unshift(n),this.write(this.t.push_local("r0")+"; tmpstore @"+this.exprStack.length)}clearArgs(t,n){t.length,n.length;let r=t.concat(n);for(let t of r)0==t.currUses&&1==t.totalUses||(pxt.log(t.toString()),pxt.log(r.map((e=>e.toString()))),e.U.oops(`wrong uses: ${t.currUses} ${t.totalUses}`)),t.currUses=1;this.clearStack()}builtInClassNo(e){return{id:"builtin"+e,classNo:e,lastSubtypeNo:e}}emitBeginTry(e){this.emitExprInto(e.args[0],"r0"),this.write("bl _pxt_save_exception_state")}emitRtCall(t,n=null){let r=t.data;if("pxt::beginTry"==r)return this.emitBeginTry(t);let s=t.mask||{refMask:0},i=s.conversions||[],a=t.args.map(((e,t)=>({idx:t,expr:e,isSimple:e.isLiteral(),isRef:0!=(s.refMask&1<<t),conv:i.find((e=>e.argIdx==t))})));e.U.assert(a.length<=4);let o=!1;for(let t of e.U.reversed(a))t.expr.isPure()?t.isSimple||t.isRef||o&&!t.expr.isStateless()||(t.isSimple=!0):o=!0;for(let e of a)e.conv&&(e.isSimple=!1);let l=a.filter((e=>!e.isSimple));if(l.every((e=>e.expr.isPure()&&!e.isRef&&!e.conv))){for(let e of l)e.isSimple=!0;l=[]}let c=l[0],u=!0;if(1!=l.length||c.conv||c.isRef){for(let e of l)this.pushArg(e.expr);this.alignExprStack(0);let t=l.filter((e=>!!e.conv));if(t.length){const n=this.redirectOutput((()=>{let n=0;e.target.switches.inlineConversions||(this.t.stackAligned()?n+=2:n+=1);for(let r of t){if(e.isThumb()&&"pxt::toInt"==r.conv.method){this.write(this.loadFromExprStack("r0",r.expr,n)),this.write("asrs r0, r0, #1");let t=e.target.switches.inlineConversions?r.expr.getId():n;this.write("bcs .isint"+t),this.write("lsls r0, r0, #1"),this.alignedCall(r.conv.method,"",n),this.write(".isint"+t+":"),this.write(this.t.push_fixed(["r0"]))}else this.write(this.loadFromExprStack("r0",r.expr,n)),r.conv.refTag?e.target.switches.skipClassCheck||this.emitInstanceOf(this.builtInClassNo(r.conv.refTag),r.conv.refTagNullable?"validateNullable":"validate"):(this.alignedCall(r.conv.method,"",n),r.conv.returnsRef&&this.write(this.loadFromExprStack("r0",r.expr,n,!0))),this.write(this.t.push_fixed(["r0"]));n++}for(let r of e.U.reversed(t))n--,this.write(this.t.pop_fixed(["r"+r.idx]));for(let e of l)e.conv||this.write(this.loadFromExprStack("r"+e.idx,e.expr,n))}));e.target.switches.inlineConversions?this.write(n):this.emitHelper(this.t.helper_prologue()+n+this.t.helper_epilogue(),"conv")}else for(let e of l)this.write(this.loadFromExprStack("r"+e.idx,e.expr))}else this.emitExpr(c.expr),0!=c.idx&&this.write(this.t.mov("r"+c.idx,"r0")),u=!1;for(let e of a)e.isSimple&&this.emitExprInto(e.expr,"r"+e.idx);n?n():"langsupp::ignore"!=r&&this.alignedCall(r,"",0,!0),u&&this.clearArgs(l.filter((e=>!e.isRef)).map((e=>e.expr)),l.filter((e=>e.isRef)).map((e=>e.expr)))}alignedCall(t,n="",r=0,s=!1){(e.U.startsWith(t,"_cmp_")||e.U.startsWith(t,"_pxt_"))&&(s=!1),this.write(this.t.call_lbl(t,s,this.stackAlignmentNeeded(r))+n)}emitLabelledHelper(e,t){if(this.labelledHelpers[e])this.write(this.t.call_lbl(this.labelledHelpers[e]));else{let n=this.redirectOutput(t);this.emitHelper(n,e),this.labelledHelpers[e]=this.bin.codeHelpers[n]}}emitHelper(e,t="hlp"){if(!this.bin.codeHelpers[e]){let n=Object.keys(this.bin.codeHelpers).length;this.bin.codeHelpers[e]=`_${t}_${n}`}this.write(this.t.call_lbl(this.bin.codeHelpers[e]))}pushToExprStack(e){e.totalUses=1,e.currUses=0,this.exprStack.unshift(e)}pushArg(e){this.clearStack(!0);this.exprStack.length;this.emitExpr(e),this.clearStack(!0),this.write(this.t.push_local("r0")+" ; proc-arg"),this.pushToExprStack(e)}loadFromExprStack(t,n,r=0,s=!1){let i=this.exprStack.indexOf(n);return e.assert(i>=0),this.t.load_reg_src_off(t,"sp",(i+r).toString(),!0,s)+" ; estack\n"}pushDummy(){let t=e.ir.numlit(0);t.totalUses=1,t.currUses=1,this.exprStack.unshift(t)}alignExprStack(e){let t=this.stackAlignmentNeeded(e);if(t)for(let e=0;e<t;++e)this.write("push {r5} ; align"),this.pushDummy()}emitFieldMethods(){for(let t of["get","set"]){this.write(`\n ${this.helperObject(t)}\n .section code\n _pxt_map_${t}:\n `),this.loadVTable("r4"),this.checkSubtype(this.builtInClassNo(pxt.BuiltInType.RefMap),".notmap","r4"),this.write(this.t.callCPPPush("set"==t?"pxtrt::mapSetByString":"pxtrt::mapGetByString")),this.write(".notmap:");let n="set"==t?2:1,r=!1;this.write("mov r4, r3 ; save VT"),"set"==t?(e.target.stackAlign&&(r=!0,this.write("push {lr} ; align")),this.write("\n push {r0, r2, lr}\n mov r0, r1\n ")):this.write("\n push {r0, lr}\n mov r0, r1\n "),this.write("\n bl pxtrt::lookupMapKey\n mov r1, r0 ; put key index in r1\n ldr r0, [sp, #0] ; restore obj pointer\n mov r3, r4 ; restore vt\n bl .dowork\n "),this.write(this.t.pop_locals(n+(r?1:0))),this.write("pop {pc}"),this.write(".dowork:"),this.ifaceCallCore(n,t,!0)}}emitArrayMethod(t,n){this.write(`\n ${this.helperObject(t+" "+(n?"buffer":"array"))}\n .section code\n _pxt_${n?"buffer":"array"}_${t}:\n `),this.loadVTable("r4");let r=this.builtInClassNo(n?pxt.BuiltInType.BoxedBuffer:pxt.BuiltInType.RefCollection);e.target.switches.skipClassCheck||this.checkSubtype(r,".fail","r4");const s=e.isStackMachine()||e.target.runtimeIsARM||n?"ldr":"ldrh";this.write(`\n asrs r1, r1, #1\n bcc .notint\n ${s} r4, [r0, #${n?4:8}]\n cmp r1, r4\n bhs .oob\n `);let i="r1";n?(i="#8",this.write("\n adds r4, r0, r1\n ")):this.write("\n lsls r1, r1, #2\n ldr r4, [r0, #4]\n ");let a=n?"b":"",o=n&&"get"==t?"lsls r0, r0, #1\nadds r0, #1":"";"set"==t?this.write(`\n str${a} r2, [r4, ${i}]\n bx lr\n `):this.write(`\n ldr${a} r0, [r4, ${i}]\n ${o}\n bx lr\n `),this.write(`\n .notint:\n lsls r1, r1, #1\n ${this.t.pushLR()}\n push {r0, r2}\n mov r0, r1\n ${this.t.callCPP("pxt::toInt")}\n mov r1, r0\n pop {r0, r2}\n .doop:\n ${this.t.callCPP(`Array_::${t}At`)}\n ${o}\n ${this.t.popPC()}\n `),this.writeFailBranch(),"get"==t?this.write(`\n .oob:\n movs r0, #${n?1:0} ; 0 or undefined\n bx lr\n `):this.write(`\n .oob:\n ${this.t.pushLR()}\n b .doop\n `)}emitArrayMethods(){for(let e of["get","set"])this.emitArrayMethod(e,!0),this.emitArrayMethod(e,!1)}emitLambdaTrampoline(){let t=e.target.stackAlign?"r3,":"";this.write(`\n ${this.helperObject("trampoline")}\n .section code\n _pxt_lambda_trampoline:\n push {${t} r4, r5, r6, r7, lr}\n mov r4, r8\n mov r5, r9\n mov r6, r10\n mov r7, r11\n push {r4, r5, r6, r7} ; save high registers\n mov r4, r1\n mov r5, r2\n mov r6, r3\n mov r7, r0\n `),this.emitInstanceOf(this.builtInClassNo(pxt.BuiltInType.RefAction),"validate"),this.write(`\n mov r0, sp\n push {r4, r5, r6, r7} ; push args and the lambda\n mov r1, sp\n bl pxt::pushThreadContext\n mov r6, r0 ; save ctx or globals\n mov r5, r7 ; save lambda for closure\n mov r0, r5 ; also save lambda pointer in r0 - needed by pxt::bindMethod\n ldr r1, [r5, #8] ; ld fnptr\n movs r4, #3 ; 3 args\n blx r1 ; execute the actual lambda\n mov r7, r0 ; save result\n @dummystack 4\n add sp, #4*4 ; remove arguments and lambda\n mov r0, r6 ; or pop the thread context\n bl pxt::popThreadContext\n mov r0, r7 ; restore result\n pop {r4, r5, r6, r7} ; restore high registers\n mov r8, r4\n mov r9, r5\n mov r10, r6\n mov r11, r7\n pop {${t} r4, r5, r6, r7, pc}`),this.write(`\n ${this.helperObject("exn")}\n .section code\n ; r0 - try frame\n ; r1 - handler PC\n _pxt_save_exception_state:\n push {r0, lr}\n ${this.t.callCPP("pxt::beginTry")}\n pop {r1, r4}\n str r1, [r0, #1*4] ; PC\n mov r1, sp\n str r1, [r0, #2*4] ; SP\n str r5, [r0, #3*4] ; lambda ptr\n bx r4\n `),this.write("\n .section code\n ; r0 - try frame\n ; r1 - thread context\n _pxt_restore_exception_state:\n mov r6, r1\n ldr r1, [r0, #2*4] ; SP\n mov sp, r1\n ldr r5, [r0, #3*4] ; lambda ptr\n ldr r1, [r0, #1*4] ; PC\n movs r0, #1\n orrs r1, r0\n bx r1\n "),this.write(`\n ${this.helperObject("stringconv")}\n .section code\n _pxt_stringConv:\n `),this.loadVTable(),this.checkSubtype(this.builtInClassNo(pxt.BuiltInType.BoxedString),".notstring"),this.write(`\n bx lr\n\n .notstring: ; no string, but vtable in r3\n ldr r7, [r3, #4*${e.firstMethodOffset()-1}]\n cmp r7, #0\n beq .fail\n push {r0, lr}\n movs r4, #1\n blx r7\n str r0, [sp, #0]\n b .numops\n\n .fail: ; not an object or no toString\n push {r0, lr}\n .numops:\n ${this.t.callCPP("numops::toString")}\n pop {r1}\n pop {pc}\n `)}emitProcCall(t){let n=[],r=null,s="",i=t.data;if(i.proc&&i.proc.inlineBody)return this.emitExpr(i.proc.inlineSelf(t.args));let a=-1==i.virtualIndex,o=!1;for(let r of e.U.reversed(t.args)){if(r.isPure()){if(!o||r.isStateless())continue}else o=!0;n.push(r)}if(n.reverse(),n.length<=1){let e=n[0];e&&(r=e,this.clearStack(!0),this.emitExpr(e),e==t.args[t.args.length-1]?s="r0":(s="r3",this.write(this.t.mov("r3","r0")))),n=[]}else for(let e of n)this.pushArg(e);this.alignExprStack(t.args.length);let l=["r1","r2","r3","r4"],c=[];if(n.length){let e=-1;for(let t of n)e=Math.max(this.exprStack.indexOf(t),e);if(e++,e<=l.length){l=l.slice(0,e),this.write(this.t.pop_fixed(l)),c=this.exprStack.splice(0,e);let t=[];for(let r=e-1;r>=0;--r)n.indexOf(c[r])<0&&(t.push(l[r]),this.exprStack.unshift(c[r]));t.length&&this.write(this.t.push_fixed(t))}else l=null,this.write(this.t.reg_gets_imm("r7",0))}let u=e.U.reversed(t.args);a&&u.unshift(u.pop());for(let t of u)if(n.indexOf(t)>=0){if(l)this.write(this.t.push_fixed([l[c.indexOf(t)]]));else{this.write(this.loadFromExprStack("r0",t)),this.write(this.t.push_local("r0")+" ; re-push"),this.write(this.loadFromExprStack("r7",t,1,!0));let n=this.exprStack.indexOf(t),r=e.ir.numlit(0);r.currUses=1,r.totalUses=1,this.exprStack[n]=r}this.exprStack.unshift(t)}else t===r?(this.write(this.t.push_local(s)+" ; the one arg"),this.pushToExprStack(t)):this.pushArg(t);let p=this.mkLbl("_proccall"),d=-1;if(a){let e=t.args.length-1;this.write(this.loadFromExprStack("r0",t.args[0])),this.emitLabelledHelper("lambda_call"+e,(()=>{this.lambdaCall(e),this.writeFailBranch()}))}else if(null!=i.virtualIndex||null!=i.ifaceIndex)null!=i.ifaceIndex?i.isSet?(e.assert(2==t.args.length),this.emitIfaceCall(i,t.args.length,"set")):this.emitIfaceCall(i,t.args.length,i.noArgs?"get":""):this.emitClassCall(i),this.write(p+":");else{let e=i.proc;d=e.seqNo,this.write(this.t.call_lbl(e.label()+(i.isThis?"_nochk":""))),this.write(p+":")}this.calls.push({procIndex:d,stack:0,addr:0,callLabel:p}),a&&t.args[0].isStateless()?this.clearArgs([t.args[0]],t.args.slice(1)):this.clearArgs([],t.args)}lambdaCall(t){this.write("; lambda call"),this.loadVTable(),e.target.switches.skipClassCheck||this.checkSubtype(this.builtInClassNo(pxt.BuiltInType.RefAction)),this.write(`\n movs r4, #${t}\n ldrh r1, [r0, #4]\n cmp r1, #0\n bne .pushR5\n ldr r1, [r0, #8]\n bx r1 ; keep lr from the caller\n .pushR5:\n sub sp, #8\n `);for(let e=0;e<t;++e)this.write(`ldr r1, [sp, #4*${e+2}]`),this.write(`str r1, [sp, #4*${e}]`);this.write(`\n str r5, [sp, #4*${t}]\n mov r1, lr\n str r1, [sp, #4*${t+1}]\n mov r5, r0\n ldr r7, [r5, #8]\n blx r7 ; exec actual lambda\n ldr r4, [sp, #4*${t+1}] ; restore what was in LR\n ldr r5, [sp, #4*${t}] ; restore lambda ctx\n `);for(let e=0;e<t;++e)this.write(`ldr r1, [sp, #4*${e}]`),this.write(`str r1, [sp, #4*${e+2}]`);this.write("\n add sp, #8\n bx r4\n "),this.write("; end lambda call")}emitStore(t,n){switch(t.exprKind){case e.ir.EK.CellRef:let r=t.data;if(this.emitExpr(n),r.isGlobal()){let e=this.bitSizeInfo(r.bitSize),t="#"+r.index;r.index>=e.immLimit&&(this.write(this.t.emit_int(r.index,"r1")),t="r1"),this.write(this.t.load_reg_src_off("r7","r6","#0")),this.write(this.t.load_reg_src_off("r0","r7",t,!1,!0,e))}else{let[e,t,n]=this.cellref(r);this.write(this.t.load_reg_src_off("r0",e,t,n,!0))}break;case e.ir.EK.FieldAccess:this.emitRtCall(e.ir.rtcall("dummy",[t.args[0],n]),(()=>this.emitFieldAccess(t,!0)));break;default:e.oops()}}cellref(t){if(t.isGlobal())throw e.oops();if(t.iscap){let n=t.index+3;return e.assert(0<=n&&n<32),["r5",n.toString(),!0]}if(t.isarg){return["sp","args@"+t.index.toString()+":"+this.baseStackSize,!1]}return["sp","locals@"+t.index,!1]}emitLambdaWrapper(e){if(this.write(""),this.write(".section code"),this.write(".balign 4"),e&&(this.proc.info.usedAsValue=!0),!this.proc.info.usedAsValue&&!this.proc.info.usedAsIface)return;this.proc.info.usedAsValue&&(this.write(this.proc.label()+"_Lit:"),this.write(this.t.obj_header("pxt::RefAction_vtable")),this.write(".short 0, 0 ; no captured vars"),this.write(`.word ${this.proc.label()}_args@fn`)),this.write(`${this.proc.label()}_args:`);let t=this.proc.args.length;if(0==t)return;this.write(`cmp r4, #${t}`),this.write(`bge ${this.proc.label()}_nochk`);let n=this.stackAlignmentNeeded(t+1),r=n?t+2:t+1;this.write("push {lr}"),this.emitLabelledHelper(`expand_args_${t}`,(()=>{this.write("movs r0, #0"),this.write("movs r1, #0"),n&&this.write("push {r0}");for(let e=t;e>0;e--)e!=t&&(this.write(`cmp r4, #${e}`),this.write(`blt .zero${e}`),this.write(`ldr r0, [sp, #${r-1}*4]`),this.write(`str r1, [sp, #${r-1}*4] ; clear existing`),this.write(`.zero${e}:`)),this.write("push {r0}");this.write("bx lr")})),this.write(`bl ${this.proc.label()}_nochk`);let s=t+(n?1:0);this.write(`@dummystack ${s}`),this.write(`add sp, #4*${s}`),this.write("pop {pc}")}emitCallRaw(t){let n=e.hexfile.lookupFunc(t);e.assert(!!n,"unimplemented raw function: "+t),this.alignedCall(t)}}}(e.pxtc||(e.pxtc={}))}(ts||(ts={})),function(e){!function(e){const t={"numops::adds":"+","numops::subs":"-","numops::div":"/","numops::mod":"%","numops::muls":"*","numops::ands":"&","numops::orrs":"|","numops::eors":"^","numops::bnot":"~","numops::lsls":"<<","numops::asrs":">>","numops::lsrs":">>>","numops::le":"<=","numops::lt":"<","numops::lt_bool":"<","numops::ge":">=","numops::gt":">","numops::eq":"==","pxt::eq_bool":"==","pxt::eqq_bool":"===","numops::eqq":"===","numops::neqq":"!==","numops::neq":"!="},n={"pxsim.Boolean_":"","pxsim.pxtcore":"","pxsim.String_":"","pxsim.ImageMethods":"","pxsim.Array_":"","pxsim.pxtrt":"","pxsim.numops":""},r={"pxsim.Array_.getAt":"","pxsim.Array_.length":"","pxsim.Array_.mk":"","pxsim.Array_.push":"","pxsim.Boolean_.bang":"","pxsim.String_.concat":"","pxsim.String_.stringConv":"","pxsim.numops.toBool":"","pxsim.numops.toBoolDecr":"","pxsim.pxtcore.mkAction":"","pxsim.pxtcore.mkClassInstance":"","pxsim.pxtrt.ldlocRef":"","pxsim.pxtrt.mapGetByString":"","pxsim.pxtrt.stclo":"","pxsim.pxtrt.stlocRef":""};function s(e){let t="";for(let n of Object.keys(e)){const r=n.replace(/\./g,"_");e[n]=r,t+=`const ${r} = ${n};\n`}return t}function i(e){"pxt."==(e=e.replace(/::/g,".")).slice(0,4)&&(e="pxtcore."+e.slice(4));const t="pxsim."+e;if(r.hasOwnProperty(t))return r[t];const s=t.lastIndexOf(".");if(s>0){const e=t.slice(0,s);if(n.hasOwnProperty(e))return n[e]+t.slice(s)}return t}e.isBuiltinSimOp=function(n){return!!e.U.lookup(t,n.replace(/\./g,"::"))},e.shimToJs=i;const a=["runtime","oops","doNothing","pxsim","globals","maybeYield","setupDebugger","isBreakFrame","breakpoint","trace","checkStack","leave","checkResumeConsumed","setupResume","setupLambda","checkSubtype","failedCast","buildResume","mkVTable","bind","leaveAccessor"];e.jsEmit=function(o,l){let c="(function (ectx) {\n'use strict';\n";for(let e of a)c+=`const ${e} = ectx.${e};\n`;c+="const __this = runtime;\n",c+="const pxtrt = pxsim.pxtrt;\n",c+="let yieldSteps = 1;\n",c+="ectx.setupYield(function() { yieldSteps = 100; })\n";let u="pxsim.setTitle("+JSON.stringify(o.getTitle())+");\n",p={},d={};for(let e of l.configData||[])p[e.key+""]=e.value,d[e.name]=e.key;u+="pxsim.setConfigData("+JSON.stringify(p,null,1)+", "+JSON.stringify(d,null,1)+");\n",u+="pxtrt.mapKeyNames = "+JSON.stringify(o.ifaceMembers,null,1)+";\n";const f=o.setPerfCounters(["SysScreen"]);u+="__this.setupPerfCounters("+JSON.stringify(f,null,1)+");\n",u+=s(r),u+=s(n);let m=0,h=0;o.procs.forEach((n=>{let r;if(n.cachedJS){r=n.cachedJS,m+=r.length;for(const e of Object.keys(n.cachedJSHexLiterals))o.hexlits[e]=n.cachedJSHexLiterals[e]}else r=function(n,r){if(r.cachedJS)return r.cachedJS;let s="",a=e=>{s+=e+"\n"},o=e=>{s+=" "+e+"\n"},l=e.ir.EK,c=[],u=0,p={};a(`\nfunction ${r.label()}(s) {\nlet r0 = s.r0, step = s.pc;\ns.pc = -1;\n`),r.perfCounterNo&&a(`if (step == 0) __this.startPerfCounter(${r.perfCounterNo});\n`);a("\nwhile (true) {\nif (yieldSteps-- < 0 && maybeYield(s, step, r0) || runtime !== pxsim.runtime) return null;\nswitch (step) {\n case 0:\n"),r.locals.forEach((e=>{o(`${x(e)} = undefined;`)})),r.args.length&&(o("if (s.lambdaArgs) {"),r.args.forEach(((e,t)=>{o(` ${x(e)} = (s.lambdaArgs[${t}]);`)})),o(" s.lambdaArgs = null;"),o("}"));r.classInfo&&r.info.thisParameter&&(o("r0 = s.arg0;"),v(r.classInfo,"validate"));let d=0,f=[];for(let t of r.body)t.stmtKind==e.ir.SK.Label&&t.lblNumUses>0&&(t.lblId=++d);let m=0;for(let t of r.body){switch(t.stmtKind){case e.ir.SK.Expr:I(t.expr);break;case e.ir.SK.StackEmpty:C();break;case e.ir.SK.Jmp:let n=!1;for(let s=m+1;s<r.body.length&&r.body[s].stmtKind==e.ir.SK.Label;++s)if(t.lbl==r.body[s]){n=!0;break}y(t,n);break;case e.ir.SK.Label:t.lblNumUses>0&&a(` case ${t.lblId}:`);break;case e.ir.SK.Comment:a(`// ${t.expr.data}`);break;case e.ir.SK.Breakpoint:b(t);break;default:e.oops()}m++}C(),r.perfCounterNo&&a(`__this.stopPerfCounter(${r.perfCounterNo});\n`);r.isGetter()?o("return leaveAccessor(s, r0)"):o("return leave(s, r0)");a(" default: oops()"),a("} } }");let h=e.nodeLocationInfo(r.action);h.functionName=r.getName(),h.argumentNames=r.args&&r.args.map((e=>e.getName())),a(`${r.label()}.info = ${JSON.stringify(h)}`),r.isGetter()&&a(`${r.label()}.isGetter = true;`);r.isRoot&&a(`${r.label()}.continuations = [ ${f.join(",")} ]`);return a(g(r.label()+"_mk",r.label(),u,Object.keys(p))),r.cachedJS=s,s;function g(e,t,n,r){let s="";s+=`\nfunction ${e}(s) {\n checkStack(s.depth);\n return {\n parent: s, fn: ${t}, depth: s.depth + 1,\n pc: 0, retval: undefined, r0: undefined, overwrittenPC: false, lambdaArgs: null,\n`;for(let e=0;e<n;++e)s+=` tmp_${e}: undefined,\n`;for(let e of r)s+=` ${e}: undefined,\n`;return s+="} }\n",s}function b(e){let t,s=e.breakpointInfo.id;if(o(`s.lastBrkId = ${s};`),n.breakpoints){t=++d;let i=`return breakpoint(s, ${t}, ${s}, r0);`;e.breakpointInfo.isDebuggerStmt?o(i):(o(`if ((breakpoints[0] && isBreakFrame(s)) || breakpoints[${s}]) ${i}`),n.trace&&o(`else return trace(${s}, s, ${t}, ${r.label()}.info);`))}else{if(!n.trace)return;t=++d,o(`return trace(${s}, s, ${t}, ${r.label()}.info);`)}a(` case ${t}:`)}function x(e){if(e.isGlobal())return"globals."+e.uniqueName();if(e.iscap)return`s.caps[${e.index}]`;const t=e.uniqueName();return p[t]=!0,"s."+t}function y(t,n){if(t.lbl.lblNumUses==e.ir.lblNumUsesJmpNext||n)return e.assert(t.jmpMode==e.ir.JmpMode.Always),void(t.expr&&I(t.expr));e.assert(t.lbl.lblNumUses>0);let r=`{ step = ${t.lbl.lblId}; continue; }`;t.jmpMode==e.ir.JmpMode.Always?(t.expr&&I(t.expr),o(r)):(I(t.expr),t.jmpMode==e.ir.JmpMode.IfNotZero?o(`if (r0) ${r}`):o(`if (!r0) ${r}`))}function k(e){switch(e.exprKind){case l.NumberLiteral:case l.PointerLiteral:case l.SharedRef:case l.CellRef:return!0;default:return!1}}function S(e){return k(e)?T(e):(I(e),"r0")}function T(t){switch(t.exprKind){case l.NumberLiteral:if(!0===t.data)return"true";if(!1===t.data)return"false";if(null===t.data)return"null";if(void 0===t.data)return"undefined";if("number"==typeof t.data)return t.data+"";if("string"==typeof t.data)return`"${t.data}"`;throw e.oops("invalid data: "+typeof t.data);case l.PointerLiteral:if(t.ptrlabel())return t.ptrlabel().lblId+"";if(null!=t.hexlit()){const e=`const ${t.data} = pxsim.BufferMethods.createBufferFromHex("${t.hexlit()}")\n`;return r.cachedJSHexLiterals[t.data]=e,n.hexlits[t.data]=e,t.data}if("string"==typeof t.jsInfo)return t.jsInfo;e.U.oops();case l.SharedRef:let s=t.args[0];e.U.assert(!!s.currUses),e.U.assert(s.currUses<s.totalUses),s.currUses++;let i=c.indexOf(s);return e.U.assert(i>=0),"s.tmp_"+i;case l.CellRef:return x(t.data);default:throw e.oops()}}function I(e){switch(e.exprKind){case l.JmpValue:o("// jmp value (already in r0)");break;case l.Nop:o("// nop");break;case l.FieldAccess:let t=e.data,n=t.shimName,r=S(e.args[0]);return n?void o(`r0 = ${r}${n};`):void o(`r0 = ${r}.fields["${t.name}"];`);case l.Store:return K(e.args[0],e.args[1]);case l.RuntimeCall:return N(e);case l.ProcCall:return A(e);case l.SharedDef:return $(e);case l.Sequence:return e.args.forEach(I);case l.InstanceOf:return I(e.args[0]),void v(e.data,e.jsInfo);default:o(`r0 = ${T(e)};`)}}function w(e){return`${e.id}_VT`}function E(e,t="r0"){return`checkSubtype(${t}, ${w(e)})`}function v(t,n,r="r0"){"bool"==n?o(`r0 = ${E(t)};`):"validate"==n?o(`if (!${E(t,r)}) failedCast(${r}, ${w(t)});`):e.U.oops()}function $(t){let n=t.args[0];if(e.U.assert(n.totalUses>=1),e.U.a