aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootstrap/all.h1
-rw-r--r--bootstrap/cgen.c8
-rw-r--r--bootstrap/env.c4
-rw-r--r--bootstrap/parse.c17
-rw-r--r--examples/ack.cff (renamed from bootstrap/ack.cff)0
-rw-r--r--examples/libc.hff32
-rw-r--r--src/cffc.hff (renamed from src/all.hff)62
-rw-r--r--src/common.hff45
-rw-r--r--src/env.cff3
-rw-r--r--src/fmt.cff25
-rw-r--r--src/main.cff5
-rw-r--r--src/map.hff5
-rw-r--r--src/mem.hff3
-rw-r--r--src/parse.cff23
-rw-r--r--src/set.hff36
-rw-r--r--src/targ.cff3
-rw-r--r--src/targ.hff12
-rw-r--r--src/type.cff3
-rw-r--r--src/type.hff15
-rw-r--r--src/util.cff5
-rw-r--r--src/util.hff12
-rw-r--r--src/vec.hff9
22 files changed, 224 insertions, 104 deletions
diff --git a/bootstrap/all.h b/bootstrap/all.h
index 9bbab37..bb0711a 100644
--- a/bootstrap/all.h
+++ b/bootstrap/all.h
@@ -290,6 +290,7 @@ struct decl {
int loopid;
};
int age;
+ bool _gen;
};
struct teplparam {
diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c
index 5c64a30..39cbba0 100644
--- a/bootstrap/cgen.c
+++ b/bootstrap/cgen.c
@@ -50,7 +50,11 @@ pristring(const char *s, u64 n) {
extern int isprint(int);
pri("\"");
for (int i = 0; i < n; ++i) {
- if (isprint(s[i]))
+ if (s[i] == '"')
+ pri("\\\"");
+ else if (s[i] == '\\')
+ pri("\\\\");
+ else if (isprint(s[i]))
pri("%c", s[i]);
else
fprintf(outfp, "\\%.3o", s[i]);
@@ -699,6 +703,7 @@ genstatic(bool externp, const char *cname, struct var *var) {
static void
gendecl(struct decl *decl, bool toplevel) {
const char *p = fileid2path(decl->span.fileid);
+ if (decl->_gen) return;
switch (decl->t) {
case Dfn:
pri("#line %d %S\n", decl->span.line, p, (u64)strlen(p));
@@ -718,6 +723,7 @@ gendecl(struct decl *decl, bool toplevel) {
case Dtype: case Ddef: case Dtepl: case Dmacro: case Dlabel:
break;
}
+ decl->_gen = 1;
}
static void
diff --git a/bootstrap/env.c b/bootstrap/env.c
index 40392b9..21d9580 100644
--- a/bootstrap/env.c
+++ b/bootstrap/env.c
@@ -42,6 +42,10 @@ envput(struct env *env, const struct decl *decl) {
return d0;
if (d0->t == Dmacro && !memcmp(&decl->macro, &d0->macro, sizeof decl->macro))
return d0;
+ if (d0->t == Dtype && d0->ty == decl->ty)
+ return d0;
+ if (d0->t == Dfn && !memcmp(&decl->fn, &d0->fn, sizeof decl->fn))
+ return d0;
if (d0->t == Dtepl && !memcmp(&decl->tepl, &d0->tepl, sizeof decl->tepl))
return d0;
for (int kind = TYstruct; kind <= TYeunion; ++kind) {
diff --git a/bootstrap/parse.c b/bootstrap/parse.c
index 4a1721d..0c619fc 100644
--- a/bootstrap/parse.c
+++ b/bootstrap/parse.c
@@ -2925,7 +2925,7 @@ getbasedir(const char *path) {
static struct comfile
doimport(struct parser *P, const char *path) {
- static vec_t(struct entry { const char *s; struct comfile cf; }) seen;
+ static vec_t(struct entry { const char *s; struct comfile cf; bool wip; }) seen;
char path2[PATH_MAX], _rpath[PATH_MAX], *rpath;
struct comfile cf = {0};
struct parser P2;
@@ -2934,16 +2934,23 @@ doimport(struct parser *P, const char *path) {
if (!(rpath = realpath(path2, _rpath)))
fatal(P, P->tokspan, "import %q: %s", path, strerror(errno));
- for (int i = 0; i < seen.length; ++i)
- if (!strcmp(seen.data[i].s, rpath))
- return seen.data[i].cf;
+ for (int i = 0; i < seen.length; ++i) {
+ if (!strcmp(seen.data[i].s, rpath)) {
+ if (seen.data[i].wip) {
+ epri("warning: \"%s\": circular import detected: \"%s\" being processed\n",
+ P->curfile, path);
+ }
+ return seen.data[i].cf;
+ }
+ }
rpath = xstrdup(rpath);
// P2.primenv = P->primenv;
initparser(&P2, rpath);
P2.is_header = 1;
- vec_push(&seen, ((struct entry) { rpath, cf }));
+ vec_push(&seen, ((struct entry) { rpath, cf, 1 }));
parse(&cf, &P2);
+ seen.data[seen.length - 1].wip = 0;
seen.data[seen.length - 1].cf = cf;
return cf;
}
diff --git a/bootstrap/ack.cff b/examples/ack.cff
index 233abc2..233abc2 100644
--- a/bootstrap/ack.cff
+++ b/examples/ack.cff
diff --git a/examples/libc.hff b/examples/libc.hff
new file mode 100644
index 0000000..488a495
--- /dev/null
+++ b/examples/libc.hff
@@ -0,0 +1,32 @@
+// stdio.h
+struct FILE;
+extern static stdin *FILE,
+ stdout *FILE,
+ stderr *FILE;
+extern fn printf(fmt *const u8, ...) int;
+extern fn fprintf(fp *FILE, fmt *const u8, ...) int;
+extern fn sprintf(*u8, fmt *const u8, ...) int;
+extern fn snprintf(*u8, usize, fmt *const u8, ...) int;
+extern fn fopen(path *const u8, mode *const u8) *FILE;
+extern fn fclose(*FILE) int;
+extern fn fgetc(*FILE) int;
+extern fn fputc(int, *FILE) int;
+def EOF = -1;
+
+// stdlib.h
+extern fn abort() void;
+extern fn exit(c int) void;
+extern fn perror(s *const u8) void;
+extern fn malloc(n usize) *void;
+extern fn calloc(n usize, m usize) *void;
+extern fn realloc(p *void, n usize) *void;
+extern fn free(p *void) void;
+
+// string.h
+extern fn strlen(s *const u8) usize;
+extern fn strcmp(a *const u8, b *const u8) int;
+extern fn memcpy(*void, *const void, usize) *void;
+extern fn strcpy(*u8, *const u8) *u8;
+
+//ctype.h
+extern fn tolower(int) int;
diff --git a/src/all.hff b/src/cffc.hff
index 4ae3e26..dcb91f7 100644
--- a/src/all.hff
+++ b/src/cffc.hff
@@ -1,34 +1,7 @@
-import "mem.hff";
import "libc.hff";
+import "mem.hff";
import "option.hff";
-/// Macros
-
-defmacro assert {
-(ex, s, ...args) [
- (do
- if not (ex) {
- fprintf(stderr, "%s:%d: assertion failed: ", #FILE, #LINE);
- fprintf(stderr, s, args);
- fprintf(stderr, "\n");
- abort();
- }
- )
-]
-}
-
-defmacro foreach(x, i, a, ...body) [
- {
- let $a = a;
- for let i = 0; i < $a.#len; ++i {
- let x = $a[i];
- { body }
- }
- }
-]
-
-defmacro streq(a,b) [ (strcmp(a,b) == 0) ]
-
/// Types
struct Type;
@@ -138,25 +111,15 @@ struct Targ {
extern fn parser_init(*Parser, path *const u8) void;
extern fn parse(*Parser) [#]Decl;
-// util.cff
-extern fn xmalloc(n usize) *void;
-extern fn xcalloc(n usize, m usize) *void;
-extern fn xrealloc(p *void, n usize) *void;
-extern fn xstrdup(str *const u8) *u8;
-def FNV1A_INI u32 = 0x811c9dc5;
-extern fn fnv1a(h u32, [#]const u8) u32;
-extern fn fnv1a_s(h u32, *const u8) u32;
-extern fn fnv1a_i(h u32, i64) u32;
-extern fn addfilepath(*const u8) int;
-extern fn fatal(*Parser, Loc, fmt *const u8, ...) void;
-extern fn internstr(*const u8) *const u8;
-
// fmt.cff
extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, va_list) void;
extern fn pfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ...) void;
extern fn vefmt(fmt *const u8, ap va_list) void;
extern fn efmt(fmt *const u8, ...) void;
+// .. util.cff ..
+extern fn fatal(*Parser, Loc, fmt *const u8, ...) void;
+
// type.cff
// env.cff
@@ -166,20 +129,3 @@ extern fn envput(*Env, *const Decl) *Decl;
// targ.cff
extern static g_targ *const Targ;
extern fn targ_ini(name *const u8) bool;
-
-// Inline functions
-fn bswap32(x u32) u32 {
- return (x >> 24)
- | ((x >> 8) & 0x00FF00)
- | ((x << 8) & 0xFF0000)
- | (x << 24);
-}
-
-fn bswap64(x u64) u64 {
- return (as(u64)bswap32(x) << 32)
- | (bswap32(x >> 32));
-}
-
-fn spanz(x *const u8) [#]const u8 {
- return x[0::strlen(x)];
-}
diff --git a/src/common.hff b/src/common.hff
new file mode 100644
index 0000000..aac733e
--- /dev/null
+++ b/src/common.hff
@@ -0,0 +1,45 @@
+import "libc.hff";
+
+/// Macros
+
+defmacro assert {
+(ex, s, ...args) [
+ (do
+ if not (ex) {
+ fprintf(stderr, "%s:%d: assertion failed: ", #FILE, #LINE);
+ fprintf(stderr, s, args);
+ fprintf(stderr, "\n");
+ abort();
+ }
+ )
+]
+}
+
+defmacro foreach(x, i, a, ...body) [
+ {
+ let $a = a;
+ for let i = 0; i < $a.#len; ++i {
+ let x = $a[i];
+ { body }
+ }
+ }
+]
+
+defmacro streq(a,b) [ (strcmp(a,b) == 0) ]
+
+// Inline functions
+fn bswap32(x u32) u32 {
+ return (x >> 24)
+ | ((x >> 8) & 0x00FF00)
+ | ((x << 8) & 0xFF0000)
+ | (x << 24);
+}
+
+fn bswap64(x u64) u64 {
+ return (as(u64)bswap32(x) << 32)
+ | (bswap32(x >> 32));
+}
+
+fn spanz(x *const u8) [#]const u8 {
+ return x[0::strlen(x)];
+}
diff --git a/src/env.cff b/src/env.cff
index 8878238..d1eab07 100644
--- a/src/env.cff
+++ b/src/env.cff
@@ -1,5 +1,6 @@
+import "cffc.hff";
import "map.hff";
-import "all.hff";
+import "util.hff";
struct StringKeyTraits {
fn hash(s *const u8) u32 { return fnv1a_s(FNV1A_INI, s); }
diff --git a/src/fmt.cff b/src/fmt.cff
index 8212593..90fcd47 100644
--- a/src/fmt.cff
+++ b/src/fmt.cff
@@ -1,4 +1,5 @@
-import "all.hff";
+import "cffc.hff";
+import "common.hff";
extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) void {
defmacro p(x) [ proc(x, parg) ]
@@ -10,14 +11,22 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list)
defmacro pch(ch) [ {
extern fn isprint(int) int;
- let $ch = ch;
- if isprint($ch) != 0 {
+ let $ch u8 = ch;
+ switch {
+ case $ch == '\'';
+ ps("\\'");
+ case $ch == '\"';
+ ps("\\\"");
+ case $ch == '\\';
+ ps("\\\\");
+ case isprint($ch) != 0;
p($ch);
- } else {
- p('\\');
- p('0' + ($ch % 8));
- p('0' + (($ch / 8) % 8));
- p('0' + (($ch / 8 / 8) % 8));
+ case $ch == '\n';
+ ps("\\n");
+ case else;
+ ps("\\x");
+ p("0123456789ABCDEF"[($ch >> 4) & 15]);
+ p("0123456789ABCDEF"[$ch & 15]);
}
} ]
diff --git a/src/main.cff b/src/main.cff
index 596a411..7cc90a0 100644
--- a/src/main.cff
+++ b/src/main.cff
@@ -1,6 +1,5 @@
-import "all.hff";
-import "libc.hff";
-import "vec.hff";
+import "cffc.hff";
+import "common.hff";
extern fn main(argc int, argv **u8) int {
assert(argc > 1, "args?");
diff --git a/src/map.hff b/src/map.hff
index 87d0506..d7883dd 100644
--- a/src/map.hff
+++ b/src/map.hff
@@ -1,4 +1,5 @@
-import "all.hff";
+import "common.hff";
+import "util.hff";
// KTraits:
// :hash(K) u32
@@ -32,6 +33,8 @@ struct Map<K, V, KTraits> {
}
fn _reallockvb(self *Map) void {
+ // keys, vals, bitmap are in a contiguous memory allocation,
+ // XXX ^ alignment
let p = xcalloc((self.N * (sizeof K + sizeof V)) + (self.N / 8), 1);
self.keys = p;
self.vals = as(*V)(self.keys + self.N);
diff --git a/src/mem.hff b/src/mem.hff
index a86bee3..805c3ce 100644
--- a/src/mem.hff
+++ b/src/mem.hff
@@ -1,8 +1,7 @@
import "libc.hff";
-import "all.hff";
-def ARENA_SIZE = 16 * 1024;
defmacro ALIGNUP(x,a) [ (((x) + ((a) - 1)) & -(a)) ]
+def ARENA_SIZE = 16 * 1024;
extern fn xmalloc(n usize) *void;
extern fn xcalloc(n usize, m usize) *void;
extern fn xrealloc(p *void, n usize) *void;
diff --git a/src/parse.cff b/src/parse.cff
index 0843ccf..25a2617 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -1,5 +1,7 @@
+import "mem.hff";
+import "util.hff";
import "vec.hff";
-import "all.hff";
+import "cffc.hff";
///////////
// Lexer //
@@ -164,6 +166,15 @@ fn str2keyword(s *const u8) int {
return -1;
}
+fn xdigit2num(c u8) int {
+ switch {
+ case isdigit(c); return c - '0';
+ case c >= 'a' and c <= 'f'; return (c - 'a') + 10;
+ case c >= 'A' and c <= 'F'; return (c - 'A') + 10;
+ }
+ return -1;
+}
+
fn readnumber(s *const u8) Option<Tok> {
let c u8 #?,
acc = 0u64,
@@ -198,8 +209,7 @@ fn readnumber(s *const u8) Option<Tok> {
accf = accf + ((c - '0') * fmul);
fmul *= 0.1;
} else {
- c = tolower(c);
- acc = (acc * base) + (c <= '9' ? c - '0' : (c - 'a') + 10);
+ acc = (acc * base) + xdigit2num(c);
}
}
@@ -323,6 +333,13 @@ fn lex(P *Parser) Tok {
case 'r'; str->push('\r'); case 't'; str->push('\t');
case 'v'; str->push('\v'); case 'f'; str->push('\f');
case '0'; str->push('\0');
+ case 'x';
+ let x0 = xdigit2num(chr(P)),
+ x1 = xdigit2num(chr(P));
+ if x0 < 0 or x1 < 0 {
+ fatal(P, P.tokloc, "not a hex byte escape sequence");
+ }
+ str->push((x0 << 4) | x1);
case else
fatal(P, P.tokloc, "unknown escape sequence '\\%c'", c);
}
diff --git a/src/set.hff b/src/set.hff
index 6ab44ea..82c213f 100644
--- a/src/set.hff
+++ b/src/set.hff
@@ -1,5 +1,4 @@
import "vec.hff";
-import "all.hff";
#{
Traits:hash(K) u32
@@ -12,6 +11,12 @@ struct Set<T, Traits> {
N int,
count int,
+
+ fn _nexthash(h *u32) u32 {
+ // return *h = (*h * 1664525) + 1013904223u; // double hashing
+ return ++*h; // linear probing
+ }
+
fn intern(self *Set, x T) *const T {
if self.set == #null {
self.set = xcalloc(self.N = 16, sizeof int);
@@ -21,20 +26,22 @@ struct Set<T, Traits> {
free(self.set);
self.set = xcalloc(self.N *= 2, sizeof int);
vec_each(p, i, self.buf,
- let j = Traits:hash(p) & (self.N - 1);
+ let h = Traits:hash(p);
+ let j = h & (self.N - 1);
for ;; {
if self.set[j] == 0 {
self.set[j] = i + 1;
break;
}
- j = (j + 1) & (self.N - 1);
+ j = _nexthash(&h) & (self.N - 1);
}
)
}
- let i0 u32 = Traits:hash(x) & (self.N - 1);
- let i int = i0;
- do {
+ let h u32 = Traits:hash(x);
+ let i = h & (self.N - 1) & (self.N - 1);
+ let n = 0;
+ for ;; {
if self.set[i] == 0 {
++self.count;
self.buf->push(Traits:dup(x));
@@ -46,23 +53,22 @@ struct Set<T, Traits> {
return x2;
}
}
- i = (i + 1) & (self.N - 1);
- } while i != i0;
- assert(#f, "unreachable");
+ ++n;
+ i = _nexthash(&h) & (self.N - 1);
+ }
}
fn contains(self *Set, x T) bool {
- let i0 u32 = Traits:hash(x) & (self.N - 1);
- let i int = i0;
- do {
+ let h u32 = Traits:hash(x);
+ let i = h & (self.N - 1);
+ for ;; {
if self.set[i] == 0 {
return #f;
} else if Traits:eq(self.buf.dat[self.set[i] - 1], x) {
return #t;
}
- i = (i + 1) & (self.N - 1);
- } while i != i0;
- assert(#f, "unreachable");
+ i = _nexthash(&h) & (self.N - 1);
+ }
}
fn put(self *Set, x T) void {
diff --git a/src/targ.cff b/src/targ.cff
index 6490dff..59078a0 100644
--- a/src/targ.cff
+++ b/src/targ.cff
@@ -1,4 +1,5 @@
-import "all.hff";
+import "cffc.hff";
+import "common.hff";
static const targs []const Targ = {
{
diff --git a/src/targ.hff b/src/targ.hff
new file mode 100644
index 0000000..9df8ee5
--- /dev/null
+++ b/src/targ.hff
@@ -0,0 +1,12 @@
+struct Targ {
+ name *const u8,
+ ptrsize u8,
+ intsize u8,
+ longsize u8, longalign u8,
+ llongsize u8, llongalign u8,
+ sizesize u8,
+ f64align u8,
+ valistsize u8, valistalign u8,
+ charsigned bool,
+ shortenum bool,
+}
diff --git a/src/type.cff b/src/type.cff
index a6987b7..a3c7021 100644
--- a/src/type.cff
+++ b/src/type.cff
@@ -1,4 +1,5 @@
-import "all.hff";
+import "cffc.hff";
+import "util.hff";
fn hashtype(ty *const Type) u32 {
let h = FNV1A_INI;
diff --git a/src/type.hff b/src/type.hff
new file mode 100644
index 0000000..ce04063
--- /dev/null
+++ b/src/type.hff
@@ -0,0 +1,15 @@
+struct Type {
+ size usize,
+ align usize,
+ konst bool,
+ id uint,
+ u enum union {
+ Void,
+ Bool,
+ Int struct { sgn bool },
+ Flo,
+ Ptr *Type,
+ Arr struct { child *Type, length i64 },
+ Slice *Type,
+ }
+}
diff --git a/src/util.cff b/src/util.cff
index 18305b2..1b81ab4 100644
--- a/src/util.cff
+++ b/src/util.cff
@@ -1,5 +1,8 @@
+import "util.hff";
+import "cffc.hff";
import "set.hff";
-import "all.hff";
+import "mem.hff";
+import "common.hff";
extern fn xmalloc(n usize) *void {
let p = malloc(n);
diff --git a/src/util.hff b/src/util.hff
new file mode 100644
index 0000000..5eb9c88
--- /dev/null
+++ b/src/util.hff
@@ -0,0 +1,12 @@
+// util.cff
+extern fn xmalloc(n usize) *void;
+extern fn xcalloc(n usize, m usize) *void;
+extern fn xrealloc(p *void, n usize) *void;
+extern fn xstrdup(str *const u8) *u8;
+def FNV1A_INI u32 = 0x811c9dc5;
+extern fn fnv1a(h u32, [#]const u8) u32;
+extern fn fnv1a_s(h u32, *const u8) u32;
+extern fn fnv1a_i(h u32, i64) u32;
+extern fn addfilepath(*const u8) int;
+// extern fn fatal(*Parser, Loc, fmt *const u8, ...) void;
+extern fn internstr(*const u8) *const u8;
diff --git a/src/vec.hff b/src/vec.hff
index 35a9331..7f012aa 100644
--- a/src/vec.hff
+++ b/src/vec.hff
@@ -1,6 +1,7 @@
-import "all.hff";
+import "common.hff";
+import "mem.hff";
+import "util.hff";
-extern fn malloc(n usize) *void;
struct Vec<T> {
dat *T,
len uint,
@@ -10,10 +11,10 @@ struct Vec<T> {
if vec.len >= vec.cap {
vec.cap = (vec.len + 1) > 8 ? (vec.len + 1) * 2 : 8;
if vec.dat == #null {
- vec.dat = malloc(vec.cap * sizeof T);
+ vec.dat = xmalloc(vec.cap * sizeof T);
assert(vec.dat != #null, "malloc");
} else {
- vec.dat = realloc(vec.dat, vec.cap * sizeof T);
+ vec.dat = xrealloc(vec.dat, vec.cap * sizeof T);
assert(vec.dat != #null, "realloc");
}
}