aboutsummaryrefslogtreecommitdiff
path: root/neb/std/fs.py
diff options
context:
space:
mode:
Diffstat (limited to 'neb/std/fs.py')
-rw-r--r--neb/std/fs.py80
1 files changed, 75 insertions, 5 deletions
diff --git a/neb/std/fs.py b/neb/std/fs.py
index 495c7ea..d20cde9 100644
--- a/neb/std/fs.py
+++ b/neb/std/fs.py
@@ -2,9 +2,15 @@ from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic
from ..structs import *
from pathlib import Path
from glob import glob
+from io import UnsupportedOperation
+import sys
FS = Environment()
+FS.register("_stdin_", Handle(sys.stdin))
+FS.register("_stdout_", Handle(sys.stdout))
+FS.register("_stderr_", Handle(sys.stderr))
+
def interpretExists(symbol, args, env, ns):
return Bool(Path(args[0].value).resolve().exists())
@@ -39,13 +45,77 @@ def interpretWithWrite(symbol, args, env, ns):
FS.register("with-write", Builtin("with-write", interpretWithWrite, [Arg("filename", TypeEnum.STRING)], Arg("exprs", TypeEnum.ANY, lazy=True)))
def interpretWrite(symbol, args, env, ns):
- # write :string :filehandle
- line = args[0]
+ string = args[0]
handle = args[1]
- handle.args[0].write(line.value) # TODO wrong! how do we evaluate a handle?
- return Literal([])
+ try:
+ handle.file.write(string.value)
+ except UnsupportedOperation:
+ raise InterpretPanic(symbol, f"{handle} is not writable!")
+ except ValueError:
+ raise InterpretPanic(symbol, f"{handle} is closed")
+ return List([])
+
+FS.register("write", Builtin("write", interpretWrite, [Arg("string", TypeEnum.STRING), Arg("handle", TypeEnum.HANDLE)], return_type=TypeEnum.LIST))
+
+def interpretOpenRead(symbol, args, env, ns):
+ name = args[0].value
+ fil = Path(name)
+ if not fil.exists():
+ raise InterpretPanic(symbol, "file does not exist", fil)
+ try:
+ f = open(str(fil), "r")
+ except:
+ raise InterpretPanic(symbol, "cannot open {fil} for reading")
+ return Handle(f)
+
+FS.register("open-read", Builtin("open-read", interpretOpenRead, [Arg("filename", TypeEnum.STRING)], return_type=TypeEnum.HANDLE))
+
+def interpretOpenWrite(symbol, args, env, ns):
+ name = args[0].value
+ fil = Path(name)
+ try:
+ f = open(str(fil), "w")
+ except:
+ raise InterpretPanic(symbol, "cannot open {fil} for writing")
+ return Handle(f)
+
+FS.register("open-write", Builtin("open-write", interpretOpenWrite, [Arg("filename", TypeEnum.STRING)], return_type=TypeEnum.HANDLE))
+
+def interpretOpenAppend(symbol, args, env, ns):
+ name = args[0].value
+ fil = Path(name)
+ try:
+ f = open(str(fil), "a")
+ except:
+ raise InterpretPanic(symbol, "cannot open {fil} for appending")
+ return Handle(f)
+
+FS.register("open-append", Builtin("open-append", interpretOpenAppend, [Arg("filename", TypeEnum.STRING)], return_type=TypeEnum.HANDLE))
+
+def interpretClose(symbol, args, env, ns):
+ try:
+ args[0].file.close()
+ # TODO ideally we'd be able to remove it from the env
+ # but by this point, we don't know its symbol
+ # though it may not be in the env, e.g.
+ # (close (print (read (open-read "fil.txt"))))
+ except:
+ raise InterpretPanic(symbol, "cannot close {args[0]}")
+ return List([])
+
+FS.register("close", Builtin("close", interpretClose, [Arg("handle", TypeEnum.HANDLE)], return_type=TypeEnum.LIST))
+
+def interpretRead(symbol, args, env, ns):
+ handle = args[0]
+ try:
+ inp = args[0].file.read()
+ except UnsupportedOperation:
+ raise InterpretPanic(symbol, f"{handle} is not writable!")
+ except ValueError:
+ raise InterpretPanic(symbol, f"{handle} is closed")
+ return String(inp)
-FS.register("write", Builtin("write", interpretWrite, [Arg("string", TypeEnum.STRING), Arg("filename", TypeEnum.LIST)]))
+FS.register("read", Builtin("read", interpretRead, [Arg("handle", TypeEnum.HANDLE)], return_type=TypeEnum.STRING))
def interpretReadLines(symbol, args, env, ns):
target_file_name = args[0].value