// mcode runtime library for javascript ⍙.v r,ver='mcode runtime library version 0.08.18.2024' '' ⎕ ver ; ⊙.test = {} // test artifacts namespace r = `// mcode runtime library - generated file mcode.logn('` + ver + ` loaded from cache'); /* jshint asi:true */ ` r += ` // regenerate mcode cache - called by the IDE regen button` r += ⍎.er ` ∇ mcode.regen ∇.a sf : pr,r mcode.desktop → ⍠.done 'regen not currently available on desktop system' ⍔ 0 // pr ← { ⍵.replace(/^.*\\?\\s/,'') } // remove prompt // pr2 ← { ⍪ 1 ↓ '? ' ⊃ ⍵ } // another way to remove prompt mcode.serverAuth ⥊ ⍬ → // mcode.serverAuth = pr ( ⍃.c 'server write auth? ' ) // ask in session // ask outside of session for better security mcode.serverAuth = prompt('server write auth? ') // read and exec core source ⎕ ⍎ ⍃ 'core.mc.txt' // read and exec runtime library source ⎕ ⍎ ⍃ 'rtl.mc.txt' // write transpiled code to cache file r = mcode.cp.core + mcode.cp.lib 'server rsp' ⎕.nnl ⍄.'lib/mcode_cache.js' r ⍠.done 'regen done' // tell IDE we're done ⎕ 'regen' ⍠.busy 0 // tell IDE to wait for done promise ⍠.tmo sf // call async 'sf' after busy flag is shown (otherwise prompt supercedes) ` r += ` // Panel functions - in-browser floating movable windows` r += ⍎.er ` ∇ mcode.panel ∇ init // one time css class definition ⍛.head \` \` init 0 ∇ handleMoveButton : pid=⍵,svg,icon,moveAr={},moveID=0 svg = \`data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTEzLDExSDE4TDE2LjUsOS41TDE3LjkyLDguMDhMMjEuODQsMTJMMTcuOTIsMTUuOTJMMTYuNSwxNC41TDE4LDEzSDEzVjE4TDE0LjUsMTYuNUwxNS45MiwxNy45MkwxMiwyMS44NEw4LjA4LDE3LjkyTDkuNSwxNi41TDExLDE4VjEzSDZMNy41LDE0LjVMNi4wOCwxNS45MkwyLjE2LDEyTDYuMDgsOC4wOEw3LjUsOS41TDYsMTFIMTFWNkw5LjUsNy41TDguMDgsNi4wOEwxMiwyLjE2TDE1LjkyLDYuMDhMMTQuNSw3LjVMMTMsNlYxMVoiIC8+PC9zdmc+\` icon = \`\` ∇ reset : pid=⍵,t t = ⍛ pid ; !t → ⍠.↑ 'mcode.panel: no panel element ' + pid moveAr[pid] = {tgt:t,x:0,y:0} ∇ doMove : m=⍺,e=⍵,dx,dy dx = m.x - e.clientX ; dy = m.y - e.clientY; m.x = e.clientX ; m.y = e.clientY; m.tgt.style.left = ( m.tgt.offsetLeft - dx ) + 'px' m.tgt.style.top = ( m.tgt.offsetTop - dy ) + 'px' ∇ tmove : e=⍺,m,f // e is touchmove event with touch move list !moveID → ⍔ 0 m = moveAr[moveID] f ⌻ e.touches : m doMove f ∇ mmove : e=⍺,m // e is mousemove event !moveID → ⍔ 0 m = moveAr[moveID] ; m doMove e ∇ pend moveID = 0 ∇ pstart : e=⍺,id,m // ⍺ is pointerdown event from DOM id = e.currentTarget.getAttribute('move-btn') moveID = id m = moveAr[id] ; m.x = e.clientX ; m.y = e.clientY ⍛.ael [ 'touchmove' tmove 0 ] ; ⍛.ael [ 'touchend' pend 0 ] ⍛.ael [ 'mousemove' mmove 0 ] ; ⍛.ael [ 'mouseup' pend 0 ] ∇ initMoveButton : pid=⍵,id,el // pid is panel el id to be moved (using top and left) id = pid+'_move' // button user presses to cause move el = ⍛ id ; !el → ⍔ 0 // ⍠.↑ 'mcode.panel: no move element ' + id reset pid el ⍛.attr [ 'move-btn' pid ] // for pstart moveID el.style.cursor = 'move' el.style.touchAction = 'none' // nb. stops browser from scrolling while button is touched el ⍛ icon el ⍛.ael [ 'pointerdown' pstart 1 ] initMoveButton pid ∇ setColors : id=⍵,el ⍙.v [bg,btn,clr] = ⍺ el = ⍛ id ; !el → ⍔ 0 el ⍛.clr clr ; el ⍛.bg bg id+'_hr' ⍛.brd clr id+'_hdg' ⍛.clr clr id+'_move' ⍛.bg btn id+'_close' ⍛.bg btn ∇ show : id=⍵,el ⍺ ⥊ ⍬ → ⍺ = ['80%'] ⍙.v [w=⍬,h='400px',x='100px',y='50px'] = ⍺ el = ⍛ id ; !el → ⍔ 0 el ⍛.dsp 'block' w ⥊ ⍬ → ⍔ el // show only el ⍛.top y ; el ⍛.left x w != '' → el ⍛.w w h != '' → h = h ⍙ # ; el ⍛.h h id+'_body' ⍛.h h - 45 ⍔ id ∇ close : id=⍵,el !id → id = ⍺ // call from mcode or DOM id ⍛.dsp 'none' ; ⍔ id ∇ remove : id=⍵,el !id → id = ⍺ // call from mcode or DOM id ⍛.rm 0 ; ⍔ 0 ∇ create : id=⍵ ⍺ ⥊ ⍬ → ⍠.↑ 'mcode.panel.create: heading and body required' ⍙.v [hdg='',body='',bg='888',btn='777',clr='000',template=''] = ⍺ template ⥊ '' → // useful unicode: help 10067 ❓ help 10068 ❔ close 10060 ❌ template = \`

\${hdg}



\${body}
\` // zvzv trial of ≢.tmpl NFN // template = \` //
//
// // //

\${hdg}



//
//
//
\${body}
//
//
\` // template = [id,id+'_close',id+'_move',id+'_hdg',id+'_body'] ≢.tmpl template // ⎕ template ⍛.body template [bg,btn,clr] setColors id handleMoveButton id ⍔ id // API mcode.panel.create = create; mcode.panel.remove = remove; mcode.panel.show = show; mcode.panel.close = close; mcode.panel 0 ` ⍎ ` ∇ ⊙.test.panel : p,d ⎕ 'test.panel' p = 'testPanel1' d = \` Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \` [ 'test panel 1' d 375 486 'ccc' ] mcode.panel.create p mcode.panel.show p // ⊙.test.panel 0 ` r += '// mcode Language Syntax Coloring' r += ⍎.er ` ∇ mcode.syntaxColor ∇ init ⍛.head \` \` init 0 mcode.syntaxColor.printCss = \` \` ` r += ⍎.er ` ∇ mcode.syntaxColor.colorize : e0,r,s={} // colorize mcode in ⍵ with HTML // only colorizes token + space at this time, eg. not ⎕.j mcode.setLang() // 'mcode.lang' ⎕ mcode.lang e0 = '' ⊃ '?+*!^~|&' // escapes needed for regexp ∇ escapes // escape HTML in regexs and source ⍔ />/g ≢.'>' / 5' // test ∇ spans s.z0 = '' ; s.z2 = '' ⍔ '‗Z‗2' ≢.s.z2 'Z‗1' ≢.s.z1 'Z‗0' ≢.s.z0 ⍵ ∇ apply : e,s={} // apply lang regexp to mcode ∇ makeRe : b,d,m m = mcode.lang[⍵] b ⌻ e0 // insert \ escapes per e0 into m s.b = '\\\\'+b ; m = b ≢.s.b m d = /\\s/g ≢.'|' m // insert | ⍔ '('+d+')( )' ⍙.g '/' // convert to regexp w trailing space ∇ makeTmpl : c c = 'Z‗0X‗Z‗1$1‗Z‗2 ' ; s.t = ⍵ ⍔ 'X‗' ≢.s.t c e = makeRe ⍺ // ⍺ ⎕ e s.tmpl = makeTmpl ⍺ // 's.tmpl' ⎕.j s.tmpl ⍔ e ≢.s.tmpl ⍵ // insert template at matches to f r = ⍵ r = 'stmts' apply r r = 'prims' apply r r = 'vars' apply r r = 'builtins' apply r r = 'fns' apply r r = 'oprs' apply r // r = 'js' apply r r = spans 0 escapes r // ⎕ r ⍔ r // mcode.syntaxColor.colorize = colorize // mcode.syntaxColor.printCss = printCss mcode.syntaxColor 0 ` ⍎ ` ∇ ⊙.test.syntaxColor : c,s,p c = '⍎.e 1 ' // c = '1 !== 0' // c = \`∇ foo // test // 1 !== 0 != 2 // ⍔ 1 ?= 0 // \` s = mcode.syntaxColor.colorize c ⎕ s s = '
'+s+'
' p = 'syntaxColor' [ 'test colorize' s 357 468 'fff' ] mcode.panel.create p [ 200 200 500 100 ] mcode.panel.show p // ⊙.test.syntaxColor 0 ` r += ⍎.er ` ∇ mcode.showGuide : r,p='mcodeGuide' ⍠.d 1 mcode.panel.show p → ⍔ 0 r = mcode.guide 0 r = mcode.syntaxColor.colorize r r = '
'+r+'
' [ 'mcode guide' r '357' '579' 'eee' ] mcode.panel.create p mcode.panel.show p ` r += ⍎.er ` ∇ mcode.printDoc : p p = \` mcode guide \` p += mcode.syntaxColor.printCss ∇ compose p += '

' + ⍺ + '

\\n' ⍵ = mcode.syntaxColor.colorize ⍵ p += '
' + ⍵ + '
' ⍛.docwr p ∇.a rf : d // read file ⍵ ⥊ 'guide' → d = mcode.guide 0 // guide from transpiler tables ⋄ d = ⍃ ⍵ // document file from server ⍺ compose d // 'mcode guide' rf 'guide' // 'mcode primer' rf 'primer.mc.txt' // 'mcode core' rf 'core.mc.txt' // 'mcode runtime library' rf 'rtl.mc.txt' 'mcode JavaScript transpiler' rf 'mcode.js' // NIU - use cut/paste into MS Word instead /* ∇.a wf mcode.serverAuth ⥊ ⍬ → mcode.serverAuth = prompt('server write auth? ') 'server rsp' ⎕.nnl ⍄.'downloads/guide.html' p ⍠.done 'file write done' ⍔ 0 ⍠.busy 0 ⍠.tmo wf */ ` // mcode keyboard map ⊙.vik={} ⊙.vik.kbd = ` ~ ⌺│! ⌶│@ ⍫│# ⍒│$ ⍋│% ⌽│^ ⍉│& ⊖│* ⍟│( ∨│) ė│_ ‗│+ ⌹ \` ⋄│1 ¨│2 ¯│3 ⍃│4 ≤│5 ≈│6 ≥│7 ⍄│8 ≠│9 ⥊│0 θ│- ×│= ÷ -- Q ⍠│W ⍹│E ⍷│R √│T ⍨│Y ⍐│U ⍗│I ⍸│O ⍥│P ⍣│{ ⍞│} ⍬│| ⊣ q ∞│w ⍵│e ∊│r ⍴│t ~│y ↑│u ↓│i ⍳│o ○│p π│[ ←│] →│\\ ⊢ -- A ⍶│S ⍢│D δ│F ⌻│G ⍔│H ⍙│J ⍤│K ⌸│L ⌷│: ≡│" ≢ a ⍺│s ⌈│d ⌊│f ⍛│g ∇│h ∆│j ∘│k ⊙│l ⎕│; ⍎│' ⍕ -- Z ⊆│X ⊇│C «│V »│B ⍊│N ⍑│M ‖│< ⍪│> ⍂│? ⍰ z ⊂│x ⊃│c ∩│v ∪│b ⊥│n ⊤│m ¦│, ⍝│. ⍀│/ ⌿ ` ⍎ ` ∇ ⊙.vik.generate : a,b,c,d,e,f,k={},l=[],s={} // 'kbd' ⎕ ⊙.vik.kbd ∇ ins // insert fixed keys ⍺ ⥊ 'a' → ⍔ ⍵ ↓ 'tab' ⍺ ⥊ 'z' → ⍔ ⍵ ↓ 'sft' ∇ app // append fixed keys ⍺ ⥊ "'" → ⍔ ⍵ ↓ 'rtn' ⍺ ⥊ '/' → ⍔ ( ⍵ ↓ 'bks' ) ↓ 'del' a = /\s/g ≢.'' ¨ '\\n' ⊃ ¨ '--' ⊃ ⊙.vik.kbd // split kbd rows and remove lf and spaces b ⌻ a // each kybd row c = '│' ⊃ ¨ [ 1 2 ] ⌷ b // remove non-data i = 0 ; e = [] // reset d ⌻ c[1] // each key f = d[0] // base key k[f] = c[0][i++][0] // set shifted key f ins e ; e ↓ f ; f app e // set layout array d ⌻ ⍪ c : s[d[0]] = d[1] // set each key symbol l ↓ e // push layout row l ↓ [ 'sym' 'spc' 'pup' 'pdn' 'mov' 'cls' ] // bottom row layout // 'shift map' ⎕ k ; 'layout arr' ⎕.j l ; 'mcode map' ⎕ s mcode.vik.shift = ⍕.j k mcode.vik.layout = ⍕.j l mcode.vik.symbols = ⍕.j s ⍔ 0 mcode.vik = {} ⊙.vik.generate 0 ` r += ` // Virtual Input Keyboard (VIK) - generated data mcode.vik = {} mcode.vik.shift = ` + mcode.vik.shift + ` mcode.vik.layout = ` + mcode.vik.layout + ` mcode.vik.symbols = ` + mcode.vik.symbols + ` ` ∇ ⊙.vik.init ⍛.head ` ` ⊙.vik.init 0 r += ⍎.er ` ∇ mcode.vik.show : r,p='mcode-vik',k mcode.panel.show p → ⍔ 0 k = mcode.syntaxColor.colorize '∇' ⎕ k r = \`
\${k}
E
F
G
H
\` [ '' '' '468' '68a' 'fff' r ] mcode.panel.create p [ '' '' '500px' '100px' ] mcode.panel.show p ` // test // mcode.vik.show 0 r += `// end library ` ⍙.v core = mcode.cp.core // save generated core ⍙.v lib = r // save generated lib mcode.cp = {} // clear context mcode.cp.core = core mcode.cp.lib = lib ⍔ ' library loaded'