minigrace
Version:
A compiler for the Grace programming language
903 lines • 164 kB
JavaScript
let gracecode_io_sourceFile = "/Users/black/Development/mg/gracelang/minigrace/io.grace";
let gracecode_io_sha256 = "b61d3f5c7cbaaf3ff656b1c8a50c2482078af3e21370f85de33d60fb06d8fabf";
let gracecode_io_minigraceRevision = "b57591d29fc5ee5270d114920bf671367b8c3ecb";
let gracecode_io_minigraceGeneration = "5171";
if (typeof gctCache !== "undefined")
gctCache["io"] = "dialect:\n standard\nfreshScopes:\n $101 trait\n $106\n $107\nmethodTypes:$102:\n ask(question:String) \u2192 Unknown\n error \u2192 FileStream\n exists(path:String) \u2192 Boolean\n input \u2192 FileStream\n listdir(dirPath:Unknown) \u2192 Sequence\u27e6String\u27e7\n newer(path1:Unknown, path2:Unknown) \u2192 Boolean\n open(path:Unknown, mode:Unknown) \u2192 FileStream\n output \u2192 FileStream\n realpath(path:Unknown) \u2192 String\n spawn(executable:Unknown, args:Collection\u27e6String\u27e7) \u2192 Process\n system(command:String) \u2192 Boolean\nmodules:\n collections\n intrinsic\n standard\npath:\n /Users/black/Development/mg/gracelang/minigrace/io.grace\nscope:$101:\n asDebugString String (go) $scope_string\n asString String (go) $scope_string\n basicAsString String (go) $scope_string\n clear Unknown (mth) $scope_done\n isMe(1) Boolean (go) $scope_boolean\n iterator Unknown (mth) $scope_done\n myIdentityHash Number (go) $scope_number\n next Unknown (mth) $scope_done\n nextLine Unknown (mth) $scope_done\n read Unknown (mth) $scope_done\n seek(1) Unknown (mth) $scope_done\n seekBackward(1) Unknown (mth) $scope_done\n seekForward(1) Unknown (mth) $scope_done\n size Unknown (mth) $scope_done\n write(1) Unknown (mth) $scope_done\nscope:$102:\n FileException Unknown (def) $scope_done public\n FileStream type\n IO type\n IoException Unknown (def) $scope_done public\n Process type\n asDebugString String (go) $scope_string\n asString String (go) $scope_string\n ask(1) Unknown (mth) $scope_done\n basicAsString String (go) $scope_string\n error FileStream (def) $105 public\n exists(1) Boolean (mth) $scope_done\n input FileStream (def) $104 public\n isMe(1) Boolean (go) $scope_boolean\n listdir(1) Sequence (mth) $scope_done\n myIdentityHash Number (go) $scope_number\n newer(2) Boolean (mth) $scope_done\n open(2) FileStream (mth) $107\n output FileStream (def) $103 public\n realpath(1) String (mth) $scope_done\n spawn(2) Process (mth) $106\n system(1) Boolean (mth) $scope_done\n unimplementedMethodWarnings Unknown (mth) $101\n unlink(1) Unknown (mth) $scope_done\nscope:$103:\n ::(1) Unknown (mth) $scope_done\n ==(1) Unknown (mth) $scope_done\n asDebugString String (go) $scope_string\n asString Unknown (mth) $scope_done\n basicAsString String (go) $scope_string\n clear Unknown (mth) $scope_done\n close Unknown (mth) $scope_done\n eof Unknown (mth) $scope_done\n hasNext Unknown (mth) $scope_done\n hash Unknown (mth) $scope_done\n isMe(1) Boolean (go) $scope_boolean\n isOpen Unknown (var) $scopeEmpty\n isOpen:=(1) Unknown (var) $scopeEmpty\n isatty Unknown (mth) $scope_done\n iterator Unknown (mth) $scope_done\n myIdentityHash Number (go) $scope_number\n next Unknown (mth) $scope_done\n nextLine Unknown (mth) $scope_done\n pathname Unknown (mth) $scope_done\n prefix== Unknown (mth) $scope_done\n prefix\u2260 Unknown (mth) $scope_done\n read Unknown (mth) $scope_done\n seek(1) Unknown (mth) $scope_done\n seekBackward(1) Unknown (mth) $scope_done\n seekForward(1) Unknown (mth) $scope_done\n size Unknown (mth) $scope_done\n write(1) Unknown (mth) $scope_done\n \u2260(1) Unknown (mth) $scope_done\nscope:$104:\n ::(1) Unknown (mth) $scope_done\n ==(1) Unknown (mth) $scope_done\n asDebugString String (go) $scope_string\n asString Unknown (mth) $scope_done\n basicAsString String (go) $scope_string\n clear Unknown (mth) $scope_done\n close Unknown (mth) $scope_done\n eof Unknown (mth) $scope_done\n getline Unknown (mth) $scope_done\n hasNext Unknown (mth) $scope_done\n hash Unknown (mth) $scope_done\n isMe(1) Boolean (go) $scope_boolean\n isOpen Unknown (var) $scopeEmpty\n isOpen:=(1) Unknown (var) $scopeEmpty\n isatty Unknown (mth) $scope_done\n iterator Unknown (mth) $scope_done\n myIdentityHash Number (go) $scope_number\n next Unknown (mth) $scope_done\n nextLine Unknown (mth) $scope_done\n pathname Unknown (mth) $scope_done\n prefix== Unknown (mth) $scope_done\n prefix\u2260 Unknown (mth) $scope_done\n read Unknown (mth) $scope_done\n seek(1) Unknown (mth) $scope_done\n seekBackward(1) Unknown (mth) $scope_done\n seekForward(1) Unknown (mth) $scope_done\n size Unknown (mth) $scope_done\n write(1) Unknown (mth) $scope_done\n \u2260(1) Unknown (mth) $scope_done\nscope:$105:\n ::(1) Unknown (mth) $scope_done\n ==(1) Unknown (mth) $scope_done\n asDebugString String (go) $scope_string\n asString Unknown (mth) $scope_done\n basicAsString String (go) $scope_string\n clear Unknown (mth) $scope_done\n close Unknown (mth) $scope_done\n eof Unknown (mth) $scope_done\n hasNext Unknown (mth) $scope_done\n hash Unknown (mth) $scope_done\n isMe(1) Boolean (go) $scope_boolean\n isOpen Unknown (var) $scopeEmpty\n isOpen:=(1) Unknown (var) $scopeEmpty\n isatty Unknown (mth) $scope_done\n iterator Unknown (mth) $scope_done\n myIdentityHash Number (go) $scope_number\n next Unknown (mth) $scope_done\n nextLine Unknown (mth) $scope_done\n pathname Unknown (mth) $scope_done\n prefix== Unknown (mth) $scope_done\n prefix\u2260 Unknown (mth) $scope_done\n read Unknown (mth) $scope_done\n seek(1) Unknown (mth) $scope_done\n seekBackward(1) Unknown (mth) $scope_done\n seekForward(1) Unknown (mth) $scope_done\n size Unknown (mth) $scope_done\n write(1) Unknown (mth) $scope_done\n \u2260(1) Unknown (mth) $scope_done\nscope:$106:\n ::(1) Unknown (mth) $scope_done\n ==(1) Unknown (mth) $scope_done\n asDebugString String (go) $scope_string\n asString Unknown (mth) $scope_done\n basicAsString String (go) $scope_string\n cmd Unknown (def) $scope_done\n hash Unknown (mth) $scope_done\n isMe(1) Boolean (go) $scope_boolean\n myIdentityHash Number (go) $scope_number\n prefix== Unknown (mth) $scope_done\n prefix\u2260 Unknown (mth) $scope_done\n status Unknown (def) $scope_done public\n success Unknown (mth) $scope_done\n terminated Unknown (mth) $scope_done\n wait Unknown (mth) $scope_done\n \u2260(1) Unknown (mth) $scope_done\nscope:$107:\n ::(1) Unknown (mth) $scope_done\n ==(1) Unknown (mth) $scope_done\n asDebugString String (go) $scope_string\n asString Unknown (mth) $scope_done\n basicAsString String (go) $scope_string\n clear Unknown (mth) $scope_done\n close Unknown (mth) $scope_done\n eof Unknown (mth) $scope_done\n getline Unknown (mth) $scope_done\n hasNext Unknown (mth) $scope_done\n hash Unknown (mth) $scope_done\n isMe(1) Boolean (go) $scope_boolean\n isOpen Unknown (var) $scopeEmpty\n isOpen:=(1) Unknown (var) $scopeEmpty\n isatty Unknown (mth) $scope_done\n iterator Unknown (mth) $scope_done\n myIdentityHash Number (go) $scope_number\n next Unknown (mth) $scope_done\n nextLine Unknown (mth) $scope_done\n pathname Unknown (def) $scopeEmpty public\n prefix== Unknown (mth) $scope_done\n prefix\u2260 Unknown (mth) $scope_done\n read Unknown (mth) $scope_done\n seek(1) Unknown (mth) $scope_done\n seekBackward(1) Unknown (mth) $scope_done\n seekForward(1) Unknown (mth) $scope_done\n size Unknown (mth) $scope_done\n write(1) Unknown (mth) $scope_done\n \u2260(1) Unknown (mth) $scope_done\nself:\n $102\ntypedec:$102.FileStream:\n type FileStream = Object & interface {\n read \u2192 String\n size \u2192 Number\n hasNext \u2192 Boolean\n next \u2192 String\n nextLine \u2192 String\n write(s:String) \u2192 Done\n close \u2192 Done\n seek(n:Number) \u2192 FileStream\n seekForward(n:Number) \u2192 FileStream\n seekBackward(n:Number) \u2192 FileStream\n iterator \u2192 FileStream\n pathname \u2192 String\n isatty \u2192 Boolean\n ==(other) \u2192 Boolean\n clear \u2192 FileStream\n eof \u2192 Boolean}\ntypedec:$102.IO:\n type IO = Object & interface {\n IoException \u2192 ExceptionKind\n FileException \u2192 ExceptionKind\n input \u2192 FileStream\n output \u2192 FileStream\n error \u2192 FileStream\n ask(question:String) \u2192 String\n open(path:String, mode:String) \u2192 FileStream\n system(command:String) \u2192 Boolean\n exists(path:String) \u2192 Boolean\n unlink(path:String) \u2192 Done\n newer(path1:String, path2:String) \u2192 Boolean\n realpath(path:String) \u2192 String\n listdir(dirPath:String) \u2192 Sequence\u27e6String\u27e7\n changeDirectory(dirPath:String)\n env \u2192 Dictionary\u27e6String, String\u27e7\n spawn(executable:String, args:Collection\u27e6String\u27e7) \u2192 Process}\ntypedec:$102.Process:\n type Process = Object & interface {\n wait \u2192 Number\n success \u2192 Boolean\n terminated \u2192 Boolean\n status \u2192 Number}\ntypes:\n $102.FileStream\n $102.IO\n $102.Process\n";
if (typeof originalSourceLines !== "undefined") {
originalSourceLines["io"] = [
"dialect \"standard\"",
"",
"import \"intrinsic\" as intrinsic",
"import \"collections\" as collections",
"",
"def IteratorExhausted = outer.IteratorExhausted",
"def IoException is public = EnvironmentException.refine \"IoException\"",
"def FileException is public = IoException.refine \"FileError\"",
"",
"type FileStream = Object & interface {",
" // The type FileStream describes the interface of an opened file. Notice that",
" // FileStream conforms to Iterator, so FileStreams can also be treated like Iterators.",
" read -> String",
" // returns the whole contents of the underlying file.",
" // ignores the position of the read-write pointer, and does not change it.",
" size -> Number",
" // returns the total number of characters in this stream.",
" // This is the size of the string returned by read, not the number of characters remaining.",
" hasNext -> Boolean",
" // returns true if next will return a character,",
" // and false if it will raise an exception.",
" next -> String",
" // returns the next character from the file.",
" // Raises IteratorExhausted if there are are no more characters to be read.",
" nextLine -> String",
" // returns the next line in the file, up to and including the next",
" // newline, or the end of the file. The newline character itself ",
" // is not part of the result.",
" // Raises IteratorExhausted if there are no more lines to be read.",
" write (s:String) -> Done",
" // writes s to the file at the current position of the read-write",
" // pointer. Writes will not appear on the file until the FileStream is",
" // closed. As a special case, writes to the output window in the",
" // Grace editor will also appear after a newline has been written.",
" close -> Done",
" // closes the stream. Output is pushed to its destination, and further",
" // writes will raise an exception. In the Grace editor, the input, ",
" // output and error streams remain open even after this method is used",
" // to close them.",
" seek (n: Number) -> FileStream",
" // moves the read position to be just after the nth character, meaning",
" // that the next character to be read will be the (n+1)th.",
" seekForward (n:Number) -> FileStream",
" // moves the read/write position forward by n characters",
" seekBackward (n:Number) -> FileStream",
" // moved the read/write position backward by n characters",
" iterator -> FileStream",
" // returns self",
" pathname -> String",
" // the name of the file underlying this FileStream",
" isatty -> Boolean",
" // true if this fileStream is interactive",
" == (other) -> Boolean",
" // true if self and other are the same FileStream object. Note that",
" // it is possible to have several distinct fileStreams on the same",
" // underlying file.",
" clear -> FileStream",
" // makes the contents of this FileStream empty. The read/write position becomes 0",
" eof -> Boolean // true if nothing more can be read from this file stream",
"}",
"",
"type IO = Object & interface {",
" IoException -> ExceptionKind // the parent of all IO-specific exceptions; a refinement of EnvironmentException",
" FileException -> ExceptionKind // a refinement of IoException",
" input -> FileStream // answers stdin",
" output -> FileStream // answers stdout",
" error -> FileStream // answers stderr",
" ask(question:String) -> String",
" // asks `question` interactively, and returns the user's answer",
"",
" // In the Grace editor, the output and error streams write to the feedback window,",
" // in black and in red, while reading from the input stream is equivalent to",
" // ask \"Input\". These streams remain open even after executing their close methods.",
"",
" open (path:String, mode:String) -> FileStream",
" // opens path in mode, which is one of the following:",
" // \"r\" - Open file for reading. An exception occurs if the file does not exist.",
" // \"w\" - Open file for writing. The file is created (if it does not exist) or truncated (if it exists).",
" // \"rw\" - Open file for reading and writing. The file is created (if it does not exist)",
" // or truncated (if it exists).",
" // \"a\" - Open file for appending. The file is created if it does not exist.",
" // Appending means that the read–write position is at the end of the file.",
"",
" system (command:String) -> Boolean",
" // executes system command, answers true iff exit status is 0",
" exists (path:String) -> Boolean",
" // answers true iff path exists in the file system",
" unlink (path:String) -> Done",
" // removes path from the file system; raises an exception if it wasn't there",
" newer (path1:String, path2:String) -> Boolean",
" // answers true iff the file at path1 is newer than the file at path2",
" realpath (path:String) -> String // answers absolute name of the file at path",
" listdir (dirPath:String) -> Sequence⟦String⟧",
" // answers the names of the files in the directory at dirPath",
" changeDirectory (dirPath:String)",
" env -> Dictionary⟦String,String⟧",
" // answers a Dictionary mapping names of environment variables to",
" // their values",
" spawn (executable:String, args:Collection⟦String⟧) -> Process",
" // creates a new Process `executable` using `args` as the command-line arguments",
"}",
"",
"type Process = Object & interface {",
" wait -> Number",
" // wait for me to terminate, and answer my exit status.",
" // +ve indicates that I terminated normally. Other",
" // Unix status codes are negated.",
" success -> Boolean",
" // waits for me to terminate, and returns true if I",
" // exited normally (status = 0)",
" terminated -> Boolean",
" // answers true if I've terminated.",
" status -> Number",
" // waits for me to terminate, if necessary. Answers my",
" // exit status. Identical to wait for a synchronous process",
"}",
"",
"native \"js\" code ‹",
" // initialization code",
"",
" if (!inBrowser) { // if we are in Node.js",
" var fs = require(\"fs\");",
" var child_process = require('child_process');",
" var path = require('path');",
" var crypto;",
" try { crypto = require('crypto'); } catch { crypto = false; }",
" }",
" function identifierAvailable(category, identifier) {",
" if (inBrowser) {",
" return !(localStorage.hasOwnProperty(category + \":\" + identifier));",
" } else {",
" return ! fs.existsSync(identifier);",
" }",
" }",
" function getFile(name){",
" if (inBrowser) {",
" return localStorage[name];",
" } else if (fs.existsSync(name)) {",
" return fs.readFileSync(name).toString();",
" } else {",
" return \"\";",
" }",
" }",
"",
" const writeFileToDisk = inBrowser ? browserWrite : commandLineWrite;",
"",
" function browserWrite(name, data) {",
" // name is a pathname, data the string to be written",
" localStorage.setItem(name, data);",
" }",
"",
" function randomFileNameNear(pathname) {",
" // returns a randomly-generated file name in the same directory as pathname",
" var id;",
" if (crypto) {",
" id = crypto.randomBytes(16).toString('hex');",
" } else {",
" id = performance.now().toString(16);",
" }",
" return path.dirname(pathname) + path.sep + id;",
" }",
"",
" function commandLineWrite (name, data) {",
" // name is a pathname, data the string to be written",
" // we write to a temp file first, to make the write atomic",
" try {",
" const temp = randomFileNameNear(name);",
" const nodeFileObject = fs.openSync(temp, \"w\");",
" fs.writeSync(nodeFileObject, data);",
" fs.closeSync(nodeFileObject);",
" fs.renameSync(temp, name);",
" } catch(ex) {",
" raiseException(EnvironmentExceptionObject,",
" \"can't write to file '\" + name + \"'\");",
" }",
" }",
"",
" function getDirectoryName(fullPath) {",
" // fullPath is a full localStorage directory path, e.g. thisDir/thatDir/file",
" // returns just the directory component of the name, e.g., thisDir/thatDir",
"",
" const lastSlash = directoryName.lastIndexOf(\"/\");",
" if (lastSlash == -1) {",
" // -1 means not found",
" return fullPath;",
" } else {",
" return fullPath.substring(0, lastSlash);",
" }",
" }",
"",
" function addFileToTree(name) {",
" // add a file to the web editor file tree",
" var element = document.getElementById(\"add-file-io-api\");",
" element.innerHTML = name;",
" element.click(); //Trigger event in files.js (grace-web-editor)",
" }",
"",
" function removeFileFromTree(name) {",
" // remove a file from the web editor file tree",
" var element = document.getElementById(\"remove-file-io-api\");",
" element.innerHTML = name;",
" element.click(); //Trigger event in files.js (grace-web-editor)",
" }",
"›",
"",
"trait unimplementedMethodWarnings {",
"",
" method clear {",
" IoException.raise \"method \\\"clear\\\" not implemented on {self}\"",
" }",
" method seek(_){",
" IoException.raise \"method \\\"seek(_)\\\" not implemented on {self}\"",
" }",
" method seekForward(_) {",
" IoException.raise \"method \\\"seekForward(_)\\\" not implemented on {self}\"",
" }",
" method seekBackward(_){",
" IoException.raise \"method \\\"seekBackward(_)\\\" not implemented on {self}\"",
" }",
" method next {",
" IoException.raise \"method \\\"next\\\" not implemented on {self}\"",
" }",
" method nextLine {",
" IoException.raise \"method \\\"nextLine\\\" not implemented on {self}\"",
" }",
" method size {",
" IoException.raise \"method \\\"size\\\" not implemented on {self}\"",
" }",
" method write(_) {",
" IoException.raise \"method \\\"write(_)\\\" not implemented on {self}\"",
" }",
" method read {",
" IoException.raise \"method \\\"read\\\" not implemented on {self}\"",
" }",
" method iterator {",
" IoException.raise \"method \\\"iterator\\\" not implemented on {self}\"",
" }",
"}",
"",
"def output:FileStream is public = object {",
" use identityEquality",
" use unimplementedMethodWarnings",
"",
" native \"js\" code ‹this.buffer = \"\";›",
" var isOpen := true",
"",
" method asString { \"the standard output stream\" }",
" method write(s) {",
" if (isOpen.not) then { IoException.raise \"write(_) requested on {self} after it has been closed\" }",
" native \"js\" code ‹",
" var str = var_s._value;",
" if (inBrowser) {",
" var lastNewline = str.lastIndexOf(\"\\n\");",
" if (lastNewline != -1) {",
" minigrace.stdout_write(this.buffer + str.substring(0, lastNewline + 1));",
" this.buffer = str.substring(lastNewline + 1);",
" } else {",
" stdout.buffer = stdout.buffer + str;",
" }",
" } else {",
" minigrace.stdout_write(str);",
" }",
" ›",
" done",
" }",
" method pathname { \"/dev/stdout\" }",
" method isatty {",
" if (intrinsic.inBrowser) then { return false }",
" if (isOpen.not) then { IoException.raise \"isatty requested on {self} after it has been closed\" }",
" native \"js\" code ‹return process.stdout.isTTY ? GraceTrue : GraceFalse;›",
" }",
" method close {",
" if (intrinsic.inBrowser.not) then { isOpen := false }",
" native \"js\" code ‹",
" if (this.buffer.length > 0) {",
" minigrace.stdout_write(this.buffer);",
" this.buffer = \"\";",
" }",
" ›",
" }",
" method hasNext {",
" if (isOpen.not) then { IoException.raise \"hasNext requested on {self} after it has been closed\" }",
" false",
" }",
" method eof { true }",
"}",
"",
"def input:FileStream is public = object {",
" use identityEquality",
" use unimplementedMethodWarnings",
" var isOpen := true",
" native \"js\" code ‹",
" this.lineBuffer = \"\";",
" this.lineCursor = 0;",
" ›",
" method asString { \"the standard input stream\" }",
" method getline {",
" if (isOpen.not) then { IoException.raise \"getLine requested on {self} after it has been closed\" }",
" native \"js\" code ‹return new GraceString(minigrace.stdin_read());›",
" }",
" method nextLine {",
" if (isOpen.not) then { IoException.raise \"nextLine requested on {self} after it has been closed\" }",
" native \"js\" code ‹return new GraceString(minigrace.stdin_read());›",
" }",
" method read {",
" if (isOpen.not) then { IoException.raise \"read requested on {self} after it has been closed\" }",
" native \"js\" code ‹return new GraceString(minigrace.stdin_read());›",
" }",
" method hasNext {",
" if (isOpen.not) then { IoException.raise \"hasNext requested on {self} after it has been closed\" }",
" true",
" }",
" method next {",
" if (isOpen.not) then { IoException.raise \"next requested on {self} after it has been closed\" }",
" native \"js\" code ‹",
" if (this.lineCursor >= this.lineBuffer.length) {",
" this.lineCursor = 0;",
" this.lineBuffer = minigrace.stdin_read() + \"\\n\";",
" }",
" this.lineCursor++;",
" return this.lineBuffer.charAt(this.lineCursor - 1);",
" ›",
" }",
" method iterator {",
" read.iterator",
" }",
" method isatty {",
" if (intrinsic.inBrowser) then { return false }",
" native \"js\" code ‹return process.stdin.isTTY ? GraceTrue : GraceFalse;›",
" }",
" method pathname { \"/dev/stdin\" }",
" method size { IoException.raise \"method \\\"size\\\" not implemented on {self}\" }",
" method close {",
" if (intrinsic.inBrowser.not) then { isOpen := false }",
" }",
" method eof { isOpen.not }",
"}",
"",
"def error:FileStream is public = object {",
" use identityEquality",
" use unimplementedMethodWarnings",
" var isOpen := true",
" method asString { \"the standard error stream\" }",
" method write(s) {",
" native \"js\" code ‹minigrace.stderr_write(var_s._value);›",
" }",
" method isatty {",
" if (intrinsic.inBrowser) then { return false }",
" native \"js\" code ‹return (process.stderr.isTTY) ? GraceTrue : GraceFalse;›",
" }",
" method pathname { \"/dev/stderr\" }",
" method close {",
" if (intrinsic.inBrowser.not) then { isOpen := false }",
" }",
" method hasNext {",
" if (isOpen.not) then { IoException.raise \"hasNext requested on {self} after it has been closed\" }",
" false",
" }",
" method eof { true }",
"}",
"",
"method system (command:String) -> Boolean {",
" // executes command in a sub-process and answers true if it exits with 0",
" native \"js\" code ‹",
" if (inBrowser) { return GraceFalse; }",
" try {",
" var result = child_process.execSync(safeJsString(var_command),",
" {stdio: [process.stdin, process.stdout, process.stderr]});",
" return GraceTrue;",
" } catch(ex) {",
" return GraceFalse;",
" }›",
"}",
"method exists (path:String) -> Boolean {",
" // returns true if `path` names a file in the filesystem.",
" native \"js\" code ‹",
" let p = safeJsString(var_path)",
" if (!inBrowser) {",
" return (fs.existsSync(p) ? GraceTrue : GraceFalse);",
" }",
" if (!identifierAvailable(\"file\",p)) return GraceTrue;",
" return GraceFalse;›",
"}",
"method unlink(path) {",
" native \"js\" code ‹",
" let path = safeJsString(var_path);",
" if (inBrowser) {",
" var fileKey = \"file:\" + path;",
" if (! localStorage.hasOwnProperty(fileKey)) {",
" throw new GraceExceptionPacket(EnvironmentExceptionObject,",
" new GraceString(\"can't unlink file \\\"\" + path +\"\\\" because it does not exist\"));",
" } else {",
" removeFileFromTree(path);",
" localStorage.removeItem(fileKey);",
" }",
" } else {",
" try {",
" fs.unlinkSync(path);",
" } catch (ex) {",
" throw new GraceExceptionPacket(EnvironmentExceptionObject,",
" new GraceString(\"can't unlink file '\" + path));",
" }",
" }",
" return GraceDone;›",
"}",
"",
"method spawn (executable, args:Collection⟦String⟧) -> Process {",
" // forks and execv's executable, with args",
" // executable can be a string, or any object with an `asString` method",
" native \"js\" code ‹",
" if (inBrowser) { return GraceFalse; }",
" let cmd = safeJsString(var_executable);",
" let args = [];",
" let iter = callmethod(var_args, \"iterator\", 0);",
" while (Grace_isTrue(callmethod(iter, \"hasNext\", 0))) {",
" let arg = callmethod(iter, \"next\", 0);",
" args.push(safeJsString(arg));",
" }",
" let procResult = child_process.spawnSync(cmd, args,",
" {stdio: [process.stdin, process.stdout, process.stderr]});",
" ›",
" object {",
" use identityEquality",
" def status is public = native \"js\" code ‹result = new GraceNum(procResult.status);›",
" def cmd = native \"js\" code ‹result = new GraceString(cmd);›",
" method asString { \"process spawned to execute {cmd.asDebugString}\" }",
" method terminated { true }",
" method wait { status }",
" method success { status == 0 }",
" }",
"}",
"method open(path, mode) -> FileStream {",
" native \"js\" code ‹",
" var path = safeJsString(var_path);",
" const fileMode = var_mode._value.toLowerCase();",
" var fileName = inBrowser ? \"file:\"+path : path;",
" var lastPeriod = fileName.lastIndexOf(\".\");",
" var fileExtension = fileName.substring(lastPeriod);",
" var textExtensions = [\".grace\", \".txt\", \".json\", \".xml\", \".js\", \".html\", \".xhtml\"];",
" var rw_pointer, content_length;",
"",
" // Determine File Mode",
" const append_mode = (fileMode === \"a\");",
" const write_allowed = fileMode.includes(\"w\") || append_mode;",
" const read_only = (fileMode === \"r\");",
"",
" if (inBrowser) {",
" // Enforce specified file types for IDE",
" if (!textExtensions.includes(fileExtension)) {",
" throw new GraceExceptionPacket(IoExceptionObject,",
" new GraceString(\"can't open file \\\"\" + path + \"\\\" due to unsupported file type: \" + fileExtension));",
" }",
"",
" const isFile_creation_needed = identifierAvailable(\"file\", path);",
"",
" // Check to see if reading a non-existing file",
" if (read_only && isFile_creation_needed) {",
" throw new GraceExceptionPacket(EnvironmentExceptionObject,",
" new GraceString(\"can't open file \" + path + \" in mode \" + fileMode + \" because it does not exist\"));",
" }",
"",
" // Add the file to the UI, if needed",
" if (write_allowed && isFile_creation_needed) {",
" var directory = getDirectoryName(path);",
"",
" // Check to see if the file's directory exists",
" if ((directory !== path) && identifierAvailable(\"directory\", directory)) {",
" throw new GraceExceptionPacket(EnvironmentExceptionObject,",
" new GraceString(\"can't create file \\\"\" + path + \"\\\" because directory \\\"\" + directory + \"\\\" does not exist\"));",
" }",
" }",
" } else {",
" if (!fs.existsSync(path) && read_only) {",
" throw new GraceExceptionPacket(EnvironmentExceptionObject,",
" new GraceString(\"can't open file '\" + path + \" in mode \" + fileMode + \" because it does not exist\"));",
" }",
" }",
"",
" // Get and parse file",
" var contents = getFile(fileName);",
" if (contents === undefined || fileMode===\"w\") {",
" contents = \"\";",
" content_length = 0;",
" } else {",
" content_length = contents.length;",
" }",
" if (append_mode && contents !== undefined) {",
" rw_pointer = contents.length;",
" } else {",
" rw_pointer = 0;",
" }",
"",
" function checkSeekInput(className, value, method) { // helper function",
" if (className !== \"number\"){",
" throw new GraceExceptionPacket(TypeErrorObject,",
" new GraceString(\"in request of `\"+method+\"`, the argument is not of type Number\"));",
" }",
" else if (!Number.isInteger(value)) {",
" throw new GraceExceptionPacket(RequestErrorObject,",
" new GraceString(\"in request of `\"+method+\"`, the argument is not an integer\"));",
" }",
" }",
" ›",
" object {",
" // construct the FileStream object",
" use identityEquality",
" def pathname is public = path",
" var isOpen := true",
" method asString { \"a stream on file {pathname}\" }",
" method write(data) {",
" if (isOpen.not) then {",
" IoException.raise \"write(_) requested on a stream on file {pathname} after it has been closed\"",
" }",
" native \"js\" code ‹",
" var new_contents;",
" if (write_allowed) {",
" if (contents && inBrowser) {",
" new_contents = contents.slice(0,rw_pointer) + var_data._value + contents.slice((rw_pointer)+(var_data._value.length));",
" } else {",
" new_contents = safeJsString(var_data);",
" }",
"",
" // Update buffer values only",
" if (fileMode === \"w\" && !inBrowser) {",
" contents = contents + new_contents;",
" rw_pointer += new_contents.length;",
" } else if (inBrowser) {",
" contents = new_contents;",
" rw_pointer += var_data._value.length;",
" }",
"",
" content_length = contents.length;",
" return GraceDone;",
" }",
" ›",
" ProgrammingError.raise \"can't write to file \\\"{pathname}\\\" in read-only mode\"",
" }",
" method clear {",
" native \"js\" code ‹",
" if (write_allowed) {",
" contents = \"\";",
" rw_pointer = 0;",
" content_length = 0;",
" return GraceDone;",
" }",
" ›",
" ProgrammingError.raise \"can't write to file \\\"{pathname}\\\" in read-only mode\"",
" }",
" method getline {",
" native \"js\" code ‹",
" var resultLine;",
" var newline_index = contents.indexOf(\"\\n\", rw_pointer);",
"",
" // Check for last-line or EOF case and narrow-down to next line from rw_pointer",
" if (newline_index !== -1) {",
" resultLine = contents.slice(rw_pointer, newline_index);",
" } else {",
" resultLine = contents.slice(rw_pointer);",
" }",
"",
" // Update rw_pointer to take into account returned value",
" rw_pointer += (resultLine.length + 1);",
"",
" return new GraceString(resultLine);",
" ›",
" }",
" method nextLine {",
" native \"js\" code ‹",
" if (rw_pointer >= contents.length) {",
" raiseException(var_IteratorExhausted, \"End of file reached; there is no next line\");",
" }",
" var resultLine;",
" var newline_index = contents.indexOf(\"\\n\", rw_pointer);",
"",
" // Check for last-line or EOF case and narrow-down to next line from rw_pointer",
" if (newline_index !== -1) {",
" resultLine = contents.slice(rw_pointer, newline_index);",
" } else {",
" resultLine = contents.slice(rw_pointer);",
" }",
"",
" // Update rw_pointer to take into account returned value",
" rw_pointer += (resultLine.length + 1);",
"",
" return new GraceString(resultLine);",
" ›",
" }",
" method seek(data) {",
" native \"js\" code ‹",
" var pointer = parseFloat(var_data._value);",
" // Check for NaN and for non-integer input",
" checkSeekInput(var_data.className, pointer, \"seek(_)\");",
"",
" if (pointer<0){pointer=0}",
" else if (pointer>content_length){pointer=content_length}",
"",
" rw_pointer=pointer;",
" return this;",
" ›",
" }",
" method seekForward(data) {",
" native \"js\" code ‹",
" var pointer = parseFloat(var_data._value);",
" // Check for NaN and for non-integer input",
" checkSeekInput(var_data.className, pointer, \"seekForward(_)\");",
"",
" pointer = rw_pointer+pointer;",
"",
" if (pointer<0){pointer=0}",
" else if (pointer>content_length){pointer=content_length}",
"",
" rw_pointer=pointer;",
" return this;",
" ›",
" }",
" method seekBackward(data) {",
" native \"js\" code ‹",
" var pointer = parseFloat(var_data._value);",
" // Check for NaN and for non-integer input",
" checkSeekInput(var_data.className, pointer, \"seekBackward(_)\");",
"",
" pointer = rw_pointer-pointer;",
"",
" if (pointer<0){pointer=0}",
" else if (pointer>content_length){pointer=content_length}",
"",
" rw_pointer=pointer;",
" return this;",
" ›",
" }",
" method hasNext {",
" native \"js\" code ‹",
" return (rw_pointer < content_length) ? GraceTrue : GraceFalse;",
" ›",
" }",
" method next {",
" native \"js\" code ‹",
" if (! Grace_isTrue(this.data.isOpen)) { request(var_IoException, \"raise(1)\", [1],",
" new GraceString(\"next requested on a stream on file \" + path + \" after it has been closed\"));",
" }",
" if (rw_pointer < content_length){",
" var char = new GraceString(contents.charAt(rw_pointer));",
" rw_pointer++;",
" return char;",
" } else {",
" raiseException(var_IteratorExhausted,",
" \"End of file reached; there is no next character\");",
" }",
" ›",
" }",
" method close {",
" native \"js\" code ‹",
" // Update system storage with buffered contents",
" if (inBrowser && fileMode === \"w\") {",
" if (identifierAvailable(\"file\",path)) { addFileToTree(path); }",
" writeFileToDisk(fileName, contents);",
" } else if (!inBrowser && fileMode === \"w\") {",
" writeFileToDisk(fileName, contents);",
" }",
" this.data.isOpen = GraceFalse;",
" return GraceDone;",
" ›",
" }",
" method eof {",
" native \"js\" code ‹return (rw_pointer < content_length) ? GraceFalse : GraceTrue;›",
" }",
" method read { native \"js\" code ‹return new GraceString(contents.toString());› }",
" method size { native \"js\" code ‹return new GraceNum(content_length);› }",
" method iterator { self }",
" method isatty { false } // tty not currently possible",
" }",
"}",
"",
"method realpath(path) -> String {",
" // answers the canonicalized absolute pathname corresponding to `path`",
" native \"js\" code ‹",
" if (!inBrowser) {",
" const arg = safeJsString(var_path);",
" try {",
" let realpath = fs.realpathSync(arg);",
" if (fs.lstatSync(realpath).isDirectory()) {",
" realpath = realpath + \"/\";",
" }",
" return new GraceString(realpath);",
" } catch (ex) {",
" const pat = ex.code + \": ([^,]+)\"; // build a regex",
" const msg = ex.message.match(pat)[1]; // extract error message",
" throw new GraceExceptionPacket(RequestErrorObject,",
" new GraceString(\"can't get real path for \\\"\" + arg +",
" \"\\\" — \" + msg));",
" }",
" }",
" return x;›",
"}",
"method listdir(dirPath) -> Sequence⟦String⟧ {",
" // lists the directory `dirPath`",
" native \"js\" code ‹",
" if (!inBrowser) {",
" var list = [];",
" list.push(new GraceString(\".\"));",
" list.push(new GraceString(\"..\"));",
" fs.readdirSync(safeJsString(var_dirPath)).forEach(function(val, index, array) {",
" list.push(new GraceString(val));",
" });",
" return new GraceList(list);",
" }",
" return new GraceList([]); // TODO: enumerate files in local storage›",
"}",
"",
"method newer (path1, path2) -> Boolean {",
" // returns true is `path1` is a newer file than `path2`",
" native \"js\" code ‹",
" if (inBrowser) { return GraceTrue; }",
" let p1Stats = fs.statSync(safeJsString(var_path1));",
" let p2Stats = fs.statSync(safeJsString(var_path2));",
" return (p1Stats.mtimeMs > p2Stats.mtimeMs ? GraceTrue : GraceFalse);›",
"}",
"",
"method ask(question:String) {",
" // asks `question` interactively, and returns the answer input",
" // by the interactive user.",
" native \"js\" code ‹",
" return new GraceString(minigrace.ask(var_question._value));›",
"}",
"" ];
}
function gracecode_io() {
importedModules["io"] = this;
const var_$module = this;
this.definitionModule = "io";
this.definitionLine = 1;
setLineNumber(1); // compilenode dialect
// Dialect "standard"
const var_$dialect = do_import("standard", gracecode_standard);
this.outer = var_$dialect;
setLineNumber(3); // compilenode import
// Import of "intrinsic" as intrinsic
if (typeof gracecode_intrinsic == "undefined")
throw new GraceExceptionPacket(EnvironmentExceptionObject,
new GraceString("could not find module intrinsic"));
var var_intrinsic = do_import("intrinsic", gracecode_intrinsic);
var func0 = function(argcv) { // accessor method intrinsic, line 3
const numArgs = arguments.length - 1;
if (numArgs > 0) raiseTypeArgError("intrinsic", 0, numArgs - 0);
return var_intrinsic;
}; // end of method intrinsic
this.methods["intrinsic"] = func0;
func0.methodName = "intrinsic";
func0.paramCounts = [0];
func0.paramNames = [];
func0.definitionLine = 3;
func0.definitionModule = "io";
func0.debug = "import";
func0.confidential = true;
setLineNumber(4); // compilenode import
// Import of "collections" as collections
if (typeof gracecode_collections == "undefined")
throw new GraceExceptionPacket(EnvironmentExceptionObject,
new GraceString("could not find module collections"));
var var_collections = do_import("collections", gracecode_collections);
var func1 = function(argcv) { // accessor method collections, line 4
const numArgs = arguments.length - 1;
if (numArgs > 0) raiseTypeArgError("collections", 0, numArgs - 0);
return var_collections;
}; // end of method collections
this.methods["collections"] = func1;
func1.methodName = "collections";
func1.paramCounts = [0];
func1.paramNames = [];
func1.definitionLine = 4;
func1.definitionModule = "io";
func1.debug = "import";
func1.confidential = true;
this.closureKeys = this.closureKeys || [];
this.closureKeys.push("outer_io_1");
this.outer_io_1 = var_$dialect;
setLineNumber(10); // compilenode typedec
// Type decl FileStream
var func3 = function(argcv) { // method FileStream, line 1
var returnTarget = invocationCount;
invocationCount++;
setLineNumber(1); // compilenode string
var string5 = new GraceString("FileStream");
// call case 4: other requests
setLineNumber(10); // compilenode interfaceliteral
// interface literal
var iface7 = new GraceInterface("\u2039anon\u203a");
sig8 = () => {
setLineNumber(13); // compilenode member
var call9 = selfRequest(var_$dialect, "String", [0]);
return new GraceSignature("read", [], [], [], call9);
}
sig10 = () => {
setLineNumber(16); // compilenode member
var call11 = selfRequest(var_$dialect, "Number", [0]);
return new GraceSignature("size", [], [], [], call11);
}
sig12 = () => {
setLineNumber(19); // compilenode member
var call13 = selfRequest(var_$dialect, "Boolean", [0]);
return new GraceSignature("hasNext", [], [], [], call13);
}
sig14 = () => {
setLineNumber(22); // compilenode member
var call15 = selfRequest(var_$dialect, "String", [0]);
return new GraceSignature("next", [], [], [], call15);
}
sig16 = () => {
setLineNumber(25); // compilenode member
var call17 = selfRequest(var_$dialect, "String", [0]);
return new GraceSignature("nextLine", [], [], [], call17);
}
sig18 = () => {
setLineNumber(30); // compilenode member
var call19 = selfRequest(var_$dialect, "String", [0]);
var call20 = selfRequest(var_$dialect, "Done", [0]);
return new GraceSignature("write(1)", ["s"], [], [call19], call20);
}
sig21 = () => {
setLineNumber(35); // compilenode member
var call22 = selfRequest(var_$dialect, "Done", [0]);
return new GraceSignature("close", [], [], [], call22);
}
sig23 = () => {
setLineNumber(40); // compilenode member
var call24 = selfRequest(var_$dialect, "Number", [0]);
var call25 = selfRequest(var_$module, "FileStream", [0]);
return new GraceSignature("seek(1)", ["n"], [], [call24], call25);
}
sig26 = () => {
setLineNumber(43); // compilenode member
var call27 = selfRequest(var_$dialect, "Number", [0]);
var call28 = selfRequest(var_$module, "FileStream", [0]);
return new GraceSignature("seekForward(1)", ["n"], [], [call27], call28);
}
sig29 = () => {
setLineNumber(45); // compilenode member
var call30 = selfRequest(var_$dialect, "Number", [0]);
var call31 = selfRequest(var_$module, "FileStream", [0]);
return new GraceSignature("seekBackward(1)", ["n"], [], [call30], call31);
}
sig32 = () => {
setLineNumber(47); // compilenode member
var call33 = selfRequest(var_$module, "FileStream", [0]);
return new GraceSignature("iterator", [], [], [], call33);
}
sig34 = () => {
setLineNumber(49); // compilenode member
var call35 = selfRequest(var_$dialect, "String", [0]);
return new GraceSignature("pathname", [], [], [], call35);
}
sig36 = () => {
setLineNumber(51); // compilenode member
var call37 = selfRequest(var_$dialect, "Boolean", [0]);
return new GraceSignature("isatty", [], [], [], call37);
}
sig38 = () => {
setLineNumber(53); // compilenode member
var call39 = selfRequest(var_$dialect, "Boolean", [0]);
return new GraceSignature("==(1)", ["other"], [], [type_Unknown], call39);
}
sig40 = () => {
setLineNumber(57); // compilenode member
var call41 = selfRequest(var_$module, "FileStream", [0]);
return new GraceSignature("clear", [], [], [], call41);
}
sig42 = () => {
setLineNumber(59); // compilenode member
var call43 = selfRequest(var_$dialect, "Boolean", [0]);
return new GraceSignature("eof", [], [], [], call43);
}
iface7.typeMethods = {
"read": sig8
, "size": sig10
, "hasNext": sig12
, "next": sig14
, "nextLine": sig16
, "write(1)": sig18
, "close": sig21
, "seek(1)": sig23
, "seekForward(1)": sig26
, "seekBackward(1)": sig29
, "iterator": sig32
, "pathname": sig34
, "isatty": sig36
, "==(1)": sig38
, "clear": sig40
, "eof": sig42
};
// call case 4: other requests
setLineNumber(10); // compilenode member
var call44 = selfRequest(var_$dialect, "Object", [0]);
var term6 = request(call44, "&(1)", [1], iface7);
var call4 = selfRequest(term6, "setTypeName(1)", [1], string5);
ret