diff options
author | Camil Staps | 2016-11-10 12:19:49 +0000 |
---|---|---|
committer | Camil Staps | 2016-11-10 12:19:49 +0000 |
commit | 12d40570b34a04d7f1c542f8c1d42371512d2e45 (patch) | |
tree | f6fa4e3d21d374559bde6f29fb23ebad3a761d51 | |
parent | Made reverse, revtwice and sieve compile (diff) |
made copyfile.icl compile
-rw-r--r-- | copyfile.icl | 594 |
1 files changed, 583 insertions, 11 deletions
diff --git a/copyfile.icl b/copyfile.icl index 8cf70f2..872c2d1 100644 --- a/copyfile.icl +++ b/copyfile.icl @@ -7,37 +7,39 @@ Run the program using the "Basic Values Only" option. */ -import StdEnv, StdFile +import _SystemArray + +//import StdEnv, StdFile Start::*World -> *File Start world = fwrites "\nGoodbye.\n" stdinout` -where +where (stdinout`,_) = accFiles (CommandLoop stdinout) world` (stdinout ,world`) = stdio world - + CommandLoop::*File *Files -> (*File,*Files) CommandLoop stdio files = CommandLoop` stdio` files` -where +where (files`,stdio`) = Copy files stdio - + CommandLoop`::*File *Files -> (*File,*Files) CommandLoop` stdio files | answer<>'y' && answer<>'Y' = (stdio2,files) = CommandLoop` stdio` files` -where +where (files`,stdio`) = Copy files stdio2 answer = FirstChar answ (answ ,stdio2) = freadline stdio1 stdio1 = fwrites "\nCopy another file (y/n)? " stdio - + Copy::*Files *File -> (*Files,*File) Copy files io | source == dest = (files, fwrites "\nCopying succeeded.\n" io4) = CopyFile (StripNewline source) (StripNewline dest) files io4 -where +where (dest,io4) = freadline io3 io3 = fwrites "\nDestination file: " io2 (source,io2) = freadline io1 @@ -51,7 +53,7 @@ CopyFile source dest files io | not dclose = (files4,alert4) | not sclose = (files4,alert5) = (files4,alert6) -where +where (sclose,files4) = fclose sfile` files3 (dclose,files3) = fclose dfile` files2 (io_error,sfile`,dfile`) = CopyFiles sfile dfile @@ -64,13 +66,13 @@ where alert4 = fwrites "Copying failed.\nDestination file could not be closed.\n" io alert5 = fwrites "Copying failed.\nSource file could not be closed.\n" io alert6 = fwrites "\nCopying succeeded.\n" io - + CopyFiles::*File *File -> (Bool, *File, *File) CopyFiles source dest | srcend || wrterror = (wrterror,source1,dest1) = CopyFiles source2 (fwritec byte dest1) -where +where (_,byte,source2) = freadc source1 (srcend,source1) = fend source (wrterror,dest1) = ferror dest @@ -82,3 +84,573 @@ StripNewline str = str % (0, size str - 2) FirstChar::String -> Char FirstChar "" = ' ' FirstChar str = str.[0] + +// --- + +FReadText :== 0 // read from a text file +FWriteText :== 1 // write to a text file +FAppendText :== 2 // append to an existing text file +FReadData :== 3 // read from a data file +FWriteData :== 4 // write to a data file +FAppendData :== 5 // append to an existing data file + +// Seek modes + +FSeekSet :== 0 // new position is the seek offset +FSeekCur :== 1 // new position is the current position plus the seek offset +FSeekEnd :== 2 // new position is the size of the file plus the seek offset + +:: * Files = Files; + +class FileSystem f where + fopen :: !{#Char} !Int !*f -> (!Bool,!*File,!*f) + /* Opens a file for the first time in a certain mode (read, write or append, text or data). + The boolean output parameter reports success or failure. */ + fclose :: !*File !*f -> (!Bool,!*f) + stdio :: !*f -> (!*File,!*f) + /* Open the 'Console' for reading and writing. */ + sfopen :: !{#Char} !Int !*f -> (!Bool,!File,!*f) + /* With sfopen a file can be opened for reading more than once. + On a file opened by sfopen only the operations beginning with sf can be used. + The sf... operations work just like the corresponding f... operations. + They can't be used for files opened with fopen or freopen. */ + +instance FileSystem Files +where + fopen :: !{#Char} !Int !*Files -> (!Bool,!*File,!*Files) + fopen s i w + # (b,f) = fopen_ s i; + = (b,f,w); + + fclose :: !*File !*Files -> (!Bool,!*Files) + fclose f w + # b = fclose_ f + = (b,w); + + stdio :: !*Files -> (!*File,!*Files) + stdio w + # f = stdio_ + = (f,w); + + sfopen :: !{#Char} !Int !*Files -> (!Bool,!File,!*Files) + sfopen s i w + # (b,f) = sfopen_ s i + = (b,f,w) + +instance FileSystem World +where + fopen::!{#Char} !Int !*World -> (!Bool,!*File,!*World) + fopen s i w + # (b,f) = fopen_ s i; + = (b,f,w); + + fclose :: !*File !*World -> (!Bool,!*World) + fclose f w + # b = fclose_ f + = (b,w); + + stdio::!*World -> (!*File,!*World) + stdio w + # f = stdio_ + = (f,w); + sfopen::!{#Char} !Int !*World -> (!Bool,!File,!*World) + sfopen s i w + # (b,f) = sfopen_ s i + = (b,f,w) + +fopen_ ::!{#Char} !Int -> (!Bool,!*File) +fopen_ s i = code inline { + .d 1 1 i + jsr openF + .o 0 3 b f + } + +fclose_ :: !*File -> Bool +fclose_ f = code inline { + .d 0 2 f + jsr closeF + .o 0 1 b + } + +/* Open the 'Console' for reading and writing. */ +stdio_ :: *File +stdio_ = code inline { + .d 0 0 + jsr stdioF + .o 0 2 f + } + +sfopen_ ::!{#Char} !Int -> (!Bool,!File) +sfopen_ s i += code inline { + .d 1 1 i + jsr openSF + .o 0 3 b f + } + +/* + openfiles::!*World -> (!*Files,!*World) + openfiles world + | (1 bitand w) == 0 + = OpenFiles2 (StoreWorld (w bitor 1) world) + = abort "openfiles: This world doesn't contain files" + where w = LoadWorld world + + OpenFiles2::!*World -> (!*Files,!*World) + OpenFiles2 w + = code inline { + pushI 0 + } + + LoadWorld :: !World -> Int; + LoadWorld w = code inline { + pushI_a 0 + pop_a 1 + }; + + StoreWorld :: !Int !World -> *World; + StoreWorld i w = code inline { + fillI_b 0 1 + pop_b 1 + pop_a 1 + }; + + closefiles::!*Files !*World -> *World + closefiles f world + = CloseFiles2 f (StoreWorld ((LoadWorld world) bitand (-2)) world) + + CloseFiles2::!*Files !*World -> *World + CloseFiles2 f w + = code inline { + pop_b 1 + fill_a 0 1 + pop_a 1 + } +*/ + +freopen::!*File !Int -> (!Bool,!*File) +/* Re-opens an open file in a possibly different mode. + The boolean indicates whether the file was successfully closed before reopening. */ +freopen f m + = code inline { + .d 0 3 f i + jsr reopenF + .o 0 3 b f + } + +// Input. The boolean output parameter reports success or failure of the operations. + +freadc::!*File -> (!Bool,!Char,!*File) +/* Reads a character from a text file or a byte from a datafile. */ +freadc f + = code inline { + .d 0 2 f + jsr readFC + .o 0 4 b c f + } + +freadi::!*File -> (!Bool,!Int,!*File) +/* Reads an integer from a textfile by skipping spaces, tabs and newlines and + then reading digits, which may be preceeded by a plus or minus sign. + From a datafile freadi will just read four bytes (a Clean Int). */ +freadi f + = code inline { + .d 0 2 f + jsr readFI + .o 0 4 b i f + } + +freadr::!*File -> (!Bool,!Real,!*File) +/* Reads a real from a textfile by skipping spaces, tabs and newlines and then + reading a character representation of a real number. + From a datafile freadr will just read eight bytes (a Clean Real). */ +freadr f + = code inline { + .d 0 2 f + jsr readFR + .o 0 5 b r f + } + +freads::!*File !Int -> (!*{#Char},!*File) +/* Reads n characters from a text or data file, which are returned as a {#Char}. + If the file doesn't contain n characters the file will be read to the end + of the file. An empty {#Char} is returned if no characters can be read. */ +freads f l + = code inline { + .d 0 3 f i + jsr readFS + .o 1 2 f + } + +freadsubstring :: !Int !Int !*{#Char} !*File -> (!Int,!*{#Char},!*File) + /* + Reads n characters from a text or data file, which are returned in the string s + at positions i..i+n-1. If the file doesn't contain n characters the file will + be read to the end of the file, and the part of the string s that could not be + read will not be changed. The number of characters read, the modified string + and the file are returned. + */ +freadsubstring i n s f + = code { + .inline freadsubstring + .d 1 4 i i f + jsr readFString + .o 1 3 i f + .end + } + +freadline::!*File -> (!*{#Char},!*File) +/* Reads a line from a textfile. (including a newline character, except for the last + line) freadline cannot be used on data files. */ +freadline f + = code inline { + .d 0 2 f + jsr readLineF + .o 1 2 f + } + +// Output. Use FError to check for write errors. + +fwritec::!Char !*File -> *File +/* Writes a character to a textfile. + To a datafile fwritec writes one byte (a Clean Char). */ +fwritec c f + = code inline { + .d 0 3 c f + jsr writeFC + .o 0 2 f + } + +fwritei::!Int !*File -> *File +/* Writes an integer (its textual representation) to a text file. + To a datafile fwritec writes four bytes (a Clean Int). */ +fwritei i f + = code inline { + .d 0 3 i f + jsr writeFI + .o 0 2 f + } + +fwriter::!Real !*File -> *File +/* Writes a real (its textual representation) to a text file. + To a datafile fwriter writes eight bytes (a Clean Real). */ +fwriter r f + = code inline { + .d 0 4 r f + jsr writeFR + .o 0 2 f + } + +fwrites::!{#Char} !*File -> *File +/* Writes a {#Char} to a text or data file. */ +fwrites s f + = code inline { + .d 1 2 f + jsr writeFS + .o 0 2 f + } + +fwritesubstring :: !Int !Int !{#Char} !*File -> *File +/* Writes the characters at positions i..i+n-1 of string s to a text or data file. */ +fwritesubstring i n s f + = code { + .inline fwritesubstring + .d 1 4 i i f + jsr writeFString + .o 0 2 f + .end + } + +// Tests + +fend::!*File -> (!Bool,!*File) +/* Tests for end-of-file. */ +fend f + = code inline { + .d 0 2 f + jsr endF + .o 0 3 b f + } + +ferror::!*File -> (!Bool,!*File) +/* Has an error occurred during previous file I/O operations? */ +ferror f + = code inline { + .d 0 2 f + jsr errorF + .o 0 3 b f + } + +fposition::!*File -> (!Int,!*File) +/* returns the current position of the file pointer as an integer. + This position can be used later on for the fseek function. */ +fposition f + = code inline { + .d 0 2 f + jsr positionF + .o 0 3 i f + } + +fseek::!*File !Int !Int -> (!Bool,!*File) +/* Move to a different position in the file, the first integer argument is the offset, + the second argument is a seek mode. (see above). True is returned if successful. */ +fseek f p m + = code inline { + .d 0 4 f i i + jsr seekF + .o 0 3 b f + } + + +// Predefined files. + +stderr:: *File +/* Open the 'Errors' file for writing only. May be opened more than once. */ +stderr + = code inline { + .d 0 0 + jsr stderrF + .o 0 2 f + } + +sfreadc::!File -> (!Bool,!Char,!File) +sfreadc f + = code inline { + .d 0 2 f + jsr readSFC + .o 0 4 b c f + } + +sfreadi::!File -> (!Bool,!Int,!File) +sfreadi f + = code inline { + .d 0 2 f + jsr readSFI + .o 0 4 b i f + } + +sfreadr::!File -> (!Bool,!Real,!File) +sfreadr f + = code inline { + .d 0 2 f + jsr readSFR + .o 0 5 b r f + } + + +sfreads::!File !Int -> (!*{#Char},!File) +sfreads f i + = code inline { + .d 0 3 f i + jsr readSFS + .o 1 2 f + } + +sfreadline::!File -> (!*{#Char},!File) +sfreadline f + = code inline { + .d 0 2 f + jsr readLineSF + .o 1 2 f + } + +sfseek::!File !Int !Int -> (!Bool,!File) +sfseek f i1 i2 + = code inline { + .d 0 4 f i i + jsr seekSF + .o 0 3 b f + } + +/* Change a file so that from now it can only be used with sfF... operations. */ +fshare::!*File -> File +fshare f + = code inline { + .d 0 2 f + jsr shareF + .o 0 2 f + } + +/* The functions sfend and sfposition work like fend and fposition, but don't return a + new file on which other operations can continue. They can be used for files opened + with sfopen or after fshare, and in guards for files opened with fopen or freopen. */ +sfend::!File -> Bool +sfend f + = code inline { + .d 0 2 f + jsr endSF + .o 0 1 b + } + +sfposition::!File -> Int +sfposition f + = code inline { + .d 0 2 f + jsr positionSF + .o 0 1 i + } + +class (<<<) infixl a :: !*File !a -> *File + +instance <<< Int where +// (<<<) file i = fwritei i file + (<<<) file i = code inline { + push_b 2 + update_b 2 3 + update_b 1 2 + update_b 0 1 + pop_b 1 + .d 0 3 i f + jsr writeFI + .o 0 2 f + } + +instance <<< Char where +// (<<<) file c = fwritec c file + (<<<) file c = code inline { + push_b 2 + update_b 2 3 + update_b 1 2 + update_b 0 1 + pop_b 1 + .d 0 3 c f + jsr writeFC + .o 0 2 f + } + +instance <<< {#Char} where +// (<<<) file s = fwrites s file + (<<<) file s = code inline { + .d 1 2 f + jsr writeFS + .o 0 2 f + } + +instance <<< Real where +// (<<<) file r = fwriter r file + (<<<) file r = code inline { + push_b 3 + push_b 3 + update_b 3 5 + update_b 2 4 + update_b 1 3 + update_b 0 2 + pop_b 2 + .d 0 4 r f + jsr writeFR + .o 0 2 f + } + +// Access to the file system: + +class FileEnv env where + accFiles :: !.(*Files -> (.x,*Files)) !*env -> (!.x,!*env) + appFiles :: !.(*Files -> *Files) !*env -> *env + +instance FileEnv World where + accFiles :: !.(*Files -> (.x,*Files)) !*World -> (!.x,!*World) + accFiles accfun world + #! files=create_files + (r,files) = accfun files + = do_files2 files r world + where + do_files2 :: !*Files !.x !*World -> (!.x,!*World) + do_files2 filesRWS r world + = (r,world) + + appFiles :: !.(*Files -> *Files) !*World -> *World + appFiles appfun world + #! files1=create_files +// RWS ... #! files=appfun files + files=appfun files1 +// .. RWS + = do_files files world + where + do_files :: !*Files !*World -> *World + do_files filesRWS world + = code inline { + fill_a 1 2 + pop_a 2 + } + +create_files :== Files; + +not :: !Bool -> Bool +not a + = code inline { + notB + } + +(&&) infixr 3 :: !Bool Bool -> Bool +(&&) a b + = code { + push_b 0 + jmp_false l1 + pop_b 1 + jsr_eval 0 + pushB_a 0 + pop_a 1 + .d 0 1 b + rtn + :l1 + pop_a 1 + .d 0 1 b + rtn + } + +(||) infixr 2 :: !Bool Bool -> Bool +(||) a b + = code { + push_b 0 + jmp_true l2 + pop_b 1 + jsr_eval 0 + pushB_a 0 + pop_a 1 + .d 0 1 b + rtn + :l2 + pop_a 1 + .d 0 1 b + rtn + } + +class (==) infix 4 a :: !a !a -> Bool // True if arg1 is equal to arg2 + +instance == Char +where + (==) ::!Char !Char -> Bool + (==) a b + = code inline { + eqC + } + +class Eq a | == a +where + (<>) infix 4 :: !a !a -> Bool | Eq a + (<>) x y :== not (x == y) + +(-) infixl 6 :: !Int !Int -> Int +(-) a b = code inline { + subI +} + +class (%) infixl 9 a :: !a !(!Int,!Int) -> a // Slice a part from arg1 +instance % {#Char} +where + (%) ::!{#Char} !(!Int,!Int) -> {#Char} + (%) str (a,b) + = code inline { + .d 1 2 ii + jsr sliceAC + .o 1 0 + } +instance == {#Char} +where + (==) :: !{#Char} !{#Char} -> Bool + (==) a b + = code inline { + .d 2 0 + jsr eqAC + .o 0 1 b + } |