├── xfrpc.aws ├── xfrcode.dws ├── xfrpcV5.aws ├── ReadCovers.atf ├── LICENSE ├── FixCovers.dyalog ├── xfrdefs.txt ├── tools.dyalog ├── README.md ├── TestAPLX.dyalog ├── Differences.md └── APLX.dyalog /xfrpc.aws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dyalog/aplx/master/xfrpc.aws -------------------------------------------------------------------------------- /xfrcode.dws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dyalog/aplx/master/xfrcode.dws -------------------------------------------------------------------------------- /xfrpcV5.aws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dyalog/aplx/master/xfrpcV5.aws -------------------------------------------------------------------------------- /ReadCovers.atf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dyalog/aplx/master/ReadCovers.atf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Dyalog Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /FixCovers.dyalog: -------------------------------------------------------------------------------- 1 | :Require file://./APLX.dyalog 2 | 3 | ∇FixCovers;T 4 | ⍝ Create emulation function templates 5 | 6 | :If 'Dyalog'≡APLVERSION←(4 7⍳⍴⎕AI)⊃'Dyalog' 'APLX' 'APLX' 7 | EMULATED←APLX.⎕NL ¯3 ⍝ Use the list of functions 8 | :Else ⍝ Hardcoded in APLX - remember to update! 9 | T←'/∆AF/∆AI/∆AV/∆B/∆BOX/∆C/∆CALL/∆DBR/∆DISPLAY/∆DR/∆EA/∆EM/∆EQ_' 10 | T←T,'/∆ERM/∆ERX/∆EXPORT/∆FDROP/∆FHOLD/∆FI/∆FREAD/∆FWRITE/∆GETCLASS' 11 | T←T,'/∆HOST/∆I/∆IMPORT/∆L/∆LIB/∆LSHOE/∆M/∆MOUNT/∆N/∆NAPPEND' 12 | T←T,'/∆NERASE/∆NERROR/∆NREAD/∆NREPLACE/∆NWRITE/∆OV/∆R/∆RSHOE' 13 | T←T,'/∆SS/∆TIME/∆UP/∆VI/∆W/∆WSSIZE/∆a' 14 | EMULATED←1↓¨(+\T='/')⊂T 15 | :EndIf 16 | 17 | :For fn :In EMULATED 18 | :Select APLVERSION 19 | :Case 'APLX' 20 | :If (⎕AF 'Z')<⎕AF 1⊃fn ⍝ lowercase => function 21 | ⎕FX ⊃('Z←L ',fn,' R')(':If 2=⎕NC ''L'' ⋄ Z←L ⎕',fn,' R')(':Else ⋄ Z←⎕',fn,' R')':EndIf' 22 | :Else ⍝ Niladic 23 | ⎕FX ⊃('Z←∆',fn)('Z←⎕',fn) 24 | :EndIf 25 | :Case 'Dyalog' 26 | :If 0≠1 2⊃APLX.⎕AT fn 27 | ⎕FX ⊃('Z←{L} ',fn,' R')(':If 2=⎕NC ''L'' ⋄ Z←L #.APLX.',fn,' R')(':Else ⋄ Z←#.APLX.',fn,' R')':EndIf' 28 | :Else ⍝ Niladic 29 | ⎕FX ⊃('Z←',fn)('Z←#.APLX.',fn) 30 | :EndIf 31 | :EndSelect 32 | :EndFor 33 | ∇ -------------------------------------------------------------------------------- /xfrdefs.txt: -------------------------------------------------------------------------------- 1 | :APX "215"%⍬ "11"% ∆oFREAD ! "12"% ∆oFWRITE ! "9"% ∆oFDROP ! "7"% ∆oFHOLD ! Ã% ! ⎕AF%∆AF ⎕AI%∆AI ⎕AV%∆AV ⎕B%∆B ⎕BOX%∆BOX ⎕C%∆C ⎕CALL%∆CALL ⎕CHART%∆CHART ⎕CLASSNAME%∆CLASSNAME ⎕CL%(⍬⍴⎕lc) ⎕CONF%∆CONF 2 ⎕CR%⎕NR ⎕DBR%∆DBR ⎕DISPLAY%∆DISPLAY ⎕DR%∆DR ⎕EA%∆EA ⎕EDIT%⎕ED ⎕EM%∆EM ⎕ERM%∆ERM ⎕ERS%⎕SIGNAL ⎕ERX%∆ERX ⎕ES%99 ⎕signal⍨ ⎕ET%∆ET ⎕EXPORT%∆EXPORT ⎕FC%fc_ ⎕FDROP%∆FDROP ⎕FHOLD%∆FHOLD ⎕FI%∆FI ⎕FREAD%∆FREAD ⎕FWRITE%∆FWRITE ⎕GETCLASS%∆GETCLASS ⎕HOST%∆HOST ⎕HT%∆HT ⎕I%∆I ⎕IC%∆IC ⎕IMPORT%∆IMPORT ⎕L%∆L ⎕LER%⎕EN ⎕LIB%∆LIB ⎕M%∆M ⎕MIXIN%∆MIXIN ⎕MOUNT%∆MOUNT ⎕N%∆N ⎕NAPPEND%∆NAPPEND ⎕NERASE%∆NERASE ⎕NREAD%∆NREAD ⎕NREPLACE%∆NREPLACE ⎕NWRITE%∆NWRITE ⎕OV%∆OV ⎕R%∆R ⎕SS%∆SS ⎕TIME%∆TIME ⎕T%⎕av[9+⎕io] ⎕UL%1 ⎕UNMIX%∆UNMIX ⎕VI%∆VI ⎕W%∆W ⎕WE%∆WE ⎕a%∆a! :catchall%:else :EndTry%:EndTrap :Try%:Trap 0 ⊣%{⍺←⍬⊤⍬⋄⍺} ≡% ∆EQ_ ! ⊂% ∆LSHOE ! ↑% ∆UP ! ⊃% ∆RSHOE ! ⍺%⊢⍕ :A2K ⎕ENLIST%{⎕ml←1⋄∊⍵} ⎕IDLIST%∆IDLIST ⎕IDLOC%∆IDLOC ⎕HTOPIC%∆HTOPIC ⎕USERID%⎕AN ⎕ERROR%⎕signal/{⍵((×⍴⍵)⍴99)} ⎕TCESC%#.A2K.⍙ESC ⎕TCNUL%#.A2K.⍙NUL ⎕SINL%∆SINL ;⎕ELX%;⎕trap ;⎕ALX%;⎕TRAP ;⎕SA%;⎕TRAP ⎕FDUP%∆FDUP ⎕KEYW%∆KEYW ⎕TCNL%⎕av[3+⎕io] ⎕TCLF%⎕av[2+⎕io] ⎕TCFF%(⎕UCS 12) ⎕TCBS%⎕av[1+⎕io] ⎕TCHT%(⎕UCS 9) ⎕TCNUL%⎕av[⎕io] ⎕TCBEL%∆TCBEL ⎕WCALL%∆WCALL ⎕WGIVE%∆WGIVE ⎕ELX←'⎕dm'%⎕trap←0'S' ⎕ELX←'%⎕trap←0'E',⊂' ⎕XNNUMS%⎕NNUMS "22"%⍬ ⎕DEF%⎕FX ⎕ELX%⎕TRAP ⎕SEG%∆SEG ⎕VI%{⎕IO⊃⎕VFI ⍵} ⎕FI%{⎕IO⊃⌽⎕VFI ⍵} ⎕SI%(⊃⎕SI) ⎕ERASE%∆ERASE ⎕FSTIE%∆FSTIE ⎕FTIE%∆FTIE ⎕XN*%⎕N ⎕CN*%⎕N ⎕SS%⍷⍨ ⎕MF%⎕MONITOR ⎕WIN%∆WIN ⎕WINDOW%∆WINDOW ⎕WKEYS%∆WKEYS ⎕POKES%∆POKES ⎕CURSOR%∆CURSOR ⎕POKE%∆POKE ⎕PEEK%∆PEEK ⎕KEYLOG%∆KEYLOG ⎕SPLIT%↓ ⎕INT%∆INT ⎕LIB%∆LIB ⎕LIBD%∆LIBD ⎕LIBS%∆LIBS ⎕CHDIR%∆CHDIR ⎕ERASE%∆ERASE ⎕ALX←%∆SetALX ⎕PFKEYS%∆PFKEYS ⎕WSELF%∆WSELF ⎕WI%∆WI ⎕CHDIR%∆CHDIR ⎕TYPE%∆TYPE ⎕PENCLOSE%{⎕ml←0⋄⍺⊂⍵} ⎕UCMD%⎕SE.UCMD ⎕REPL%/ ⎕FIRST%∆FIRST ⎕EXPAND%\ ⎕LOG%∆LOG ⎕MIX%∆MIX ⎕SYS[%#.A2K.∆SYS[ ⎕SYS%#.A2K.⌷∆SYS ⎕WSSIZE%(2000⌶0) :returnif%→0/⍨ :try *%:trap 0 :try%:trap 0 :endtry%:endtrap :catchall%:else :catch%:else :SAPL ⎕replace%⎕FREPLACE ⎕appendr%⎕FAPPEND 2 ⎕ws 1%⎕WSID ⎕signal%⎕SIGNAL 2 ⎕ws 2%(⊃⎕SI) ⎕resize%⎕FRESIZE ⎕create%⎕FCREATE ⎕rename%⎕FRENAME ⎕pnames%Pnames ⎕trap←%⎕trap←∆TRAP ⎕avail%⎕FAVAIL ⎕names%⎕FNAMES ⎕erase%⎕FERASE ⎕untie%⎕FUNTIE ⎕ppdef%Ppdef ⎕plock%Plock 3 ⎕fd%⎕FX 1 ⎕fd%⎕VR ⎕trap%⎕TRAP ⎕rdfi%⎕FHIST ⎕rdci%⎕FRDCI ⎕size%⎕FSIZE ⎕nums%⎕FNUMS ⎕rdac%⎕FRDAC ⎕stac%⎕FSTAC ⎕hold%⎕FHOLD ⎕read%⎕FREAD ⎕stie%⎕FSTIE ⎕drop%⎕FDROP ⎕copy%∆FDUP ⎕pdef%Pdef ⎕psel%Psel ⎕pins%Pins ⎕pack%Pack ⎕pval%Pval ⎕EDIT%⎕ED ⎕lib%⎕FLIB ⎕tie%⎕FTIE ¨><<%¨⊂⊂ ⎕pnc%Pnc ⎕pex%Pex ⎕out%∆OUT ⎕fmt%∆FMT ⎕vi%⎕IO⊃⎕VFI ⎕fi%⎕IO⊃⌽⎕VFI ⎕er%er_ ¨><%¨⊂ ⎕ec%ec_ ⎕sc%sc_ ⎕ps%ps_ ⎕sp%sp_ ⎕ht%ht_ ⎕ul%1 ⎕ws%∆WS ⎕fd%∆FD ⎕fc%fc_ ¨>%¨ €>%⊃ €<%⊂ ⊃<% ∆enc ≡⊃% ∆boxed <.%<. .%>. >/%>/ >⌿%>⌿ >\%>\ >⍀%>⍀ (<%(⊂ ←<%←⊂ \<%\⊂ ∊<%∊⊂ ⍴<%⍴⊂ ↑<%↑⊂ ↓<%↓⊂ ⍳<%⍳⊂ ⊖<%⊖⊂ ⊣<%⊣⊂ €<%€⊂ ⍕<%⍕⊂ ,<%,⊂ ⍪<%⍪⊂ /<%/⊂ ⌿<%⌿⊂ (>%(⊃ +>%+⊃ ←>%←⊃ →>%→⊃ <>%<⊃ ≤>%≤⊃ =>%=⊃ ≥>%≥⊃ >>%>⊃ ≠>%≠⊃ ∨>%∨⊃ ∧>%∧⊃ ->%-⊃ ×>%×⊃ ÷>%÷⊃ !>%!⊃ ⍱>%⍱⊃ ⍲>%⍲⊃ ⌹>%⌹⊃ ⍀>%⍀⊃ \>%\⊃ ⌽>%⌽⊃ ⍷>%⍷⊃ ∊>%∊⊃ ⍴>%⍴⊃ ~>%~⊃ ⍉>%⍉⊃ ↑>%↑⊃ ↓>%↓⊃ ⍳>%⍳⊃ ○>%○⊃ *>%*⊃ ⍟>%⍟⊃ [>%[⊃ ⊖>%⊖⊃ ⌈>%⌈⊃ ⌊>%⌊⊃ ⍒>%⍒⊃ ⍋>%⍋⊃ #<%⊂ #>%⊃ ⊥>%⊥⊃ ⊤>%⊤⊃ ⍎>%⍎⊃ ⍕>%⍕⊃ |>%|⊃ ,>%,⊃ ⍪>%⍪⊃ ?>%?⊃ />%/⊃ ⌿>%⌿⊃ ö>% ∆Rank⊃ Ö>% ∆Upon⊃ ⊂%"133" ⍺%a_ ⍵%w_ ⊣% ∆lev €%{⍵} ⊃% ⌶% ∆ibeam ö% ∆Rank Ö% ∆Upon :AP2 ⎕ES%⎕SIGNAL{(1⌊⍴⍵)↑⍵} ⎕AF%∆AF ⎕AT%∆AT ⎕EA%∆EA ⎕AV←%{} ⎕WA←%{} -------------------------------------------------------------------------------- /tools.dyalog: -------------------------------------------------------------------------------- 1 | :Namespace convertionTools 2 | ⍝ === VARIABLES === 3 | 4 | L←⎕av[3+⎕io] 5 | _←⍬ 6 | _,←'This namespace, "convertionTools", is used to find' 7 | _,←L,'and solve some possible conversion problems.' 8 | _,←L 9 | _,←L,'At the moment it can only find the use of [brackets] in vectors.' 10 | _,←L,'APLX uses A B[i] to mean A (B[i]) in Dyalog.' 11 | _,←L,'When code from APLX is transferred to Dyalog no such translation is ' 12 | _,←L,'usually performed and this tool here can help with that.' 13 | _,←L 14 | _,←L,'The program "findBrackets" accepts the name of a program as argument' 15 | _,←L,'and shows where problems are likely to exist.' 16 | _,←L 17 | _,←L,'For example, if line 23 of program "Calc" reads' 18 | _,←L 19 | _,←L,'[23] A+B C[i]' 20 | _,←L 21 | _,←L,'then the tool will show' 22 | _,←L 23 | _,←L,' findBrackets ''Calc''' 24 | _,←L 25 | _,←L,' ∇ #.Calc (1 found)' 26 | _,←L,'[23] A+B C[i]' 27 | _,←L,' ^^^^^^' 28 | _,←L,7⍴' ' 29 | _,←L,'If an empty list is given to "findBrackets" then all programs in the' 30 | _,←L,'workspace will be searched. ' 31 | _,←L 32 | _,←L,'Note that overlapping matches are not found. If line 23 of the preceding' 33 | _,←L,'example were ' 34 | _,←L 35 | _,←L,'[23] A+B C[i] D[j]' 36 | _,←L 37 | _,←L,'then only ' 38 | _,←L 39 | _,←L,'[23] A+B C[i] D[j]' 40 | _,←L,' ^^^^^^' 41 | _,←L,'would be found and shown.' 42 | _,←L,'Also, text and comments are NOT searched but it reports problematic lines' 43 | _,←L,'in text following ∆EA:' 44 | _,←L 45 | _,←L,'[24] '''' ∆EA ''A+B C[i]'' ' 46 | _,←L,' ^^^^^^' 47 | _,←L 48 | _,←L,'If replacement is required the program "addParens" works the same way: it' 49 | _,←L,'accepts the name of a program or an empty string to mean "all programs". ' 50 | _,←L,'But it only changes code, not code in text following ∆EA for example.' 51 | _,←L 52 | _,←L,' addParens ''Calc''' 53 | _,←L 54 | _,←L,' ∇ #.Calc (1 found)' 55 | _,←L,'[23] A+B (C[i])' 56 | _,←L,' ^^^^^^' 57 | _,←L,'1 replacement made. ' 58 | _,←L 59 | _,←L,'If the line has overlapping matches like' 60 | _,←L 61 | _,←L,' findBrackets''Calc''' 62 | _,←L 63 | _,←L,' ∇ #.Calc (1 found) ' 64 | _,←L,'[23] A+B C[i] D[j] ' 65 | _,←L,' ∧∧∧∧∧∧' 66 | _,←L 67 | _,←L,'then "addParens" will do them all' 68 | _,←L 69 | _,←L,' addParens ''Calc''' 70 | _,←L 71 | _,←L,' ∇ #.Calc (1 found)' 72 | _,←L,'[23] A+B (C[i])D[j]' 73 | _,←L,' ^^^^^^ ' 74 | _,←L 75 | _,←L,' ∇ #.Calc (1 found)' 76 | _,←L,'[23] A+B (C[i])(D[j])' 77 | _,←L,' ^^^^^^' 78 | _,←L 79 | _,←L 80 | _,←L 81 | _,←L,'NOTE:' 82 | _,←L 83 | _,←L,'For these tools to work you need at least V15 and user commands version 2.12' 84 | _,←L,'To find out which version you are running type' 85 | _,←L 86 | _,←L,' ]version ' 87 | _,←L 88 | _,←L,'If your version is not good enough you can do ' 89 | _,←L 90 | _,←L,' ]uupdate ' 91 | _,←L 92 | _,←L,'To update your tools.' 93 | _,←L 94 | _,←L,'DanB 2016' 95 | _,←L 96 | Describe←_ 97 | 98 | RBV←'''((?(DEFINE)(?(?>''''(''''''''|[^''''])*''''))(?(?>(((&S)|[^()])*)))(?(?>(((&S)|[^][])*)))(?

\((?&noP)?(?&P)?(?&noP)?\))(?\[(?&noB)?(?&B)?(?&noB)?\]))(?((?>⍵)|(?>⍺)|(?&S)|(?&P))\s*(?&B)??) *)((?&item) *(?&B))''' 99 | 100 | ⎕ex¨'L_' 101 | 102 | ⍝ === End of variables definition === 103 | 104 | (⎕IO ⎕ML ⎕WX)←1 1 3 105 | 106 | ∇ addParens arg;exp 107 | ⍝ Add parentheses around the 1st element with brackets in a vector 108 | exp←RBV,(1+~0∊⍴arg)⊃' -class=3'{⍺ ⍵}' -object=',arg 109 | exp←'locate -pattern -show -exclude=ct -callback=#.convertionTools.prune ',exp,' -replace "\1 (\G)"' 110 | :Repeat ⋄ :Until '0'=1↑⎕RSI[⎕IO]⎕SE.UCMD exp 111 | ∇ 112 | 113 | ∇ findBrackets arg;exp 114 | ⍝ Find where bracketed expressions involving vectors are found 115 | ⎕←'* List of places where parentheses would be needed in code only:' 116 | exp←RBV,(1+~0∊⍴arg)⊃' -class=3'{⍺ ⍵}' -object=',arg 117 | ⎕RSI[⎕IO]⎕SE.UCMD'locate -pattern -show -exclude=ct -callback=#.convertionTools.prune ',exp 118 | ⎕←2 1⍴'' 119 | ⎕←'* List of places where parentheses would be needed after ∆EA:' 120 | exp←'''∆EA''''.*?\K',1↓exp 121 | ⎕RSI[⎕IO]⎕SE.UCMD'locate -pattern -show -exclude=c -callback=#.convertionTools.prune ',exp 122 | ∇ 123 | 124 | ∇ r←prune exp;noun 125 | :If r←3≠#.⎕NC noun←(∧\exp∊⎕A,'abcdefghijklmnopqrstuvwxyz∆⍙',⎕D)/exp 126 | :AndIf 9=⎕NC'#.APLX' 127 | r←~(#.APLX.⎕NC noun)∊3 4 128 | :EndIf 129 | ∇ 130 | 131 | :EndNamespace 132 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | ##### Dated July 30th, 2016 3 | On July 11th 2016, MicroAPL announced the end of support for the APLX product. Since that date, Dyalog has been working with APLX users on developing tools to assist in the migration of existing applications from APLX to Dyalog APL. At this time, the tools are very much “work in progress” and will be updated frequently as we receive feedback. 4 | 5 | Comments and contributions are very welcome. Since Dyalog Ltd still has relatively limited knowledge of active APLX applications, we need input from APLX users to help us prioritise our work! Write to us at [aplx@dyalog.com](mailto:aplx@dyalog.com), or participate in [the forum section created for this purpose](http://www.dyalog.com/forum/viewforum.php?f=37) (note that membership is not required in order to read the contents of the Dyalog forums). 6 | 7 | **Important:** *All of the tools and documents and other information contained in this repository are provided free of charge and without warranty of any kind. Dyalog will endeavour to correct any defects that are reported, but this is a community effort and not a supported product from Dyalog Ltd.* 8 | 9 | ### Acknowledgements 10 | Many thanks to *Jay Whipple III* for suffering through the first versions of the emulations - all APLX users who subsequently use these tools should be grateful for his pioneering spirit and prepare to buy him the drink of his choice at the next User Meeting! 11 | 12 | Thanks to *Dan Baronet* for contributing the "xfrpc" tools which he has worked on for decades. 13 | 14 | **NB:** The tools remain in a state of rapid flux. Feedback and contributions are very welcome! 15 | Did we say that already? 16 | 17 | ## Overview 18 | At the moment, the following resources are available or under development: 19 | 20 | **Updates to Dyalog v15.0:** Builds of Version 15.0 dated July 29th 2016 or later (that is 15.0.27982 or later, which appear in the second issue of the 15.0 installation images), include the following APLX-related improvements:” : 21 | 22 | * A fix to an issue with communication between the interpreter and the RIDE, which was causing slow execution of code when using RIDE as the development environment. 23 | * `⎕NREAD` now accepts `¯1` for the number of elements to read, meaning read to end of file 24 | * `⎕NREPLACE` accepts `¯1` as a position, meaning "the current position" 25 | 26 | **List of Differences:** A document containing a [list of differences](Differences.md) between APLX and Dyalog APL, and a discussion of strategies for dealing with them. 27 | 28 | **Emulations of APLX Features:** The file [APLX.dyalog](APLX.dyalog) defines a Dyalog namespace containing emulations for APLX primitives and system functions that are different or do not exist at all in Dyalog APL. 29 | 30 | **`]in` user command:** This user command is available with all standard installations of Dyalog APL v15.0 or later. It can import files in APL Transfer format (.ATF) that are created by the `)out` system command which is found in many APL systems, including APLX. For increasing amounts of online help, type `]?in`, `]??in` (and so on) in a Dyalog session. 31 | 32 | **Source Code Translation Tool:** The APLX workspaces `xfrpx.aws` and `xfrpcV5.aws` (for APLX v5) are APLX versions of Dan Baronet's xfrpc tool, which creates “enhanced” transfer files. The `]in` user command recognises these files and will perform translation of APLX statements into Dyalog equivalents, including references to the emulation functions. 33 | 34 | **Test Cases:** The file [TestAPLX.dyalog]() contains a collection of tests which put the emulations through their paces. If you have problems with any emulated features, a **VERY GOOD THING TO DO** is to contribute a failing test which someone will hopefully fix! 35 | 36 | ## Getting Set Up 37 | All the materials developed in this process are available as open source tools via github, and can be found at [http://github.com/Dyalog/aplx](). The easiest way to get hold of a local copy is to download the [zip package](https://github.com/Dyalog/aplx/archive/master.zip), if you want to participate actively or be able to easily view the revision history as new versions are developed, we suggest that you install a GUI front-end for git, for example [SourceTree](https://www.sourcetreeapp.com/) (which is used within the Dyalog development team) or use the [git gui](https://git-scm.com/downloads), and clone the repository. 38 | 39 | ### Running the Tests 40 | 41 | Once you have the materials downloaded (for example to a folder called `/Users/mkrom/aplx`), it is suggested that you load and run the test script: 42 | 43 | ⎕FIX 'file:///Users/mkrom/aplx/TestAPLX.dyalog' 44 | TestAPLX.Run 0 45 | APLX tests completed 46 | 47 | You can now edit the TestAPLX and APLX namespaces (the latter was brought in automatically thanks to a :Require statement in TestAPLX) and add new emulations or test cases - and submit proposals for extensions. 48 | 49 | ## Bringing your Code Across 50 | 51 | You export your workspace using `)OUT` in APLX, and then import it with `]in` under Dyalog APL, and make your own modifications to your source code in order to call the emulation functions. Alternatively, you can use the `xfrpc` tool to automatically modify the code to call emulation functions and make other changes to the code. 52 | 53 | The conversions are controlled by the file [xfrdefs.txt](xfrdefs.txt); if you are dissatisfied with these definitions and you are brave, you can experiment with adding lines to this file (in the section following `:APX`), or perhaps more likely, you can remove conversions that you do not wish to make. 54 | 55 | Once you have made any changes that you wish to make, copy the latest versions of the files `xfrcode.dws`, `APLX.dyalog`, and `xfrdefs.txt` from the repository to the Dyalog "ws" folder (`xfrcode.dws` will be there already, it is used by the `]in` user command, it is best to update it just in case you have an older version). 56 | 57 | Now we are ready to do the transfer: In APLX, `)Load` the workspace to be transferred, then: 58 | 59 | )COPY /Users/mkrom/aplx/xfrpcV5.aws 60 | SAVED 2014-02-01 23.21.35 61 | 62 | ∆xfrto '/Users/mkrom/myws' 63 | * XFR version 3.11 64 | 1243 objects transferred 65 | 66 | This will create the file myws.xpw. Next, start Dyalog APL and import the file. 67 | 68 | ]in /Users/mkrom/myws.xpw -trans=2 -replace 69 | * XFR version 3.88 70 | Using the external file "...[dyalog folder]...\ws\xfrdefs.txt" for translations. 71 | APX3.11 20160729 223656; WS=CLEAR WS 72 | #.APLX defined from file "...[dyalog folder]...\ws\APLX.dyalog" 73 | 1243 objects defined 74 | 75 | At this point, `APLX` will be a namespace containing the emulation functions, and `⎕PATH` will have been set to `#.APLX`. 76 | 77 | ## Running the same code in APLX and Dyalog APL 78 | The files ReadCovers/FixCovers are work in progress, with the intention of creating cover-functions in both APLX (for real system functions) and Dyalog APL (for emulation functions), so that the same application code can run on both systems. This will be useful for application which are in active development under APLX while migration work is in progress. This code is not yet working. 79 | 80 | ## Further Reading 81 | 82 | See the list and discussion of differences between APLX and Dyalog APL in the file [Differences.md](Differences.md). 83 | 84 | ## Comments and Questions 85 | 86 | Please send question and comments to [aplx@dyalog.com](mailto:aplx@dyalog.com), or the [Dyalog Forums](http://www.dyalog.com/forum/viewforum.php?f=37), or sign up to GitHub and submit comments and change requests there! 87 | -------------------------------------------------------------------------------- /TestAPLX.dyalog: -------------------------------------------------------------------------------- 1 | :Require file://./APLX.dyalog 2 | 3 | :Namespace TestAPLX ⍝ V1.01 4 | ⎕PATH←'#.APLX' 5 | 6 | ∇ {tests}Run DEBUG;⎕IO;⎕ML;FOLDER;fn;fns;z;m 7 | ⍝ Test the APLX emulation functions 8 | 9 | ⎕IO←1 ⋄ ⎕ML←1 10 | ⎕NUNTIE ⎕NNUMS 11 | ⎕FUNTIE ⎕FNUMS 12 | #.APLX.⎕EX'⍙MOUNTS' 13 | isWIN←'W'=⊃⊃'.' ⎕WG 'APLVersion' 14 | 15 | FOLDER←{(1-⌊/(⌽⍵)⍳'\/')↓⍵}{⊃⍵[⍵[;1]⍳⎕THIS;4]}↑5177⌶⍬ ⍝ find loaded files' location 16 | 17 | fns←'T'⎕NL ¯3 18 | :If 2=⎕NC'tests' 19 | :If (⊂tests)∊'list' '?' ⋄ ⎕←5↓¨fns ⋄ →0 ⋄ :EndIf 20 | tests←'Test_'∘,¨{1=≡⍵:,⊂⍵ ⋄ ⍵},tests 21 | :If ∨/m←~tests∊fns 22 | ('Unknown test(s): ',,⍕m/tests)⎕SIGNAL 11 23 | :EndIf 24 | fns←fns∩tests 25 | :EndIf 26 | 27 | :For fn :In fns 28 | ⍎fn 29 | :EndFor 30 | 31 | :If 0≠≢z←{(~1∊¨⍵⍷¨,/⎕VR¨fns)/⍵}'∆'#.APLX.⎕NL ¯3 32 | ⎕←'NB: ',(⍕≢z),' functions not tested:' 33 | ⎕←z 34 | ⎕←' ' 35 | :EndIf 36 | 37 | ⎕←'APLX tests completed' 38 | ∇ 39 | 40 | ∇ Test_Chars 41 | 42 | assert ∆a≡⎕UCS 96+⍳26 43 | assert 105086=+/⎕UCS ∆C 44 | assert 241=≢∪∆AV 45 | assert 225 97 65≡∆AF'aA⍺' 46 | 47 | assert 1 8 10 13≡⎕UCS ∆N ∆B ∆L ∆R 48 | 49 | assert'SMTWTFS'≡∆W[;1] 50 | assert'JFMAMJJASOND'≡∆M[;1] 51 | 52 | assert(2 3⍴'AB CDE')≡∆BOX'AB CDE' 53 | assert(2 3⍴'AB.CDE')≡'/.'∆BOX'AB/CDE' 54 | 55 | assert'A B C'≡∆DBR' A B C ' 56 | 57 | ∇ 58 | 59 | ∇ Test_Errors_Traps;⎕TRAP 60 | 61 | assert 4≡'42'∆EA'2+2⊣∆a' 62 | assert 42≡'42⊣∆a'∆EA'1÷0' 63 | 64 | assert(↑⎕DM)≡∆EM 65 | assert(¯1↓⊃,/⎕DM,¨⎕UCS 13)≡∆ERM 66 | 67 | ∇ 68 | 69 | ∇ Test_Misc 70 | 71 | :If isWIN 72 | assert'(System.DateTime)'≡⍕'.net'∆GETCLASS'System.DateTime' 73 | :EndIf 74 | 75 | assert ∆WSSIZE=2000⌶16 76 | 77 | assert 1 0 1≡∆VI'1 E 2' 78 | assert 1 0 2≡∆FI'1 E 2' 79 | 80 | assert 5 8 14 17≡{(⍵∊'-.')/⍳⍴⍵}∆TIME 81 | 82 | assert 3 1≡+/'→∊'∘.=,∆DISPLAY(1 2 3)'ABC' 83 | 84 | assert 7∊⍴∆AI 85 | 86 | :If isWIN 87 | assert 14=≢(⍕'.net'∆CALL'System.DateTime.Now')∩⎕D 88 | :EndIf 89 | 90 | :If isWIN 91 | assert 2≤+/'

'⍷∆HOST'dir' 92 | :Else 93 | ∘∘∘ 94 | :EndIf 95 | 96 | text←'Quack Quack Quack!' 97 | assert 2∊⍴ns.⎕NL-2 3⊣ns←0 ∆OV+z←↑'assert' 'text' 98 | assert z≡3 ∆OV ns 99 | 100 | assert(⍳7)≡∆DR¨(0 1 0 1)2 3.14 'A'(⎕NS'')('A' 1)# 101 | 102 | {}∆ERX L10 103 | assert~0∊⍴⎕TRAP 104 | ÷0 105 | L10:{}∆ERX 0 106 | assert 0∊⍴⎕TRAP 107 | 108 | assert 0=∆EQ_ 6 109 | assert 2=∆EQ_'dsa' 3 110 | assert'dsa'∆EQ_'dsa' 111 | assert(⊂'dsa')≡∆LSHOE'dsa' 112 | assert'dsa' 'dsa'≡1 1 1 0 1 1 1 ∆LSHOE'dsa dsa' 113 | assert 2≡2 ∆RSHOE'dsa' 2 114 | assert(2 3⍴'dsa')≡∆RSHOE'dsa' 'dsa' 115 | assert 3≡∆UP 3 4 116 | assert 1 2≡2 ∆UP⍳6 117 | 118 | new←0=#.APLX.⎕NC'⍙MOUNT' 119 | assert new≤0∊⍴∆MOUNT'' ⍝ this could be false if tests are run more than once. 'new' solves this 120 | {}∆MOUNT'dsa' 121 | assert((∆MOUNT'')∨.≠' ')≡10↑1 122 | 123 | ∇ 124 | 125 | ∇ Test_ImportExport;filename;text;data;NL;t;CR 126 | 127 | 1 ⎕NDELETE filename←FOLDER,'APLXtest.dat' 128 | 129 | (CR NL)←⎕ucs 13 10 130 | 131 | text←'hello',∆R,'world' 132 | text ∆EXPORT filename'txt' 133 | assert text≡t←∆IMPORT filename'txt' 134 | assert 1 0≡+/CR NL∘.=t←n_get filename ⍝ there should be only 1 CR 135 | 136 | ('hello',∆R,∆L,'world') ∆EXPORT filename'txt' ⍝ Now put a CRLF in 137 | assert text≡t←∆IMPORT filename'txt' ⍝ Should still get CR back 138 | 139 | text←'⍋⍒' 140 | text ∆EXPORT filename'utf8' 141 | assert 226 141 139 226 141 146≡⎕UCS n_get filename 142 | assert text≡t←∆IMPORT filename'UTF-8' 143 | 144 | data←{⍵⍪-⌿⍵}2 4⍴11300 13220 16550 19230,12450 12950 13620 13980 145 | data←'' 'Q1' 'Q2' 'Q3' 'Q4'⍪'Sales' 'Expenses' 'Profit',data 146 | data ∆EXPORT filename'csv' 147 | assert data≡t←∆IMPORT filename'csv' 148 | 149 | {0 ⎕NRESIZE ⍵ ⋄ ⎕NUNTIE ⍵}filename ⎕NTIE 0 150 | assert 0=⍴∆IMPORT filename'txt' 151 | 152 | ⎕NDELETE filename 153 | ∇ 154 | 155 | ∇ Test_CFiles;filename;tn;z 156 | 1 ⎕NDELETE filename←FOLDER,'APLXtest.dcf' 157 | 158 | tn←filename ⎕FCREATE 0 159 | 'Hello'∆FWRITE tn 0 ⍝ ⎕FAPPEND 160 | assert'Hello'≡∆FREAD tn 1 161 | 'There'∆FWRITE tn 1 ⍝ ⎕FREPLACE 162 | assert'There'≡∆FREAD tn 1 163 | z←∆FHOLD tn 1000000 164 | assert 1≡∆FDROP tn 0 ⍝ ⎕FDROP tn ¯1 165 | assert 1 1 1000000≡1 1 0 1/⎕FSIZE tn 166 | 167 | ⎕FUNTIE tn 168 | 1 ⎕NDELETE filename 169 | ∇ 170 | 171 | ∇ Test_NFiles;filename;z;tn;expect;text 172 | ⍝ /// Work in Progress 173 | 174 | 1 ⎕NDELETE filename←FOLDER,'APLXtest.dat' 175 | 176 | tn←filename ⎕NCREATE 0 177 | expect←⍬ 178 | text←'aA⍺0' 179 | text ∆NAPPEND tn 0 ⋄ expect,←¯1+∆AV⍳text ⍝ Untranslated 180 | assert text≡∆NREAD tn 0 4 0 181 | 182 | (8⍴0 1)∆NAPPEND tn 1 ⋄ expect,←2⊥8⍴0 1 ⍝ Bool 183 | assert(8⍴0 1)≡∆NREAD tn 1 8 4 184 | 42 ∆NAPPEND tn 2 ⋄ expect,←4↑42 ⍝ Int32 185 | assert(,42)≡∆NREAD tn 2 1 5 186 | 42 ∆NWRITE tn 2 5 ⍝ Test NWRITE does the same thing 187 | assert(,42)≡∆NREAD tn 2 1 5 188 | 189 | ¯0.1 ∆NAPPEND tn 3 ⋄ expect,←⎕UCS 80 ⎕DR ¯0.1 ⍝ Float64 190 | assert(,¯0.1)≡∆NREAD tn 3 1 9 191 | ¯0.1 ∆NREPLACE tn 9 3 ⍝ Test NREPLACE as well 192 | assert(,¯0.1)≡∆NREAD tn 3 1 9 193 | 194 | text ∆NAPPEND tn 4 ⋄ expect,←97 65 184 48 ⍝ Translated Char 195 | assert text≡∆NREAD tn 4 4 17 196 | text ∆NAPPEND tn 5 ⍝ UTF-16 197 | assert text≡∆NREAD tn 5 4 21 198 | expect,←,⌽⍉256 256⊤'UTF-16'⎕UCS text 199 | ⍝ Skip 6 (Float32) 200 | text ∆NAPPEND tn 8 ⋄ expect,←'UTF-8'⎕UCS text ⍝ UTF-8 201 | ⍝ assert text≡∆NREAD tn 8 4 29 202 | 203 | assert expect≡z←⎕UCS ⎕NREAD tn 80(⎕NSIZE tn)0 204 | filename ∆NERASE tn 205 | 206 | :Trap 22 207 | filename ⎕NTIE tn 208 | :Else 209 | assert'Unable to open file'{⍺≡(≢⍺)↑⍵}∆NERROR 210 | :EndTrap 211 | 212 | assert 1∊'TestAPLX.dyalog'⍷∆LIB FOLDER 213 | ∇ 214 | 215 | ∇ Test_SS;t;MAIL;vtv;⎕IO 216 | ⍝ Test suite for ∆SS 217 | 218 | ⎕IO←1 219 | assert 19=+/t←∆SS'A pixel color (or colour)' 'colour' 220 | assert(9 19,⍪1 2)≡t←∆SS'A pixel color (or colour)'('color' 'colour') 221 | ⎕IO←0 222 | assert(9 19,⍪1 2)≡1+t←∆SS'A pixel color (or colour)'('color' 'colour') 223 | 224 | ⎕IO←1 225 | assert(2 2⍴2 1 4 2)≡t←∆SS'.ABC.'('ABC' 'C.') 226 | assert(2 2⍴9 5 19 6)≡t←1 ∆SS'A pixel color (or colour)' 'colou?r' 227 | assert(3 3⍴9 5 1 19 6 1 42 4 2)≡t←1 ∆SS'A pixel color (or colour), such as light grey'('colou?r' 'gr[ea]y') 228 | assert(3 2⍴9 5 19 6 42 4)≡t←1 ∆SS'A pixel color (or colour), such as light grey' 'colou?r|gr[ea]y' 229 | MAIL←'Try e-mailing bill.gates@microsoft.com or, better, jim@microapl.co.uk' 230 | assert(2 2⍴15 24 52 18)≡t←1 1 ∆SS MAIL'\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b' 231 | assert(1 12 19 23,⍪2/3 4)≡t←1 ∆SS'

This is bold

' '<[^>]+>' 232 | assert'∆This is ∆bold∆∆'≡t←1 ∆SS'

This is bold

' '<[^>]+>' '∆' 233 | assert'This is bold'≡t←1 ∆SS'

This is bold

' '<[^>]+>' '' 234 | assert'[HTML:

]This is [HTML: ]bold[HTML: ][HTML:

]'≡t←1 ∆SS'

This is bold

' '<[^>]+>' '[HTML: \0]' 235 | 236 | assert'abc..def..'≡∆SS('abc',∆R,'def',∆R)∆R'..' 237 | 238 | vtv←'bill.gates@microsoft.com' 'jim@microapl.co.uk' 239 | ⍝ assert vtv≡t←2 1 ∆SS MAIL'\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b' 240 | ∇ 241 | 242 | ∇ assert ok;caller 243 | caller←⎕IO+1 244 | :If ~ok 245 | ⎕←'*** Assertion failed at ',(caller⊃⎕SI),'[',(⍕caller⊃⎕LC),']: ' 246 | ⎕←' ',(⎕CR caller⊃⎕SI)[1+caller⊃⎕LC;] 247 | ⎕←' ' 248 | 'assertion failed'⎕SIGNAL DEBUG/11 249 | :EndIf 250 | ∇ 251 | 252 | expecterror←{ 253 | 0::⎕SIGNAL(⍺≡⊃⎕DMX.DM)↓11 254 | z←⍺⍺ ⍵ 255 | ⎕SIGNAL 11 256 | } 257 | 258 | ⍝ We should provide utilities to detect potential problems. 259 | ⍝ For example ⎕WA← is illegal in Dyalog but not in APLX. 260 | ⍝ A[2] B[3] is fine in APLX but an INDEX error in Dyalog 261 | 262 | ⍝ The first one can be solved by doing 263 | 264 | ⍝ ]locate (⎕AI|⎕AV|⎕D|⎕A|⎕EM|⎕B|⎕C|⎕CL|⎕ERM|⎕I|⎕ID|⎕L|⎕LC|⎕LER|⎕M|⎕N|⎕NULL|⎕R|⎕SI|⎕T|⎕TC|⎕THIS|⎕TIME|⎕TS|⎕T|⎕UL|⎕W|⎕WA)← -pat -excl=c -in 265 | 266 | ⍝ The simple cases of the 2nd one could be 267 | 268 | ⍝ ]locate "(⍺\[[ ;0-9]+\]){2,}" -pat -exc=c 269 | 270 | :EndNamespace 271 | -------------------------------------------------------------------------------- /Differences.md: -------------------------------------------------------------------------------- 1 | # Differences between APLX and Dyalog APL 2 | Both APL systems are variations on IBM APL2, and most computational code will work unchanged, with automatic translation, or minor manual changes. This repository contains tools to perform automated translation and provide emulations of frequently-used features that are missing from Dyalog APL. 3 | 4 | This document lists the emulations provided, the limitations that we are currently aware of, and a discussion of differences that we are unlikely to address unless someone explains why we should. It is very much work in progress; and if you find that there are features that you desperately need, please get in touch to discuss. Contributions of enhancements or additions to the emulations, or simply failing test cases, are all very welcome. 5 | 6 | ## Important Differences 7 | In addition to the emulated features, and language constructs which can be automatically transformed, there are a number of features of APLX which are not supported at all in Dyalog APL, and which we are not currently planning to emulate: 8 | 9 | * The `⎕WI` user interface tool is not provided. Under Microsoft Windows, Dyalog APL provides a similar tool called `⎕WC`. An emulator for `⎕WI`, based on `⎕WC`, is available from Joachim Hoffman; an example of an application converted this tool can be found at [https://condim.at/downloads](). 10 | * Dyalog is developing a cross-platform emulator for `⎕WC` , which will work on all platforms and also run as a web server, expected to become available for testing in the 2nd half of 2024. 11 | 12 | * `⎕CHART` is not emulated: Dyalog provides SharpPlot and interfaces to Javascript-based charting as alternatives. 13 | * Object Oriented features in Dyalog are in many ways more powerful than those in APLX, but they are different. There is currently no support for external Java and Ruby objects. 14 | * Dyalog APL essentially provides the same native and component file functionality as APLX, but there is no concept of library numbers, and Dyalog APL insists that component files have positive tie numbers, while native file ties are negative. See the separate sections below for further discussion. 15 | * The R interface is significantly different but should provide the same capabilities. 16 | 17 | ###Language Differences 18 | There are a handful of core language differences which are difficult to translate automatically and will probably require manual recoding: 19 | 20 | * Brackets bind differently: `A[2]B[1]` is equivalent to `(A[2])(B[1])` in APLX, but `((A[2])B)[1]` in Dyalog APL. It is difficult to detect all cases of this by searching source code; Dyalog is experimenting with tools which will be able to detect the issue at runtime. 21 | * Slashes (`/` and `⌿`) are strictly operators in APLX, but in Dyalog APL they are functions when there is an array on the left. This gives different results when slashes are combined with other operators. For example `1 0 1/¨⍳3` returns `(1 1)(2 2)(3 3)` in APLX and `(,1)⍬(,3)` in Dyalog APL. The equivalent expression in Dyalog APL would be `1 0 1∘/¨⍳3`. 22 | * In Dyalog APL, with the default Migration Level (`⎕ML←1`), monadic `↑` is *mix*, `⊃` is *first*, and `≡` (*depth*) works slightly differently from APLX. 23 | * Partitioned enclose (dyadic `⊂`), works differently from APLX unless ⎕ML←3. 24 | * `⍎` accepts system commands (`X←⍎')SYMBOLS'`) in APLX but not in Dyalog APL. System functions and I-Beams can provide the same functionality but will need recoding. In this particular case, just delete the code - Dyalog APL has a dynamic Symbol Table and you do not need to worry about how big it is. 25 | * Monadic Left Tack (`⊣`) returns a shy result of `0 0⍴0` in APLX, in Dyalog it returns the right argument unchanged. `{}` can be used to "sink" a result. 26 | * Dyalog APL does not support `⍺` picture formatting, and `⎕FC` cannot be used to control formatting. 27 | * `⍞` works differently: In APLX the prompt (if any) is replaced according to `⎕PR` 28 | * `⎕RL` is richer in Dyalog APL, allowing the selection of several different random number generators. In Dyalog APL, `⎕RL←0` generates a "truly" random seed. APLX code should work unchanged but seed-setting functions should be examined and random sequences may be different 29 | * Note that the default comparison tolerance in (`⎕CT`) in APLX is 1E¯13, but 1E¯14 in Dyalog APL; this could conceivably cause computational differences; you may need to set it explicitly. 30 | * APLX variable names can contain a high minus (`¯`), this not allowed in Dyalog APL 31 | * Dyalog APL does not have 64-bit integers, even in the 64-bit versions. 32 | * Dyalog APL does not allow "undefined" assignments to system variables (`⎕WA←3`). 33 | * There are some differences in Control Structures (detailed in a separate section in this document). 34 | 35 | ###Control structures 36 | There are some significant differences in control structures: 37 | 38 | * APLX `:Try` is `:Trap` in Dyalog APL, and `:CatchAll` is `:Else` (converted) 39 | * APLX `:CatchIf` takes a Boolean argument. There is no catching on a specific error (number). The equivalent of `:Case 11` in a Dyalog `:Trap` statement would be `:CatchIf 11=↑⎕LER` in APLX. 40 | * `:Repeat` accepts a number of repetitions in APLX, but not in Dyalog APL 41 | * `:Leave` may take a label as argument in APLX, not in Dyalog APL 42 | 43 | ###Component Files 44 | Dyalog APL has no concept of numeric libraries, and component file tie numbers must be positive. The following differences are worth noting, many of which could be handled by additional emulation functions: 45 | 46 | * `⎕FDUP` in APLX is `⎕FCOPY` in Dyalog. The access code is different (16384 vs 4096). 47 | * When creating a file Dyalog adds the extension `.dcf` if no extension is provided. 48 | * `⎕FRDCI` reports the time when the component was written in seconds since 2000/1/1. Dyalog reports it in 1/60th of a second since 1970/1/1 49 | * `⎕FRENAME` accepts a filename as right argument under APLX, but not in Dyalog APL. 50 | * `⎕FSIZE` in APLX has a 5th element which gives the unused space in the file. The 4th element may be 0 in APLX meaning "no limit". 51 | * `⎕FRDFI`, `⎕FCSIZE` and `⎕FDELETE` do not exist in Dyalog APL (but `⎕NDELETE` can be used in place of `⎕FDELETE`). 52 | 53 | ###Native files 54 | Note that an update to Dyalog 15.0 was released at the beginning of August, with support for ¯1 in the arguments to `⎕NREPACE (used by ∆NWRITE)` (position of ¯1 means write to current position) and `⎕NREAD` (count of ¯1 means read to end of file). 55 | 56 | * The emulation functions for `⎕NWRITE, ⎕NAPPEND, ⎕NREPLACE, ⎕NREAD` support nearly all APLX conversion codes. However, `∆NREAD` cannot read a specific number of elements counts for variable-length encodings (UTF-8 and UTF-16). 57 | * `⎕NCREATE` does not support a 2nd element (permissions) in the right argument 58 | * `∆NERROR` attempts to emulate `⎕NERROR`, but the error messages will not be identical, and Native File errors are not separated from other errors. 59 | 60 | ###Classes 61 | 62 | Unfortunately, the Object Oriented functionality of the two systems are quite different, although many capabilities are present in both systems. 63 | 64 | The following emulations work for APL objects and Microsoft.NET objects: 65 | 66 | * `⎕GETCLASS`: for APL and .Net only you can use execute (`⍎`) 67 | * `⎕CLASSNAME`: format (`⍕`) will display a string of the class name. 68 | 69 | Many APLX OO functions have no equivalents in Dyalog APL: 70 | 71 | `⎕DS, ⎕IC, ⎕MIXIN, ⎕UNMIX, ⎕RC, ⎕RECLASS, ⎕REPARENT`. 72 | 73 | ## Working Emulations 74 | 75 | After all the bad news: fairly decent emulations are provided for a large number of the most frequently used system functions. These functions have names beginning with ∆, in the APLX namespace. For example, `APLX.∆a` emulates `⎕a` (the lowercase letters from a-z): 76 | 77 | ∆a ∆AF ∆AI ∆AV ∆B ∆BOX ∆C ∆CALL 78 | ∆DBR ∆DISPLAY ∆DR ∆EA ∆EM ∆ERM 79 | ∆EXPORT ∆FI ∆GETCLASS ∆HOST ∆I 80 | ∆IMPORT ∆L ∆LIB ∆M ∆N 81 | ∆NAPPEND ∆NERASE ∆NREAD ∆NREPLACE ∆NWRITE 82 | ∆OV ∆R ∆SS ∆TIME ∆VI ∆W ∆WSSIZE 83 | 84 | ### Replacements for ⎕ML-Dependent Primitives 85 | 86 | Emulation functions are provided for the primitives which can be made to behave the same way as APLX by setting ⎕ML. This allows a migrated application to be automatically converted to run with the default Dyalog Migration Level of 1, and for the use of these functions to be replaced over time. 87 | 88 | ∆EQ_ (≡), ∆LSHOE (⊂), ∆RSHOE (⊃), ∆UP (↑) 89 | 90 | ### Emulation Not Required 91 | 92 | We currently believe that the following system functions do not need emulation (in the vast majority of uses): 93 | 94 | ⎕CR ⎕D ⎕DL ⎕FX ⎕NC ⎕NCREATE ⎕RESIZE ⎕SIZE ⎕NTIE 95 | ⎕NULL ⎕PFKEY ⎕THIS ⎕STOP ⎕TRACE ⎕TS ⎕UCS ⎕A 96 | 97 | ### Known Limitations of Emulations 98 | * Native file functions do not handle conversion codes for explicit byte swapping, 64-bit integers or single-precision (4-byte) floats 99 | * `∆IMPORT` and `∆EXPORT` do not handle the `slk` format 100 | * `∆CALL` only handles Microsoft.Net 101 | * `∆ERX` This emulation is very partial; it is not really possible to fully emulate ⎕ERX 102 | * `∆FDROP (⍗)` Can only drop the last component of a file 103 | * `∆FHOLD (⍐)` Monadic use only (⎕FRESIZE) 104 | * `∆FREAD (⍇)` Monadic use only, and passnumbers are ignored 105 | * `∆FWRITE (⍈)` User ID and passno ignored 106 | * `∆MOUNT` There is no real support for library numbers 107 | * `∆GETCLASS` Microsoft.NET only 108 | * `∆HOST` No timeout, and the format of results is nested 109 | * `∆NERROR` Error message texts will be different, and sometimes reflect other recent errors not related to native files 110 | * `∆SS` will hopefully become complete, but is work in progress, we are not 100% sure we have all the cases covered, especially not regular expression cases 111 | 112 | ##Other Issues 113 | 114 | This is mostly a list of features which are not currently emulated, and comments on differences between system functions in the two systems which have not been discussed already. Please contact us to help prioritise further work on emulations, if there is something you really need: 115 | 116 | * ⎕AT Object Attributes 117 | * ⎕CC Console Control 118 | * ⎕CS Provides similar functionality to ⎕ML, but completely different and mostly(?) irrelevant 119 | * ⎕CL can be replaced by (⍬⍴⎕LC) 120 | * ⎕CLASS has 2 nested vectors in Dyalog 121 | * ⎕CLASSES is missing but (⎕NL 9) provides similar functionality in Dyalog APL 122 | * ⎕CONF has no equivalent in Dyalog 123 | * ⎕DR Similar but the exact functionality is different 124 | * ⎕EDIT Similar but not identical to Dyalog's ⎕ED 125 | * ⎕EVAL No direct support in Dyalog APL, but Microsoft.Net and R objects are easy to access using other means. 126 | * ⎕EX: APLX reports whether the name was erased, Dyalog APL whether it is now free for use. 127 | * ⎕HC Hard Copy 128 | * ⎕ID System ID number is an unknown concept in Dyalog APL 129 | * ⎕MC - but since Dyalog has full Unicode support, there is no "Missing Character" 130 | * ⎕NA is similar but has some differences, especially in character type conversions 131 | * ⎕NTYPE is MacOS specific in APLX and not supported at all in Dyalog APL 132 | * ⎕PFKEY is similar but not supported on all platforms in Dyalog APL. 133 | * ⎕PROFILE is similar but different. 134 | * ⎕SI could probably be emulated if there is sufficient demand (see ⎕SI, ⎕LC & ⎕STACK) 135 | * ⎕SQL must be replaced by calls to the functions in distributed workspace SQAPL 136 | * ⎕SV* Shared variables exist but are considered obsolete in Dyalog APL, and are not used for APs (which are also considered obsolete). 137 | * ⎕OV: Some emulation is provided through ∆OV, but Dyalog namespaces are significantly more powerful. 138 | * ⎕STOP & ⎕TRACE with a left argument of zero clear all stop/trace bits in APLX, but set a stop/trace on line [0] in Dyalog APL. Use ⍬ as a left argument in Dyalog APL. 139 | * ⎕SYMB Dyalog APL has no symbol table limitations so this function is unnecessary 140 | * ⎕TC* (BEL, BS, DEL, ESC, ...) are not provided (would be easy to emulate). The effect of displaying control characters in the session may differ. For example, ⎕TCBEL will produce a audible sound in APLX but not in Dyalog APL (but there are other ways to produce sound). 141 | * ⎕TF produces a simple string of the representation of a function or variable in APLX; user commands can be used for this in Dyalog APL. 142 | * ⎕TR Dyalog is a Unicode system so no translation of character data is done when sharing it with the outside world. 143 | * ⎕TT terminal Type - Does not exist in Dyalog APL. 144 | * ⎕SETUP does not exist but many of the facilities provided have simple alternatives, at least for Microsoft.NET (Using, ByRef, Version) 145 | * ⎕UL User Load - not supported 146 | 147 | If one of these functions is critical to your application, please contact Dyalog Ltd. 148 | -------------------------------------------------------------------------------- /APLX.dyalog: -------------------------------------------------------------------------------- 1 | :Namespace APLX 2 | ⍝ Dyalog cover functions for APLX V1.12 3 | 4 | ⍝ This namespace can be added as is in a workspace or individual items )COPYed. 5 | ⍝ If the whole workspace is added ⎕PATH should be set to '#.APLX' in order to get at the code. 6 | ⍝ If only items are copied the namespace should be erased if it was brought in whole. 7 | 8 | ∇ Z←∆a ⍝ Emulate APLX ⎕a 9 | Z←'abcdefghijklmnopqrstuvwxyz' 10 | ∇ 11 | 12 | ⍝ ⎕AV, based on ⎕UCS ⎕AV in APLX 13 | ⍝ Note that SOME control characters (1 2 3 4 5 6 8 10 13) are repeated 14 | ⍝ in the 2nd half of ⎕AV, and SPACE appears 7x at (0 32 128 222 223 224 254) 15 | ∆av ← 32 1 2 3 4 5 6 9040 8 9047 10 9031 9032 13 9073 9074 16 | ∆av,←9042 9035 9021 9033 8854 9055 9014 9067 9038 9045 9024 9023 9053 9054 33 9017 17 | ∆av,← 32 168 41 60 8804 61 62 93 8744 94 8800 247 44 43 46 47 18 | ∆av,← 48 49 50 51 52 53 54 55 56 57 40 91 59 215 58 92 19 | ∆av,← 175 9082 8869 8745 8970 8714 95 8711 123 9075 8728 39 9109 124 8868 9675 20 | ∆av,← 42 63 9076 8968 126 8595 8746 9077 8835 8593 8834 8592 8866 8594 8805 45 21 | ∆av,←8900 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 22 | ∆av,← 80 81 82 83 84 85 86 87 88 89 90 8710 8867 9066 36 125 23 | ∆av,← 32 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 24 | ∆av,←9484 9488 9492 9496 9472 9474 9532 9500 9508 9524 9516 27 28 205 30 31 25 | ∆av,← 34 35 37 38 64 163 96 8801 8802 9079 9080 9019 9026 9060 9061 9015 26 | ∆av,← 196 197 199 201 209 214 220 225 224 226 228 227 229 231 233 232 27 | ∆av,← 234 235 237 236 238 239 241 243 242 244 246 245 250 249 251 252 28 | ∆av,← 192 195 213 338 339 198 230 9068 216 248 191 161 223 255 32 32 29 | ∆av,← 32 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 30 | ∆av,← 112 113 114 115 116 117 118 119 120 121 122 9049 200 8364 32 127 31 | ∆av←⎕UCS ∆av 32 | 33 | ⍝ ⎕NWRITE conversion code 4 table: 34 | ∆x4 ← 32 32 32 32 32 32 32 210 8 211 10 212 213 13 139 138 35 | ∆x4,← 148 147 178 179 180 181 167 162 150 149 153 154 169 171 33 142 36 | ∆x4,← 32 168 41 60 136 61 62 93 159 94 172 247 44 43 46 47 37 | ∆x4,← 48 49 50 51 52 53 54 55 56 57 40 91 59 215 58 92 38 | ∆x4,← 175 184 131 240 152 185 95 146 123 188 176 39 140 124 130 177 39 | ∆x4,← 42 63 189 151 126 135 158 190 156 134 155 132 164 133 137 45 40 | ∆x4,← 170 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 41 | ∆x4,← 80 81 82 83 84 85 86 87 88 89 90 145 202 174 36 125 42 | ∆x4,← 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 43 | ∆x4,← 218 204 192 217 206 219 207 195 221 193 194 27 32 205 32 32 44 | ∆x4,← 34 35 37 38 64 163 96 166 187 186 165 0 0 253 246 222 45 | ∆x4,← 196 197 199 201 209 214 220 225 224 226 228 227 229 231 233 232 46 | ∆x4,← 234 235 237 236 238 239 241 243 242 244 246 245 250 249 251 252 47 | ∆x4,← 208 182 183 32 32 198 230 203 216 248 191 161 223 255 32 32 48 | ∆x4,← 32 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 49 | ∆x4,← 112 113 114 115 116 117 118 119 120 121 122 254 200 128 32 32 50 | ∆x4←⎕UCS ∆x4 51 | 52 | ∆AF←{⎕IO←0 ⋄ 0∊1↑0⍴⍵:∆av[⍵] ⋄ ∆av⍳⍵} 53 | 54 | ∇ r←∆AI ⍝ ⎕AI in APLX 55 | r←7↑r+1000×4↑0=1↑r←⎕AI 56 | ∇ 57 | 58 | ∇ r←∆AV ⍝ Emulate APLX ⎕AV: Note that it does not have 256 distinct elements 59 | r←∆av 60 | ∇ 61 | 62 | ∇ Z←∆B ⍝ Emulate APLX ⎕B 63 | Z←⎕UCS 8 64 | ∇ 65 | 66 | ∇ r←{la}∆BOX ra;sep;fill;b;max;⎕ML 67 | ⍝ ⎕BOX in APLX 68 | :If 900⌶⍬ ⋄ la←''⍴0⍴ra ⋄ :EndIf 69 | (sep fill)←2↑la 70 | ⎕ML←0 71 | :If 2∊⍴⍴ra ⍝ matrix case 72 | b←,1,⌽∨\⌽fill≠ra ⋄ r←1↓b/,sep,ra 73 | :Else ⍝ vector case 74 | max←⌈/⊃,/⍴¨r←1↓¨(r∊sep)⊂r←sep,ra 75 | r←↑max↑¨r,¨⊂max⍴fill 76 | :EndIf 77 | ∇ 78 | 79 | ∇ Z←∆C ⍝ Emulate APLX ⎕C 80 | Z←⎕UCS 32 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 9484 9488 9492 9496 9472 9474 9532 9500 9508 9524 9516 27 28 205 30 31 127 81 | ∇ 82 | 83 | ∇ r←env ∆CALL args;⎕USING 84 | ⍝ Simulate ⎕CALL in APLX 85 | 'Only .Net supported'⎕SIGNAL 11/⍨'.net'≢env 86 | ⎕USING←'' 87 | :If 1=≡,args 88 | r←⍎args 89 | :Else 90 | r←(⍎1⊃args)2⊃args 91 | :EndIf 92 | ∇ 93 | 94 | ∇ Z←∆DR data ⍝ ⎕DR in APLX 95 | →0/⍨Z←1 2 3 4 0[1 3 5 0⍳10|⎕DR data] 96 | Z←5 6 7[9.1 2.1⍳⎕NC⊂'data'] 97 | ∇ 98 | 99 | ∆DBR←{⍺←' ' ⋄ 1↓(r⍲1⌽r←v∊⍺)/v←⍺,⍵} 100 | 101 | ∆DISPLAY←{⎕IO ⎕ML←0 ⍝ Boxed display of array. 102 | ⍺←1 ⋄ chars←⍺⊃'..''''|-' '┌┐└┘│─' ⍝ ⍺: 0-clunky, 1-smooth. 103 | tl tr bl br vt hz←chars ⍝ Top left, top right, ... 104 | 105 | box←{ ⍝ Box with type and axes. 106 | vrt hrz←(¯1+⍴⍵)⍴¨vt hz ⍝ Vert. and horiz. lines. 107 | top←(hz,'⊖→')[¯1↑⍺],hrz ⍝ Upper border with axis. 108 | bot←(⊃⍺),hrz ⍝ Lower border with type. 109 | rgt←tr,vt,vrt,br ⍝ Right side with corners. 110 | lax←(vt,'⌽↓')[¯1↓1↓⍺],¨⊂vrt ⍝ Left side(s) with axes, 111 | lft←⍉tl,(↑lax),bl ⍝ ... and corners. 112 | lft,(top⍪⍵⍪bot),rgt ⍝ Fully boxed array. 113 | } 114 | 115 | deco←{⍺←type open ⍵ ⋄ ⍺,axes ⍵} ⍝ Type and axes vector. 116 | axes←{(-2⌈⍴⍴⍵)↑1+×⍴⍵} ⍝ Array axis types. 117 | open←{(1⌈⍴⍵)⍴⍵} ⍝ Expose null axes. 118 | trim←{(~1 1⍷∧⌿⍵=' ')/⍵} ⍝ Remove extra blank cols. 119 | type←{{(1=⍴⍵)⊃'+'⍵}∪,char¨⍵} ⍝ Simple array type. 120 | char←{⍬≡⍴⍵:hz ⋄ (⊃⍵∊'¯',⎕D)⊃'#~'}∘⍕ ⍝ Simple scalar type. 121 | line←{(6≠10|⎕DR' '⍵)⊃' -'} ⍝ underline for atom. 122 | 123 | { ⍝ Recursively box arrays: 124 | 0=≡⍵:' '⍪(open ⎕FMT ⍵)⍪line ⍵ ⍝ Simple scalar. 125 | 1 ⍬≡(≡⍵)(⍴⍵):'∇' 0 0 box ⎕FMT ⍵ ⍝ Object rep: ⎕OR. 126 | 1=≡⍵:(deco ⍵)box open ⎕FMT open ⍵ ⍝ Simple array. 127 | ('∊'deco ⍵)box trim ⎕FMT ∇¨open ⍵ ⍝ Nested array. 128 | }⍵ 129 | } 130 | 131 | ∇ Z←V ∆EA P ⍝ Emulate APLX ⎕ea 132 | Z←⍬ 133 | :Trap 0 134 | :Trap 85 ⍝ ignore no result 135 | Z←⎕RSI[⎕IO].{0(85⌶)⍵}P 136 | :EndTrap 137 | :Else 138 | :Trap 85 139 | Z←⎕RSI[⎕IO].{0(85⌶)⍵}V 140 | :EndTrap 141 | :EndTrap 142 | ∇ 143 | 144 | ∇ Z←∆EM;⎕ML ⍝ Emulate APLX ⎕EM 145 | ⎕ML←1 ⋄ Z←↑⎕DM 146 | ∇ 147 | 148 | ∆EQ_←{⎕ML←2 ⋄ ⍺←⊢ ⋄ ⍺≡⍵} ⍝ ≡ 149 | 150 | ∇ Z←∆ERM ⍝ Emulate APLX ⎕ERM 151 | Z←¯1↓↑,/⎕DM,¨⎕UCS 13 152 | ∇ 153 | 154 | ∇ ∆ERX←∆ERX ⍝ Emulate APLX ⎕ERX 155 | ∆ERX←⍎'⎕SHADOW''⎕TRAP''⋄(⎕TRAP←{1<≢∊⍵:⍵ ⋄ (×⍵)⍴⊂0 ''E'' (''→'',⍕⍵)}',⍕,{')⊢⎕TRAP'} 156 | ∇ 157 | 158 | ∇ Z←data ∆EXPORT V;file;type;⎕IO;sep 159 | ⍝ Emulate APLX ⎕export 160 | ⎕IO←1 161 | :If 1=≡,V ⋄ V←V({(-⊥⍨'.'≠⍵)↑⍵}V) ⋄ :EndIf ⍝ use extension as type if simple string 162 | (file type)←L@2⊢V ⍝ Lowercase 163 | 164 | :Select type 165 | ⍝ data can be anything. It must be formatted if not character already. 166 | :CaseList 'txt' 'utf8' 'utf-8' 'utf16' 'utf-16' 167 | data←n_fmt data 168 | type←1⊃'txt' '\d+'⎕S'Windows-1252' 'UTF-&'⊢type 169 | :CaseList 'csv' 'tsv' 170 | :If 2≠≢⍴data 171 | :OrIf 0 2∊⍨10|⎕DR data 172 | 'Data must be nested or numeric matrix'⎕SIGNAL 11 173 | :EndIf 174 | data←n_fmt¨data 175 | sep←('ct'⍳L 1⊃type)⊃',',⎕UCS 9 176 | data←data ⎕CSV⍠'Separator'sep⊢'' 177 | type←'Windows-1252' 178 | :Case 'xml' 179 | data←⎕XML data 180 | type←'UTF-8' 181 | :Else 182 | 'Unknown file type'⎕SIGNAL 11 183 | :EndSelect 184 | data←'¯'⎕R'-'⊢data 185 | data type ⎕NPUT file 1 186 | Z←0 0⍴'' 187 | ∇ 188 | 189 | n_fmt←{1↓,(⎕UCS 10),⎕FMT'.*'⎕R'&'⍠'EOL' 'CR'⍠'NEOL' 1⍤1⍕data} 190 | 191 | ∇ r←{la}∆FDROP arg 192 | ⍝ ⍗ in APLX 193 | :If 900⌶⍬ 194 | :If 0=1↓2↑arg ⍝ 0=drop last component 195 | ⎕FDROP(1↑arg),¯1 ⋄ r←1 196 | :Else 197 | 'Unable to drop from middle of file'⎕SIGNAL 11 198 | :EndIf 199 | :Else 200 | . 201 | :EndIf 202 | ∇ 203 | 204 | ∇ {r}←{opt}∆FHOLD fs 205 | ⍝ File resize/hold in APLX 206 | :If 900⌶r←0 0⍴0 207 | (1↓fs)⎕FRESIZE 1↑fs 208 | :Else 209 | ÷'hold not implemented' 210 | :EndIf 211 | ∇ 212 | 213 | ∇ r←∆FI y ⍝ Emulate ⎕FI under APLX 214 | r←(1+⎕IO)⊃⎕VFI y 215 | ∇ 216 | 217 | ∇ r←{opt}∆FREAD arg 218 | ⍝ ⎕← file fn 219 | ⍝ arg is {[LIBRARY]} FILE, COMPONENT {,USER, PASSWORD} 220 | ⍝ we only implement FILE (tie), CPT 221 | :If 900⌶⍬ 222 | :If 0=1↑1↓arg ⋄ arg[1+⎕IO]←¯1+1↑1↓⎕FSIZE 1↑arg ⋄ :EndIf ⍝ 0 cpt= last cpt 223 | r←⎕FREAD arg 224 | :Else 225 | ÷'not implemented' 226 | :EndIf 227 | ∇ 228 | 229 | ∇ {r}←data ∆FWRITE fc;file;cpt 230 | ⍝ File write in APLX 231 | r←⍬ 232 | (file cpt)←fc 233 | :If cpt=0 234 | data ⎕FAPPEND file 235 | :Else 236 | data ⎕FREPLACE fc 237 | :EndIf 238 | ∇ 239 | 240 | ∇ r←{env}∆GETCLASS name;⎕USING 241 | ⍝ ⎕GETCLASS in APLX 242 | :If 900⌶⍬ ⋄ env←'' ⋄ :EndIf 243 | :If '.net'≡env 244 | ⎕USING←'' 245 | :EndIf 246 | r←⍎name 247 | ∇ 248 | 249 | ∇ r←{timeout}∆HOST string;v;⎕ML 250 | ⍝ ⎕HOST in APLX 251 | ⍝ timeout feature is not enabled 252 | ⎕ML←1 253 | v←⊃⊃'.'⎕WG'APLVersion' 254 | :If ''≡string ⍝ return OS type 255 | r←('WLMA'⍳v)⊃'WINDOWS' 'LINUX' 'MACOS' 'AIX' '?unknown' 256 | :Else 257 | r←1↓↑,/(⎕UCS 13),¨⎕SH((∊string)~'↑↓'),(v≠'W')/' 2>&1; exit 0' 258 | ⍝ Always on client, Never fail, return error messages as output 259 | :EndIf 260 | ∇ 261 | 262 | ∇ Z←∆I ⍝ ⎕I (Idle) in APLX 263 | Z←⎕UCS 1 264 | ∇ 265 | 266 | ∇ Z←∆IMPORT V;file;type;⎕IO;Post;_ ⍝ Emulate APLX ⎕import 267 | ⎕IO←1 268 | :If 1=≡,V ⋄ V←V({(-⊥⍨'.'≠⍵)↑⍵}V) ⋄ :EndIf ⍝ use extension as type if simple string 269 | (file type)←L@2⊢V 270 | 271 | :Select type 272 | :CaseList 'txt' 'utf8' 'utf-8' 'utf16' 'utf-16' 273 | _←1⊃'txt' '\d+'⎕S'Windows-1252' 'UTF-&'⍠1⊢type 274 | Post←''⎕R''⍠'EOL' 'CR'⍠'NEOL' 275 | :CaseList 'csv' 'tsv' 276 | _←⊢ 277 | Post←⎕CSV⍠'Separator'(('ct'=1⊃type)/',',⎕UCS 9){⍵'S'} 278 | :Case 'xml' 279 | _←⊢ 280 | Post←⎕XML 281 | :Else 282 | 'Unknown file type'⎕SIGNAL 11 283 | :EndSelect 284 | Z←Post 1⊃_ ⎕NGET file 285 | ∇ 286 | 287 | ∇ Z←∆L ⍝ Emulate APLX ⎕L 288 | Z←⎕UCS 10 289 | ∇ 290 | 291 | ∇ r←∆LIB path;⎕ML;wild;⎕IO ⍝ Emulate APLX ⎕LIB 292 | ⍝ Extension: allows filtering of terminal node, e.g. ∆lib 'c:\temp\*.csv' 293 | ⎕ML←1 ⋄ ⎕IO←1 294 | wild←'*'∊path 295 | r←↑↑(⎕NINFO⍠1)path,((wild∨(¯1↑path)∊'/\')↓'/'),wild↓'*' 296 | r←(1+(≢path)-⌊/(⌽path)⍳'/\')↓⍤1⊢r 297 | ∇ 298 | 299 | ∆LSHOE←{⍺←⊢ ⋄ ⎕ML←3 ⋄ ⍺⊂⍵} ⍝ ⊂ 300 | 301 | ∇ r←∆M 302 | r←↑⍤0⊢'JANUARY' 'FEBRUARY' 'MARCH' 'APRIL' 'MAY' 'JUNE' 'JULY' 'AUGUST' 'SEPTEMBER' 'OCTOBER' 'NOVEMBER' 'DECEMBER' 303 | ∇ 304 | 305 | ∇ r←∆MOUNT arg;id;sha;shm;max 306 | ⍝ Simulate ⎕MOUNT in APLX 307 | :If 0=⎕NC id←'#.APLX.⍙MOUNTS' ⋄ ⍎id,'←10 0⍴⎕a' ⋄ :EndIf 308 | :If 0∊⍴arg ⋄ r←⍎id 309 | :Else 310 | sha←⍴arg←(¯2↑1 1,⍴arg)⍴arg 311 | max←0 1×sha⌈shm←⍴r←⍎id 312 | r←(max⌈shm)↑r 313 | r[⍳⍴arg]←arg←(max⌈sha)↑arg 314 | ⍎id,'←r' 315 | :EndIf 316 | ∇ 317 | 318 | ∇ Z←∆N ⍝ ⎕N in APLX 319 | Z←⎕UCS 1 320 | ∇ 321 | 322 | ∇ r←∆NERROR 323 | ⍝ Similar to APLX ∆NERROR, but won't return the same texts 324 | :If 0=≢3⊃⎕DMX.OSError 325 | r←'Insufficient data available' 326 | :Else 327 | r←⎕DMX.Message,': ',(⎕IO+2)⊃⎕DMX.OSError 328 | :EndIf 329 | ∇ 330 | 331 | ∇ {r}←data ∆NAPPEND arg;tieno;type;conv 332 | ⍝ Emulate APLX ⎕NAPPEND 333 | 334 | (tieno conv)←arg,(≢arg)↓0 0 335 | 336 | type←n_type conv 337 | data←data n_data conv 338 | data ⎕NAPPEND tieno type 339 | r←0 0⍴0 340 | ∇ 341 | 342 | ∇ {file}∆NERASE tieno 343 | ⍝ Emulate APLX ⎕NERASE 344 | :If 900⌶⍬ ⍝ monadic case? 345 | :If 0=tieno←(⎕NNUMS,0)[(~∘' '¨↓⎕NNAMES)⍳⊂file←tieno] ⍝ tied already? 346 | tieno←file ⎕NTIE 0 347 | :EndIf 348 | :EndIf 349 | file ⎕NERASE tieno 350 | ∇ 351 | 352 | ∇ r←∆NREAD arg;startbyte;count;conv;tieno;type;ix;bytes 353 | ⍝ Emulate APLX ⎕NREAD 354 | 355 | ⎕IO←1 356 | (tieno conv count startbyte)←arg,(≢arg)↓0 0 ¯1 ⍬ 357 | type←n_type conv 358 | 359 | :If count≠¯1 360 | bytes←count×1+(count≠¯1)∧conv=5 ⍝ Double byte count for UTF-16 361 | r←⎕NREAD tieno type bytes,startbyte 362 | :EndIf 363 | 364 | :Select conv 365 | :Case 0 ⋄ r←∆av[1+⎕UCS r] 366 | :Case 4 ⋄ r←∆av[∆x4⍳r] 367 | :Case 5 ⋄ r←⎕UCS 256⊥⍉⌽(count 2)⍴⎕UCS r 368 | :Case 8 369 | 'Element-counted UTF-8 not supported'⎕SIGNAL(count≠¯1)/11 370 | r←'UTF-8'⎕UCS ⎕UCS r 371 | :EndSelect 372 | ∇ 373 | 374 | ∇ {r}←data ∆NREPLACE arg;tieno;type;conv;startbyte 375 | ⍝ Emulate APLX ⎕NREPLACE 376 | 377 | (tieno startbyte conv)←arg,(≢arg)↓0 ¯1 0 378 | type←n_type conv 379 | data←data n_data conv 380 | 381 | r←data ⎕NREPLACE tieno startbyte type 382 | r←0 0⍴0 383 | ∇ 384 | 385 | ∇ {r}←data ∆NWRITE arg;tieno;startbyte;type;conv 386 | ⍝ Emulate APLX ⎕NWRITE 387 | ⍝ startbyte=-1 not supported yet 388 | 389 | :If 1∊⍴,arg ⍝ write as is 390 | r←data ⎕NAPPEND tieno 391 | :Else 392 | (tieno conv startbyte)←arg,(≢arg)↓0 0 ¯1 393 | type←n_type conv 394 | data←data n_data conv 395 | 396 | :If startbyte=¯2 ⋄ r←data ⎕NAPPEND tieno type 397 | :Else ⋄ r←data ⎕NREPLACE tieno startbyte type 398 | :EndIf 399 | :EndIf 400 | r←0 0⍴0 401 | ∇ 402 | 403 | ∇ r←la ∆OV ra;src;nl ⍝ ⎕OV in APLX 404 | src←⎕IO⊃⎕NSI 405 | nl←{⍵.⎕NL⍳10} 406 | :Select la 407 | :Case 0 408 | r←#.⎕NS(src,'.')∘,¨↓ra 409 | :CaseList 2 1 410 | src ⎕NS ra ⋄ r←nl ra 411 | :Case 3 412 | r←nl ra 413 | :EndSelect 414 | ∇ 415 | 416 | ∇ Z←∆R ⍝ Emulate APLX ⎕R 417 | Z←⎕UCS 13 418 | ∇ 419 | 420 | ∆RSHOE←{⍺←⊢ ⋄ ⎕ML←2 ⋄ ⍺⊃⍵} ⍝ ⊃ 421 | 422 | ∇ r←{opt}∆SS arg;text;from;to;type;flags;fix;⎕IO;norm;⎕ML;add1;search;io;show 423 | ⍝ Mimic APLX' ⎕ss function 424 | ⍝ arg is a 2 (search) or 3 (replace) element 425 | :If 900⌶0 ⋄ opt←0 ⋄ :EndIf ⍝ simple search 426 | ((show type)flags)←2↑opt,4 ⍝ advance by 1 after search 427 | 428 | (text from to)←3↑arg,0 429 | fix←⊢ 430 | :If norm←type=0 ⍝ turn regex meta char x into \x 431 | fix←'{}[]()\^$|.?*+'∘{(⍵,b/'\')[⍋⍋b←≠\b/⍨1+b←⍵∊⍺]} 432 | :AndIf 0=10|⎕DR to 433 | to←(1+'\'=to)/to 434 | :EndIf 435 | show←0,norm↓1 ⍝ return also length for regex 436 | add1←1,norm↓0 ⍝ for ⎕IO adjustment later 437 | :If 1=≡,from ⋄ from←fix from 438 | :Else ⋄ from←fix¨from ⋄ show,←3 ⍝ show pattern number too 439 | add1,←1 440 | :EndIf 441 | 442 | ⎕IO←0 ⋄ ⎕ML←1 443 | :If search←to≡0 444 | fix←from ⎕S show 445 | :Else 446 | fix←from ⎕R to 447 | :EndIf 448 | :If flags>0 449 | flags←⌽(9⍴2)⊤flags 450 | fix←fix ⎕OPT(0⊃flags) ⍝ case insensitive? 451 | fix←fix ⎕OPT'ML'(1⊃flags) ⍝ stop after 1st 452 | :If search 453 | fix←fix ⎕OPT'OM'(2⊃flags) ⍝ advance by 1? 454 | :EndIf 455 | fix←fix ⎕OPT'Mode'(0⊃((type=0)∨3⊃flags)⌽'LM') ⍝ Line or Mixed mode? 456 | :AndIf 1=1↑type 457 | fix←fix ⎕OPT'DotAll'(4⊃flags) ⍝ . matches all? 458 | ⍝ Return all matches for multiple searches are ignored 459 | fix←fix ⎕OPT'EOL'((flags[6 7]⍳1)⊃'CR' 'LF' 'CRLF') 460 | :EndIf 461 | 462 | r←↑fix text 463 | ⍝ We need to adjust for the caller's ⎕IO 464 | :If search 465 | :If ⎕THIS=1⍴⎕RSI ⋄ io←1↑3⊃⎕STATE'⎕io' 466 | :Else ⋄ io←⎕RSI[0].⎕IO 467 | :EndIf 468 | r←r+(⍴r)⍴add1∧io 469 | :EndIf 470 | ∇ 471 | 472 | ∇ r←∆TIME 473 | r←,'G<9999-99-99 99.99.99>'⎕FMT 100⊥6⍴⎕TS 474 | ∇ 475 | 476 | ∆UP←{⍺←⊣ ⋄ ⎕ML←2 ⋄ ⍺↑⍵} ⍝ ↑ 477 | 478 | ∇ r←∆VI y 479 | r←⎕IO⊃⎕VFI y 480 | ∇ 481 | 482 | ∇ r←∆W 483 | r←↑⍤0⊢'SUNDAY' 'MONDAY' 'TUESDAY' 'WEDNESDAY' 'THURSDAY' 'FRIDAY' 'SATURDAY' 484 | ∇ 485 | 486 | ∇ r←∆WSSIZE 487 | r←2000⌶16 488 | ∇ 489 | 490 | ∇ type←n_type conv;⎕IO;ix 491 | ⍝ Convert APLX native file conversion codes 492 | ⍝ conv 325 and 643 (=7) not suppported 493 | ⎕IO←1 494 | :If conv∊11 82{⍺,⍵,-⍵}163 323 645 495 | type←|conv 496 | :Else 497 | type←(10⌊1+|conv)⊃80 11 323 645 80 80 0 0 80 0 498 | 'Unsupported conversion type'⎕SIGNAL type↓11 499 | :EndIf 500 | ∇ 501 | 502 | ∇ data←data n_data conv;ix 503 | ⍝ Convert data for native file write 504 | 505 | ⎕IO←1 506 | :Select conv 507 | :Case 0 ⋄ data←⎕UCS ¯1+∆av⍳data 508 | :Case 4 ⋄ data←∆x4[∆av⍳data] 509 | :Case 5 ⋄ data←⎕UCS,⌽⍉256 256⊤'UTF-16'⎕UCS data 510 | :Case 8 ⋄ data←⎕UCS'UTF-8'⎕UCS data 511 | :EndSelect 512 | ∇ 513 | 514 | ∆LEFT←{6::z←0 0⍴0 ⋄ ⍺} ⍝ ⊣ 515 | 516 | ∇ cl←∆CL ⍝ Emulate APLX ⎕CL Current Line 517 | cl←2⊃50100⌶2 518 | ∇ 519 | 520 | ∆ERS←⎕SIGNAL∘99 521 | 522 | ⍝ Things to watch for: 523 | ⍝ ⎕CLASSES is (⎕nl-9.4 9.6) 524 | 525 | L←⎕C ⍝ Lowercase 526 | 527 | :EndNameSpace 528 | --------------------------------------------------------------------------------