Skip to content

Some stdlib extensions, and a missing case in the pretty printer #266

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/comp/front/lexer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import std.io.stdio_reader;
import std.io;
import std._str;
import std.map;
import std.map.hashmap;
Expand All @@ -18,9 +18,9 @@ state type reader = state obj {
fn get_reserved() -> hashmap[str,()];
};

fn new_reader(stdio_reader rdr, str filename) -> reader
impure fn new_reader(io.reader rdr, str filename) -> reader
{
state obj reader(stdio_reader rdr,
state obj reader(io.reader rdr,
str filename,
mutable char c,
mutable char n,
Expand Down Expand Up @@ -72,7 +72,7 @@ fn new_reader(stdio_reader rdr, str filename) -> reader
col += 1u;
}

n = rdr.getc() as char;
n = rdr.read_char() as char;
}

fn mark() {
Expand Down Expand Up @@ -200,8 +200,8 @@ fn new_reader(stdio_reader rdr, str filename) -> reader
reserved.insert("m128", ()); // IEEE 754-2008 'decimal128'
reserved.insert("dec", ()); // One of m32, m64, m128

ret reader(rdr, filename, rdr.getc() as char, rdr.getc() as char,
1u, 0u, 1u, 0u, keywords, reserved);
ret reader(rdr, filename, rdr.read_char() as char,
rdr.read_char() as char, 1u, 0u, 1u, 0u, keywords, reserved);
}


Expand Down
2 changes: 1 addition & 1 deletion src/comp/front/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impure fn new_parser(session.session sess,
if (_str.ends_with(path, ".rc")) {
ftype = CRATE_FILE;
}
auto srdr = io.new_stdio_reader(path);
auto srdr = io.file_reader(path);
auto rdr = lexer.new_reader(srdr, path);
auto npos = rdr.get_curr_pos();
ret stdio_parser(sess, env, ftype, lexer.next_token(rdr),
Expand Down
5 changes: 5 additions & 0 deletions src/lib/_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ fn from_bytes(vec[u8] v) : is_utf8(v) -> str {
ret rustrt.str_from_vec(v);
}

// FIXME temp thing
fn unsafe_from_bytes(vec[u8] v) -> str {
ret rustrt.str_from_vec(v);
}

fn refcount(str s) -> uint {
auto r = rustrt.refcount[u8](s);
if (r == dbg.const_refcount) {
Expand Down
20 changes: 20 additions & 0 deletions src/lib/fs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
native "rust" mod rustrt {
fn rust_file_is_dir(str path) -> int;
}

impure fn file_is_dir(str path) -> bool {
ret rustrt.rust_file_is_dir(path) != 0;
}

impure fn list_dir(str path) -> vec[str] {
if (path.(_str.byte_len(path)-1u) as char != os_fs.path_sep) {
path += _str.unsafe_from_bytes(vec(os_fs.path_sep as u8));
}
let vec[str] full_paths = vec();
for (str filename in os_fs.list_dir(path)) {
if (!_str.eq(filename, ".")) {if (!_str.eq(filename, "..")) {
full_paths = _vec.push[str](full_paths, path + filename);
}}
}
ret full_paths;
}
200 changes: 121 additions & 79 deletions src/lib/io.rs
Original file line number Diff line number Diff line change
@@ -1,93 +1,113 @@
import os.libc;

type stdio_reader = state obj {
fn getc() -> int;
fn ungetc(int i);
};

fn new_stdio_reader(str path) -> stdio_reader {
state obj stdio_FILE_reader(os.libc.FILE f) {
fn getc() -> int {
ret os.libc.fgetc(f);
}
fn ungetc(int i) {
os.libc.ungetc(i, f);
}
drop {
os.libc.fclose(f);
}
}
auto FILE = os.libc.fopen(_str.buf(path), _str.buf("r"));
check (FILE as uint != 0u);
ret stdio_FILE_reader(FILE);
native "rust" mod rustrt {
fn rust_get_stdin() -> os.libc.FILE;
fn rust_get_stdout() -> os.libc.FILE;
}

// Reading

type buf_reader = state obj {
fn read() -> vec[u8];
};

type buf_writer = state obj {
fn write(vec[u8] v);
};

fn default_bufsz() -> uint {
ret 4096u;
}

fn new_buf() -> vec[u8] {
ret _vec.alloc[u8](default_bufsz());
}

fn new_buf_reader(str path) -> buf_reader {
// TODO This is all buffered. We might need an unbuffered variant as well

state obj fd_buf_reader(int fd, mutable vec[u8] buf) {
tag seek_style {seek_set; seek_end; seek_cur;}

fn read() -> vec[u8] {

// Ensure our buf is singly-referenced.
if (_vec.rustrt.refcount[u8](buf) != 1u) {
buf = new_buf();
}

auto len = default_bufsz();
auto vbuf = _vec.buf[u8](buf);
auto count = os.libc.read(fd, vbuf, len);

if (count < 0) {
log "error filling buffer";
log sys.rustrt.last_os_error();
fail;
}
type reader =
state obj {
impure fn read_byte() -> u8;
impure fn read_bytes(uint len) -> vec[u8];
impure fn read_char() -> int;
impure fn unread_char(int i);
impure fn read_c_str() -> str;
impure fn read_le_uint(uint size) -> uint;
impure fn read_le_int(uint size) -> int;

impure fn seek(int offset, seek_style whence);
};

_vec.len_set[u8](buf, count as uint);
ret buf;
state obj FILE_reader(os.libc.FILE f, bool must_close) {
impure fn read_byte() -> u8 {
ret os.libc.fgetc(f) as u8;
}
impure fn read_bytes(uint len) -> vec[u8] {
auto buf = _vec.alloc[u8](len);
auto read = os.libc.fread(_vec.buf[u8](buf), 1u, len, f);
check(read == len);
ret buf;
}
impure fn read_char() -> int {
ret os.libc.fgetc(f);
}
impure fn unread_char(int ch) {
os.libc.ungetc(ch, f);
}
impure fn read_c_str() -> str {
auto buf = "";
while (true) {
auto ch = os.libc.fgetc(f);
if (ch < 1) {break;}
buf += _str.unsafe_from_bytes(vec(ch as u8));
}

drop {
os.libc.close(fd);
ret buf;
}
// TODO deal with eof?
impure fn read_le_uint(uint size) -> uint {
auto val = 0u;
auto pos = 0u;
while (size > 0u) {
val += (os.libc.fgetc(f) as uint) << pos;
pos += 8u;
size -= 1u;
}
ret val;
}
impure fn read_le_int(uint size) -> int {
auto val = 0u;
auto pos = 0u;
while (size > 0u) {
val += (os.libc.fgetc(f) as uint) << pos;
pos += 8u;
size -= 1u;
}
ret val as int; // TODO does that work?
}
impure fn seek(int offset, seek_style whence) {
auto wh;
alt (whence) {
case (seek_set) {wh = 0;}
case (seek_cur) {wh = 1;}
case (seek_end) {wh = 2;}
}
check(os.libc.fseek(f, offset, wh) == 0);
}
drop {
if (must_close) {os.libc.fclose(f);}
}
}

auto fd = os.libc.open(_str.buf(path),
os.libc_constants.O_RDONLY() |
os.libc_constants.O_BINARY(),
0u);
fn stdin_reader() -> reader {
ret FILE_reader(rustrt.rust_get_stdin(), false);
}

if (fd < 0) {
log "error opening file for reading";
log sys.rustrt.last_os_error();
fail;
}
ret fd_buf_reader(fd, new_buf());
fn file_reader(str path) -> reader {
auto f = os.libc.fopen(_str.buf(path), _str.buf("r"));
check (f as uint != 0u);
ret FILE_reader(f, true);
}

// Writing

// TODO This is all unbuffered. We might need a buffered variant as well

tag fileflag {
append;
create;
truncate;
}

type buf_writer = state obj {
fn write(vec[u8] v);
};

state obj fd_buf_writer(int fd, bool must_close) {
fn write(vec[u8] v) {
auto len = _vec.len[u8](v);
Expand Down Expand Up @@ -141,8 +161,21 @@ type writer =
impure fn write_str(str s);
impure fn write_int(int n);
impure fn write_uint(uint n);
impure fn write_bytes(vec[u8] bytes);
impure fn write_le_uint(uint n, uint size);
impure fn write_le_int(int n, uint size);
};

fn uint_to_bytes(uint n, uint size) -> vec[u8] {
let vec[u8] bytes = vec();
while (size > 0u) {
bytes += vec((n & 255u) as u8);
n >>= 8u;
size -= 1u;
}
ret bytes;
}

state obj new_writer(buf_writer out) {
impure fn write_str(str s) {
out.write(_str.bytes(s));
Expand All @@ -153,6 +186,15 @@ state obj new_writer(buf_writer out) {
impure fn write_uint(uint n) {
out.write(_str.bytes(_uint.to_str(n, 10u)));
}
impure fn write_bytes(vec[u8] bytes) {
out.write(bytes);
}
impure fn write_le_uint(uint n, uint size) {
out.write(uint_to_bytes(n, size));
}
impure fn write_le_int(int n, uint size) {
out.write(uint_to_bytes(n as uint, size));
}
}

fn file_writer(str path, vec[fileflag] flags) -> writer {
Expand All @@ -170,21 +212,21 @@ type str_writer =
fn get_str() -> str;
};

type str_buf = @rec(mutable str buf);
type byte_buf = @rec(mutable vec[u8] buf);

state obj byte_buf_writer(byte_buf buf) {
fn write(vec[u8] v) {buf.buf += v;}
}

// TODO awkward! it's not possible to implement a writer with an extra method
fn string_writer() -> str_writer {
auto buf = @rec(mutable buf = "");
state obj str_writer_writer(str_buf buf) {
impure fn write_str(str s) { buf.buf += s; }
impure fn write_int(int n) { buf.buf += _int.to_str(n, 10u); }
impure fn write_uint(uint n) { buf.buf += _uint.to_str(n, 10u); }
}
state obj str_writer_wrap(writer wr, str_buf buf) {
let vec[u8] b = vec();
let byte_buf buf = @rec(mutable buf = b);
state obj str_writer_wrap(writer wr, byte_buf buf) {
fn get_writer() -> writer {ret wr;}
fn get_str() -> str {ret buf.buf;}
fn get_str() -> str {ret _str.unsafe_from_bytes(buf.buf);}
}
ret str_writer_wrap(str_writer_writer(buf), buf);
ret str_writer_wrap(new_writer(byte_buf_writer(buf)), buf);
}

//
Expand Down
5 changes: 4 additions & 1 deletion src/lib/linux_os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ native mod libc = "libc.so.6" {
fn fclose(FILE f);
fn fgetc(FILE f) -> int;
fn ungetc(int c, FILE f);
fn fread(vbuf buf, uint size, uint n, FILE f) -> uint;
fn fseek(FILE f, int offset, int whence) -> int;

type dir;
// readdir is a mess; handle via wrapper function in rustrt.
fn opendir(sbuf d) -> dir;
fn closedir(dir d) -> int;
type dirent;
fn readdir(dir d) -> dirent;

fn getenv(sbuf n) -> sbuf;
fn setenv(sbuf n, sbuf v, int overwrite) -> int;
Expand Down
5 changes: 4 additions & 1 deletion src/lib/macos_os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ native mod libc = "libc.dylib" {
fn fclose(FILE f);
fn fgetc(FILE f) -> int;
fn ungetc(int c, FILE f);
fn fread(vbuf buf, uint size, uint n, FILE f) -> uint;
fn fseek(FILE f, int offset, int whence) -> int;

type dir;
// readdir is a mess; handle via wrapper function in rustrt.
fn opendir(sbuf d) -> dir;
fn closedir(dir d) -> int;
type dirent;
fn readdir(dir d) -> dirent;

fn getenv(sbuf n) -> sbuf;
fn setenv(sbuf n, sbuf v, int overwrite) -> int;
Expand Down
19 changes: 19 additions & 0 deletions src/lib/posix_fs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
native "rust" mod rustrt {
fn rust_dirent_filename(os.libc.dirent ent) -> str;
}

impure fn list_dir(str path) -> vec[str] {
// TODO ensure this is always closed
auto dir = os.libc.opendir(_str.buf(path));
check (dir as uint != 0u);
let vec[str] result = vec();
while (true) {
auto ent = os.libc.readdir(dir);
if (ent as int == 0) {break;}
result = _vec.push[str](result, rustrt.rust_dirent_filename(ent));
}
os.libc.closedir(dir);
ret result;
}

const char path_sep = '/';
Loading