summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c61
-rw-r--r--decls_cgen.c10
-rw-r--r--eval.c3
-rw-r--r--main.c1
-rw-r--r--std/mem.toc10
-rw-r--r--test.toc19
-rw-r--r--tests/arr.toc3
-rw-r--r--tests/arr2.toc3
-rw-r--r--tests/arr3.toc3
-rw-r--r--tests/bf.toc26
-rw-r--r--tests/mem.toc23
-rw-r--r--tests/new.toc27
-rw-r--r--tests/new_expected2
-rwxr-xr-xtests/test.sh1
14 files changed, 128 insertions, 64 deletions
diff --git a/cgen.c b/cgen.c
index 70db8ff..4be5032 100644
--- a/cgen.c
+++ b/cgen.c
@@ -138,34 +138,39 @@ static void cgen_defs_decl(CGenerator *g, Declaration *d);
}
-#define cgen_recurse_subtypes(f, g, type) \
- switch (type->kind) { \
- case TYPE_STRUCT: \
- /* don't descend into fields */ \
- break; \
- case TYPE_FN: \
- arr_foreach(type->fn.types, Type, sub) { \
- f(g, sub); \
- } \
- break; \
- case TYPE_TUPLE: \
- arr_foreach(type->tuple, Type, sub) \
- f(g, sub); \
- break; \
- case TYPE_ARR: \
- f(g, type->arr.of); \
- break; \
- case TYPE_SLICE: \
- f(g, type->slice); \
- break; \
- case TYPE_PTR: \
- f(g, type->ptr); \
- break; \
- case TYPE_VOID: \
- case TYPE_BUILTIN: \
- case TYPE_UNKNOWN: \
- break; \
- case TYPE_EXPR: assert(0); \
+#define cgen_recurse_subtypes(f, g, type) \
+ switch (type->kind) { \
+ case TYPE_STRUCT: \
+ /* don't descend into fields */ \
+ break; \
+ case TYPE_FN: \
+ if (type->kind == TYPE_FN && (type->fn.constness || fn_type_has_varargs(&type->fn))) { \
+ /* we don't want to do this, because it's a template-y thing */ \
+ } \
+ else { \
+ arr_foreach(type->fn.types, Type, sub) { \
+ f(g, sub); \
+ } \
+ } \
+ break; \
+ case TYPE_TUPLE: \
+ arr_foreach(type->tuple, Type, sub) \
+ f(g, sub); \
+ break; \
+ case TYPE_ARR: \
+ f(g, type->arr.of); \
+ break; \
+ case TYPE_SLICE: \
+ f(g, type->slice); \
+ break; \
+ case TYPE_PTR: \
+ f(g, type->ptr); \
+ break; \
+ case TYPE_VOID: \
+ case TYPE_BUILTIN: \
+ case TYPE_UNKNOWN: \
+ break; \
+ case TYPE_EXPR: assert(0); \
}
diff --git a/decls_cgen.c b/decls_cgen.c
index 045367e..371d91f 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -12,15 +12,11 @@ static void cgen_decls_decl(CGenerator *g, Declaration *d);
/* i is the name for this type, NULL if not available */
static void cgen_sdecls_type(CGenerator *g, Type *type) {
- if (!(type->flags & TYPE_IS_RESOLVED)) /* non-instance constant fn parameter type */
- return;
if (type->kind == TYPE_STRUCT) {
StructDef *sdef = type->struc;
/* we'll actually define the struct later; here we can just declare it */
- if (sdef->flags & STRUCT_DEF_CGEN_DECLARED) {
- /* we've already done this */
- } else {
+ if ((sdef->flags & STRUCT_DEF_RESOLVED) && !(sdef->flags & STRUCT_DEF_CGEN_DECLARED)) {
cgen_write(g, "struct ");
if (!sdef->name) {
sdef->c.id = ++g->ident_counter;
@@ -173,11 +169,9 @@ static void cgen_sdecls_file(CGenerator *g, ParsedFile *f) {
}
static void cgen_decls_type(CGenerator *g, Type *type) {
- if (!(type->flags & TYPE_IS_RESOLVED)) /* non-instance constant fn parameter type */
- return;
if (type->kind == TYPE_STRUCT) {
StructDef *sdef = type->struc;
- if (!(sdef->flags & STRUCT_DEF_CGEN_DEFINED)) {
+ if ((sdef->flags & STRUCT_DEF_RESOLVED) && !(sdef->flags & STRUCT_DEF_CGEN_DEFINED)) {
/* generate struct definition */
cgen_write(g, "struct ");
cgen_struct_name(g, sdef);
diff --git a/eval.c b/eval.c
index a0de141..bafa6fc 100644
--- a/eval.c
+++ b/eval.c
@@ -748,8 +748,7 @@ static Status eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr, void
if (!eval_address_of(ev, dot_expr->binary.lhs, &ptr))
return false;
/* access struct data */
- Identifier ident = dot_expr->binary.rhs->ident;
- assert(ident_eq_str(ident, "data"));
+ assert(ident_eq_str(dot_expr->binary.rhs->ident, "data"));
*p = &((Slice *)ptr)->data;
} else {
void *ptr;
diff --git a/main.c b/main.c
index 4fcc511..1c7c9e9 100644
--- a/main.c
+++ b/main.c
@@ -8,7 +8,6 @@
/*
TODO:
-- make new(s) and del functions!
defer
use
&&, ||
diff --git a/std/mem.toc b/std/mem.toc
index 06890b5..5e8c5fa 100644
--- a/std/mem.toc
+++ b/std/mem.toc
@@ -1,14 +1,14 @@
-// TODO: check for failed malloc
-malloc ::= #foreign("malloc", "libc.so.6") fn(#C size_t) #C &"void";
+// TODO: check for failed calloc
+calloc ::= #foreign("calloc", "libc.so.6") fn(#C size_t, #C size_t) #C &"void";
free ::= #foreign("free", "libc.so.6") fn(#C &"void");
new ::= fn(t :: Type) &t {
- malloc((sizeof t) as u64)
+ calloc(1, (sizeof t) as u64)
}
-news ::= fn(t :: Type, n :: int) []t {
+news ::= fn(t :: Type, n : int) []t {
s: []t;
- s.data = malloc((n * sizeof t) as u64);
+ s.data = calloc(n as u64, (sizeof t) as u64);
s.len = n;
s
}
diff --git a/test.toc b/test.toc
index 8d884fd..790a115 100644
--- a/test.toc
+++ b/test.toc
@@ -1,18 +1,27 @@
#include "std/mem.toc", mem;
#include "std/io.toc", io;
-main ::= fn() {
+
+calculation ::= fn() int {
+ total := 0;
i := mem.new(int);
*i = 3;
- io.puti(*i);
ns := mem.news(int, 10);
for n, i := &ns {
- *n = i;
+ if i % 2 == 0 {
+ *n = i;
+ }
}
for n := ns {
- io.puti(n);
+ total += n;
}
+ total += *i;
mem.del(i);
mem.dels(ns);
+ total
}
-main();
+main ::= fn() {
+ io.puti(calculation());
+ x ::= calculation();
+ io.puti(x);
+}
diff --git a/tests/arr.toc b/tests/arr.toc
index eee514a..5fb8328 100644
--- a/tests/arr.toc
+++ b/tests/arr.toc
@@ -1,3 +1,4 @@
+#include "mem.toc";
puti ::= fn(x: int) {
//tcc's giving me "incompatible types for redefinition of 'printf'" for some reason (even though the declarations have the exact same type)
#C("#ifndef __TINYC__
@@ -25,7 +26,7 @@ Arr ::= fn (t :: Type) Type {
arr_add ::= fn(t :: Type, a : &Arr(t), x : t) {
if a.len >= a.cap {
a.cap = a.cap * 2 + 2;
- new_data := new(t, a.cap);
+ new_data := news(t, a.cap);
for i := 0..a.len-1 {
new_data[i] = a.data[i];
}
diff --git a/tests/arr2.toc b/tests/arr2.toc
index e016cf2..9d6aa34 100644
--- a/tests/arr2.toc
+++ b/tests/arr2.toc
@@ -1,3 +1,4 @@
+#include "mem.toc";
puti ::= fn(x: int) {
#C("#ifndef __TINYC__
extern int printf(const char *fmt, ...);
@@ -26,7 +27,7 @@ Arr ::= fn (t :: Type) Type {
arr_add ::= fn(t ::=, a : &Arr(t), x : t) {
if a.len >= a.cap {
a.cap = a.cap * 2 + 2;
- new_data := new(t, a.cap);
+ new_data := news(t, a.cap);
for i := 0..a.len-1 {
new_data[i] = a.data[i];
}
diff --git a/tests/arr3.toc b/tests/arr3.toc
index a6d1b14..cfbbc5a 100644
--- a/tests/arr3.toc
+++ b/tests/arr3.toc
@@ -1,4 +1,5 @@
#include "io.toc";
+#include "mem.toc";
Arr ::= struct (t :: Type) {
data: []t;
@@ -9,7 +10,7 @@ Arr ::= struct (t :: Type) {
arr_add ::= fn(t ::=, a : &Arr(t), x : t) {
if a.len >= a.cap {
a.cap = a.cap * 2 + 2;
- new_data := new(t, a.cap);
+ new_data := news(t, a.cap);
for i := 0..a.len-1 {
new_data[i] = a.data[i];
}
diff --git a/tests/bf.toc b/tests/bf.toc
index e1f8781..d300bc9 100644
--- a/tests/bf.toc
+++ b/tests/bf.toc
@@ -1,7 +1,9 @@
+#include "mem.toc";
+
readfile ::= fn(filename: []char) []char {
#C("extern void *fopen(char *name, char const *mode); extern char *fgets(char *buf, size_t sz, void *f);");
fp : &u8 = #C("fopen(&(((char *)filename.data)[0]), \"r\")");
- contents : []char;
+ contents := news(char, 1);
contents_sz : int;
contents_len : int;
buffer : [1024]char;
@@ -13,13 +15,13 @@ readfile ::= fn(filename: []char) []char {
if contents_sz < contents_len + buffer_len {
old_contents := contents;
contents_sz = 2*contents_sz + 1024;
- contents = new(char, contents_sz);
+ contents = news(char, contents_sz);
i := 0;
while i < contents_len {
contents[i] = old_contents[i];
i = i + 1;
}
- del(old_contents);
+ dels(old_contents);
}
i := 0;
while i < buffer_len {
@@ -44,7 +46,7 @@ runfile ::= fn(filename: []char) {
#C("extern int putchar(int c);");
code := readfile(filename);
tape_sz := 3;
- tape := new(int, tape_sz);
+ tape := news(int, tape_sz);
ptr := tape_sz / 2;
i := 0;
while code[i] {
@@ -58,28 +60,28 @@ runfile ::= fn(filename: []char) {
ptr = ptr + 1;
if ptr >= tape_sz {
// extend to the right
- newtape := new(int, 2*tape_sz);
+ newtape := news(int, 2*tape_sz);
j := 0;
while j < tape_sz {
newtape[j] = tape[j];
j = j + 1;
}
tape_sz = tape_sz * 2;
- del(tape);
+ dels(tape);
tape = newtape;
}
} elif code[i] == '<' {
ptr = ptr - 1;
if ptr < 0 {
// extend to the left
- newtape := new(int, 2*tape_sz);
+ newtape := news(int, 2*tape_sz);
j := 0;
while j < tape_sz {
newtape[j+tape_sz] = tape[j];
j = j + 1;
}
tape_sz = tape_sz * 2;
- del(tape);
+ dels(tape);
tape = newtape;
ptr = ptr + tape_sz;
}
@@ -110,11 +112,11 @@ runfile ::= fn(filename: []char) {
}
i = i + 1;
}
- del(tape);
- del(code);
+ dels(tape);
+ dels(code);
};
main ::= fn() {
- runfile("bf_hw0");
- runfile("bf_hw1");
+ runfile("bf_hw0\0");
+ runfile("bf_hw1\0");
};
diff --git a/tests/mem.toc b/tests/mem.toc
new file mode 100644
index 0000000..5e8c5fa
--- /dev/null
+++ b/tests/mem.toc
@@ -0,0 +1,23 @@
+// TODO: check for failed calloc
+calloc ::= #foreign("calloc", "libc.so.6") fn(#C size_t, #C size_t) #C &"void";
+free ::= #foreign("free", "libc.so.6") fn(#C &"void");
+
+new ::= fn(t :: Type) &t {
+ calloc(1, (sizeof t) as u64)
+}
+
+news ::= fn(t :: Type, n : int) []t {
+ s: []t;
+ s.data = calloc(n as u64, (sizeof t) as u64);
+ s.len = n;
+ s
+}
+
+// TODO(eventually): use type information to make this just one function
+del ::= fn(t::=, x: &t) {
+ free(x);
+}
+
+dels ::= fn(t::=, x: []t) {
+ free(x.data);
+} \ No newline at end of file
diff --git a/tests/new.toc b/tests/new.toc
new file mode 100644
index 0000000..bb6a5fa
--- /dev/null
+++ b/tests/new.toc
@@ -0,0 +1,27 @@
+#include "mem.toc", mem;
+#include "io.toc", io;
+
+calculation ::= fn() int {
+ total := 0;
+ i := mem.new(int);
+ *i = 3;
+ ns := mem.news(int, 10);
+ for n, i := &ns {
+ if i % 2 == 0 {
+ *n = i;
+ }
+ }
+ for n := ns {
+ total += n;
+ }
+ total += *i;
+ mem.del(i);
+ mem.dels(ns);
+ total
+}
+
+main ::= fn() {
+ io.puti(calculation());
+ x ::= calculation();
+ io.puti(x);
+}
diff --git a/tests/new_expected b/tests/new_expected
new file mode 100644
index 0000000..c1eee21
--- /dev/null
+++ b/tests/new_expected
@@ -0,0 +1,2 @@
+23
+23
diff --git a/tests/test.sh b/tests/test.sh
index 5e4535a..8adf412 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -3,6 +3,7 @@
tests='bf
control_flow
sizeof
+new
arr
arr2
arr3