Skip to content

Commit c806840

Browse files
committed
runtime: add support for and implement stdin
1 parent 619539a commit c806840

5 files changed

Lines changed: 224 additions & 21 deletions

File tree

src/interpreter/Interpreter.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
#include "executable/bytecode/BytecodeProgram.hpp"
2525
#include "utilities.hpp"
2626

27+
#include <cstdio>
2728
#include <filesystem>
29+
#include <unistd.h>
2830

2931
namespace fs = std::filesystem;
3032
using namespace py;
@@ -186,10 +188,23 @@ void Interpreter::internal_setup(const std::string &name,
186188
std::get<PyObject *>(io_module->symbol_table()->map().at(String{ "FileIO" }));
187189
auto *buffered_writer =
188190
std::get<PyObject *>(io_module->symbol_table()->map().at(String{ "BufferedWriter" }));
191+
auto *buffered_reader =
192+
std::get<PyObject *>(io_module->symbol_table()->map().at(String{ "BufferedReader" }));
189193
auto *text_io_wrapper =
190194
std::get<PyObject *>(io_module->symbol_table()->map().at(String{ "TextIOWrapper" }));
195+
auto py_stdin =
196+
file_io->call(PyTuple::create(Number{ STDIN_FILENO }, String{ "rb" }).unwrap(), nullptr)
197+
.and_then([buffered_reader](PyObject *stdin) {
198+
return buffered_reader->call(PyTuple::create(stdin).unwrap(), nullptr);
199+
})
200+
.and_then([text_io_wrapper](PyObject *stdin_buffer_writer) {
201+
return text_io_wrapper->call(
202+
PyTuple::create(stdin_buffer_writer).unwrap(), nullptr);
203+
});
204+
ASSERT(py_stdin.is_ok());
191205
auto py_stdout =
192-
file_io->call(PyTuple::create(Number{ 1 }, String{ "wb" }).unwrap(), nullptr)
206+
file_io->call(
207+
PyTuple::create(Number{ STDOUT_FILENO }, String{ "wb" }).unwrap(), nullptr)
193208
.and_then([buffered_writer](PyObject *stdout) {
194209
return buffered_writer->call(PyTuple::create(stdout).unwrap(), nullptr);
195210
})
@@ -199,7 +214,8 @@ void Interpreter::internal_setup(const std::string &name,
199214
});
200215
ASSERT(py_stdout.is_ok());
201216
auto py_stderr =
202-
file_io->call(PyTuple::create(Number{ 2 }, String{ "wb" }).unwrap(), nullptr)
217+
file_io->call(
218+
PyTuple::create(Number{ STDERR_FILENO }, String{ "wb" }).unwrap(), nullptr)
203219
.and_then([buffered_writer](PyObject *stderr) {
204220
return buffered_writer->call(PyTuple::create(stderr).unwrap(), nullptr);
205221
})
@@ -208,6 +224,7 @@ void Interpreter::internal_setup(const std::string &name,
208224
PyTuple::create(stderr_buffer_writer).unwrap(), nullptr);
209225
});
210226
ASSERT(py_stderr.is_ok());
227+
sys->add_symbol(PyString::create("stdin").unwrap(), py_stdin.unwrap());
211228
sys->add_symbol(PyString::create("stdout").unwrap(), py_stdout.unwrap());
212229
sys->add_symbol(PyString::create("stderr").unwrap(), py_stderr.unwrap());
213230
}

src/runtime/PyMemoryView.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,13 @@ PyResult<PyObject *> PyMemoryView::create(PyObject *object)
246246
type_error("memoryview: a bytes-like object is required, not {}", object->type()->name()));
247247
}
248248

249+
PyResult<PyObject *> PyMemoryView::create(PyBuffer buffer)
250+
{
251+
auto obj = VirtualMachine::the().heap().allocate<PyMemoryView>(std::move(buffer));
252+
if (!obj) { return Err(memory_error(sizeof(PyMemoryView))); }
253+
return Ok(obj);
254+
}
255+
249256
PyResult<PyObject *> PyMemoryView::__new__(const PyType *, PyTuple *args, PyDict *kwargs)
250257
{
251258
auto result = PyArgsParser<PyObject *>::unpack_tuple(args,

src/runtime/PyMemoryView.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class PyMemoryView : public PyBaseObject
2424

2525
public:
2626
static PyResult<PyObject *> create(PyObject *object);
27+
static PyResult<PyObject *> create(PyBuffer buffer);
2728

2829
static PyResult<PyObject *> __new__(const PyType *type, PyTuple *args, PyDict *kwargs);
2930
PyResult<PyObject *> __repr__() const;

src/runtime/modules/BuiltinsModule.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,14 @@ PyResult<PyObject *> print(const PyTuple *args, const PyDict *kwargs, Interprete
8080
.unwrap();
8181
// sys.stdout may be None when FILE* stdout isn't connected
8282
if (!file || file == py_none()) { return Ok(py_none()); }
83+
// TODO: flush should be false, but for now we keep it as true, since there is no flush at
84+
// interpreter shutdown
8385
bool flush = true;
8486
if (kwargs) {
8587
static const Value separator_keyword = String{ "sep" };
8688
static const Value end_keyword = String{ "end" };
89+
static const Value file_keyword = String{ "file" };
90+
static const Value flush_keyword = String{ "flush" };
8791

8892
if (auto it = kwargs->map().find(separator_keyword); it != kwargs->map().end()) {
8993
auto maybe_str = it->second;
@@ -107,6 +111,18 @@ PyResult<PyObject *> print(const PyTuple *args, const PyDict *kwargs, Interprete
107111
}
108112
end = PyString::create(std::get<String>(maybe_str).s).unwrap();
109113
}
114+
if (auto it = kwargs->map().find(file_keyword); it != kwargs->map().end()) {
115+
auto file_ = PyObject::from(it->second);
116+
if (file_.is_err()) { return file_; }
117+
file = file_.unwrap();
118+
}
119+
if (auto it = kwargs->map().find(flush_keyword); it != kwargs->map().end()) {
120+
auto flush_ = PyObject::from(it->second);
121+
if (flush_.is_err()) { return flush_; }
122+
const auto truthy = flush_.unwrap()->true_();
123+
if (truthy.is_err()) { return Err(truthy.unwrap_err()); }
124+
flush = truthy.unwrap();
125+
}
110126
}
111127
auto file_write_ = file->get_method(PyString::create("write").unwrap());
112128
if (file_write_.is_err()) { return file_write_; }

0 commit comments

Comments
 (0)