Skip to content

Commit ef7cfdb

Browse files
Some changed to file IO and new functions
1 parent 7b145e2 commit ef7cfdb

File tree

5 files changed

+82
-22
lines changed

5 files changed

+82
-22
lines changed

src/builtins.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,12 @@
125125
#ifndef DISABLEIO
126126
{.name="parameters", .calltype=call, .returns=true, .rettype=list},
127127
{.name="input", .calltype=call, .returns=true, .rettype=string},
128-
{.name="open", .calltype=call, .argc=2, .args={string, string}, .returns=true, .rettype=io},
128+
{.name="open", .calltype=call, .argc=2, .args={symbol, string}, .returns=true, .rettype=io},
129129
{.name="read-file", .calltype=call, .argc=1, .args={io}, .returns=true, .rettype=string},
130+
{.name="read-line", .calltype=call, .argc=1, .args={io}, .returns=true, .rettype=string},
130131
{.name="close", .calltype=call, .argc=1, .args={io}},
131132
{.name="path", .calltype=call, .returns=true, .rettype=string},
133+
{.name="seek", .calltype=call, .argc=3, .args={symbol, number, io}, .returns=false},
132134
#endif
133135

134136
{.name=NULL},

src/cognac.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <sys/wait.h>
1616
#include <execinfo.h>
1717

18+
1819
#define STR_(x) #x
1920
#define STR(x) STR_(x)
2021
#define MAX_ERROR_LINE_LENGTH 256
@@ -26,6 +27,8 @@ module_t prelude1 = { .prefix = "prelude" }; // written in C
2627
module_t prelude2 = { .prefix = "prelude" }; // written in Cognate
2728
module_list_t preludes = { .mod=&prelude2, .next = &(module_list_t){.mod=&prelude1, .next=NULL} };
2829

30+
const char* builtin_symbols[] = { "start", "end", "current", "read", "write", "append", "read-write", "read-append", "read-write-existing" };
31+
2932
char runtime_filename[] = "/tmp/cognac-runtime-XXXXXX.h";
3033

3134
int usleep (unsigned int);
@@ -886,7 +889,12 @@ void to_c(module_t* mod)
886889
FILE* c_source = fopen(c_source_path, "w");
887890
fprintf(c_source, "#include \"%s\"\n\n", runtime_filename);
888891
for (symbol_list_t* syms = mod->symbols ; syms ; syms = syms->next)
889-
fprintf(c_source, "SYMBOL SYM%s = \"%s\";\n", syms->text, syms->text);
892+
{
893+
for (int i = 0 ; i < sizeof(builtin_symbols) / sizeof(builtin_symbols[0]) ; ++i)
894+
if (!strcmp(builtin_symbols[i], syms->text)) goto next;
895+
fprintf(c_source, "const SYMBOL SYM%s = \"%s\";\n", syms->text, syms->text);
896+
next:;
897+
}
890898
if (mod->symbols) fputc('\n', c_source);
891899
for (func_list_t* func = mod->funcs ; func ; func = func->next)
892900
{

src/prelude.cog

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,11 @@ Def Times (
4747

4848

4949
Def With (
50-
Let Fp be Open;
51-
Do Swap Fp;
50+
Let Mode be Symbol!;
51+
Let Filename be String!;
52+
Def Body;
53+
Let Fp be Open as Mode Filename;
54+
Body Fp;
5255
Close Fp
5356
);
5457

src/runtime.h

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,16 @@ extern int main(int, char**);
191191

192192
static const char* restrict function_stack_start;
193193

194+
const SYMBOL SYMstart = "start";
195+
const SYMBOL SYMend = "end";
196+
const SYMBOL SYMcurrent = "current";
197+
const SYMBOL SYMread = "read";
198+
const SYMBOL SYMwrite = "write";
199+
const SYMBOL SYMappend = "append";
200+
const SYMBOL SYMreadHwrite = "read-write";
201+
const SYMBOL SYMreadHappend = "read-append";
202+
const SYMBOL SYMreadHwriteHexisting = "read-write-existing";
203+
194204
// Variables and needed by functions.c defined in runtime.c
195205
static void init_stack(void);
196206
static STRING show_object(const ANY object, const _Bool, char*);
@@ -287,7 +297,7 @@ static STRING ___join(STRING, STRING);
287297
static NUMBER ___stringHlength(STRING);
288298
static STRING ___substring(NUMBER, NUMBER, STRING);
289299
static STRING ___input(void);
290-
static IO ___open(STRING, STRING);
300+
static IO ___open(SYMBOL, STRING);
291301
static void ___close(IO);
292302
static NUMBER ___number(STRING);
293303
static STRING ___path(void);
@@ -1697,7 +1707,7 @@ static STRING ___show(ANY o)
16971707

16981708
static LIST ___split(STRING sep, STRING str)
16991709
{
1700-
if (!*sep) throw_error("Empty separator");
1710+
if (!*sep) throw_error("Seperator cannot be empty");
17011711
LIST lst = NULL;
17021712
size_t len = strlen(sep);
17031713
char* found;
@@ -1961,12 +1971,19 @@ static NUMBER ___tanh(NUMBER a)
19611971
return tanh(a);
19621972
}
19631973

1964-
static IO ___open(STRING path, STRING mode)
1974+
static IO ___open(SYMBOL m, STRING path)
19651975
{
19661976
assert_impure();
1967-
// TODO mode should definitely be a symbol.
1977+
char* mode;
1978+
if (m == SYMread) mode = "r";
1979+
else if (m == SYMwrite) mode = "w";
1980+
else if (m == SYMappend) mode = "a";
1981+
else if (m == SYMreadHappend) mode = "a+";
1982+
else if (m == SYMreadHwrite) mode = "w+";
1983+
else if (m == SYMreadHwriteHexisting) mode = "r+";
1984+
else throw_error("Expected one of \\read, \\write, \\append, \\read-write, \\read-append, \\read-write-existing");
19681985
FILE* fp = fopen(path, mode);
1969-
if unlikely(!fp) throw_error_fmt("cannot open file '%s'", path);
1986+
if unlikely(!fp) throw_error_fmt("Cannot open file '%s'", path);
19701987
IO io = gc_malloc(sizeof *io);
19711988
io->path = path;
19721989
io->mode = mode;
@@ -1979,6 +1996,7 @@ static STRING ___readHfile(IO io)
19791996
assert_impure();
19801997
// Read a file to a string.
19811998
FILE *fp = io->file;
1999+
fseek(fp, 0, SEEK_SET); // seek to beginning
19822000
if unlikely(!io->mode) throw_error_fmt("File '%s' is not open", io->path);
19832001
if unlikely(fp == NULL) throw_error_fmt("Cannot open file '%s'", io->path);
19842002
struct stat st;
@@ -1988,7 +2006,14 @@ static STRING ___readHfile(IO io)
19882006
throw_error_fmt("Error reading file '%s'", io->path);
19892007
text[st.st_size] = '\0'; // Remove trailing eof.
19902008
return text;
1991-
// TODO: single line (or delimited) file read function for better IO performance
2009+
}
2010+
2011+
static STRING ___readHline(IO io)
2012+
{
2013+
assert_impure();
2014+
char* buf = (char*)(space[z] + alloc[z]); // use the top of memory as a buffer like Show does
2015+
fgets(buf, INT_MAX, io->file);
2016+
return gc_strdup(buf); // this can only GC once so won't overwrite the buffer.
19922017
}
19932018

19942019
static void ___close(IO io)
@@ -2018,16 +2043,21 @@ static void ___write(STRING s, IO io)
20182043
fputs(s, io->file);
20192044
}
20202045

2021-
static void ___seek(NUMBER n, IO io)
2046+
static void ___seek(SYMBOL ref, NUMBER n, IO io)
20222047
{
2023-
size_t p = n;
2024-
if unlikely(p != n) throw_error_fmt("cannot seek to position %.14g", n);
2025-
fseek(io->file, p, SEEK_CUR);
2048+
int pos;
2049+
if (ref == SYMstart) pos = SEEK_SET;
2050+
else if (ref == SYMend) pos = SEEK_END;
2051+
else if (ref == SYMcurrent) pos = SEEK_CUR;
2052+
else throw_error_fmt("Expected one of \\start, \\end, \\current");
2053+
long offset = n;
2054+
if unlikely(offset != n || fseek(io->file, offset, pos))
2055+
throw_error_fmt("Can't seek to position %.14g relative to %s", n, ref);
20262056
}
20272057

20282058
static void invalid_jump(uint8_t* env)
20292059
{
2030-
throw_error("cannot resume expired continuation");
2060+
throw_error("Cannot resume expired continuation");
20312061
}
20322062

20332063
static void oh_no(uint8_t* env)
@@ -2062,7 +2092,7 @@ static TABLE ___table (BLOCK expr)
20622092
// Move to a list.
20632093
TABLE d = NULL;
20642094
size_t len = stack_length();
2065-
if (len % 2 != 0) throw_error("table initialiser must be key-value pairs");
2095+
if (len % 2 != 0) throw_error("Table initialiser must be key-value pairs");
20662096
for (size_t i = 0; i < len; i += 2)
20672097
{
20682098
ANY key = stack.start[i+1];
@@ -2074,7 +2104,7 @@ static TABLE ___table (BLOCK expr)
20742104
ptrdiff_t diff = compare_objects(ptr->key, key);
20752105
if (diff > 0) { assign = (cognate_table**)&ptr->child1 ; ptr = ptr->child1; }
20762106
else if (diff < 0) { assign = (cognate_table**)&ptr->child2 ; ptr = ptr->child2; }
2077-
else throw_error("duplicate keys in table initialiser");
2107+
else throw_error("Duplicate keys in table initialiser");
20782108
}
20792109

20802110
*assign = gc_malloc(sizeof (**assign));

tests/io.cog

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
1-
Let S be With "tests/io.txt" "r" ( Read-file );
1+
With \read "tests/io.txt" (
22

3-
Print If == "foo\nbar\n" S
4-
"PASS: Reading multi-line file to string"
5-
else
6-
"FAIL: Reading multi-line file to string";
3+
Let F be the file;
4+
5+
6+
Let S be Read-file F;
7+
8+
Print If == "foo\nbar\n" S
9+
"PASS: Reading multi-line file to string"
10+
else
11+
"FAIL: Reading multi-line file to string";
12+
13+
Seek from \start to position 0 in F;
14+
15+
Let L be Read-line F;
16+
17+
Print If == "foo\n" L
18+
"PASS: Reading first line of file to string"
19+
else
20+
"FAIL: Reading first line of file to string";
21+
22+
23+
);

0 commit comments

Comments
 (0)