summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-10-18 18:52:22 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2019-10-18 18:52:22 -0400
commit867b25643fc182d0db6045ecc5ca70b6b127b529 (patch)
tree445df3c4650c52c0a0b6e43dcbf12bcf7b6ea0c0
parent9a1054929db42852de237c8d0a7af8c1b5ac123e (diff)
started slices
-rw-r--r--cgen.c14
-rw-r--r--eval.c40
-rw-r--r--main.c5
-rw-r--r--out.c11
-rw-r--r--parse.c39
-rw-r--r--test.toc3
-rw-r--r--types.c57
-rw-r--r--types.h14
8 files changed, 133 insertions, 50 deletions
diff --git a/cgen.c b/cgen.c
index 4e6bcfc..3c0c501 100644
--- a/cgen.c
+++ b/cgen.c
@@ -91,6 +91,7 @@ static bool cgen_uses_ptr(Type *t) {
case TYPE_BUILTIN:
case TYPE_PTR:
case TYPE_FN:
+ case TYPE_SLICE:
case TYPE_VOID:
case TYPE_UNKNOWN:
return false;
@@ -141,7 +142,7 @@ static bool cgen_type_pre(CGenerator *g, Type *t, Location where) {
case BUILTIN_F64: cgen_write(g, "f64"); break;
} break;
case TYPE_PTR:
- if (!cgen_type_pre(g, t->ptr.of, where))
+ if (!cgen_type_pre(g, t->ptr, where))
return false;
cgen_write(g, "(*");
break;
@@ -159,6 +160,9 @@ static bool cgen_type_pre(CGenerator *g, Type *t, Location where) {
}
cgen_write(g, " (*");
break;
+ case TYPE_SLICE:
+ cgen_write(g, "slice_");
+ break;
case TYPE_VOID: cgen_write(g, "void"); break;
case TYPE_UNKNOWN:
err_print(t->where, "Can't determine type.");
@@ -175,7 +179,7 @@ static bool cgen_type_post(CGenerator *g, Type *t, Location where) {
switch (t->kind) {
case TYPE_PTR:
cgen_write(g, ")");
- if (!cgen_type_post(g, t->ptr.of, where))
+ if (!cgen_type_post(g, t->ptr, where))
return false;
break;
case TYPE_ARR:
@@ -221,6 +225,7 @@ static bool cgen_type_post(CGenerator *g, Type *t, Location where) {
case TYPE_VOID:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
+ case TYPE_SLICE:
break;
}
return true;
@@ -312,6 +317,7 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E
case TYPE_BUILTIN:
case TYPE_FN:
case TYPE_PTR:
+ case TYPE_SLICE:
case TYPE_UNKNOWN:
if (set_expr) {
if (!cgen_expr(g, set_expr)) return false;
@@ -771,6 +777,9 @@ static void cgen_zero_value(CGenerator *g, Type *t) {
case TYPE_FN:
cgen_write(g, "NULL");
break;
+ case TYPE_SLICE:
+ cgen_write(g, "{NULL, 0}");
+ break;
case TYPE_ARR:
cgen_write(g, "{");
cgen_zero_value(g, t->arr.of);
@@ -941,6 +950,7 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) {
"typedef float f32;\n"
"typedef double f64;\n"
"typedef unsigned char bool;\n"
+ "typedef struct { void *data; u64 n; } slice_;\n"
"#define false ((bool)0)\n"
"#define true ((bool)1)\n\n\n");
cgen_block_enter(g, NULL);
diff --git a/eval.c b/eval.c
index b9d948f..ba7712b 100644
--- a/eval.c
+++ b/eval.c
@@ -41,13 +41,15 @@ static size_t compiler_sizeof(Type *t) {
case TYPE_BUILTIN:
return compiler_sizeof_builtin(t->builtin);
case TYPE_FN:
- return sizeof(FnExpr *);
+ return sizeof t->fn;
case TYPE_PTR:
- return sizeof(void *);
+ return sizeof t->ptr;
case TYPE_ARR:
- return t->arr.n * compiler_sizeof(t->arr.of);
+ return sizeof t->arr;
case TYPE_TUPLE:
- return arr_len(t->tuple) * sizeof(Value);
+ return sizeof t->tuple;
+ case TYPE_SLICE:
+ return sizeof t->slice;
case TYPE_VOID:
case TYPE_UNKNOWN:
return 0;
@@ -82,6 +84,7 @@ static bool val_truthiness(Value *v, Type *t) {
case TYPE_PTR: return v->ptr != NULL;
case TYPE_FN: return v->fn != NULL;
case TYPE_ARR: return t->arr.n > 0;
+ case TYPE_SLICE: return v->slice.n > 0;
case TYPE_TUPLE: break;
}
assert(0);
@@ -239,6 +242,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
default: assert(0); break;
}
break;
+ case TYPE_SLICE:
case TYPE_VOID:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
@@ -257,6 +261,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_FN:
vout->fn = vin->fn;
break;
+ case TYPE_SLICE:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
case TYPE_VOID:
@@ -287,6 +292,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_FN:
vout->fn = vin->ptr;
break;
+ case TYPE_SLICE:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
case TYPE_VOID:
@@ -303,6 +309,26 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_ARR:
vout->arr = vin->arr;
break;
+ case TYPE_SLICE:
+ case TYPE_FN:
+ case TYPE_UNKNOWN:
+ case TYPE_TUPLE:
+ case TYPE_VOID:
+ case TYPE_BUILTIN:
+ assert(0); break;
+ }
+ break;
+ case TYPE_SLICE:
+ switch (to->kind) {
+ case TYPE_PTR:
+ vout->ptr = vin->slice.data;
+ break;
+ case TYPE_ARR:
+ vout->arr = vin->slice.data;
+ break;
+ case TYPE_SLICE:
+ vout->slice = vin->slice;
+ break;
case TYPE_FN:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
@@ -337,6 +363,9 @@ static void eval_deref(Value *v, void *ptr, Type *type) {
case BUILTIN_BOOL: v->boolv = *(bool *)ptr; break;
}
break;
+ case TYPE_SLICE:
+ v->slice = *(Slice *)ptr;
+ break;
case TYPE_VOID:
case TYPE_UNKNOWN:
assert(0);
@@ -366,6 +395,9 @@ static void eval_deref_set(void *set, Value *to, Type *type) {
case BUILTIN_BOOL: *(bool *)set = to->boolv; break;
}
break;
+ case TYPE_SLICE:
+ *(Slice *)set = to->slice;
+ break;
case TYPE_VOID:
case TYPE_UNKNOWN:
assert(0);
diff --git a/main.c b/main.c
index dfef286..92a207c 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,8 @@
/*
TODO:
-slices
-new run-time type resolution
+fix casting for slice => ptr/arr
+parameters can be passed as pointers
+new returns a *slice*
unicode variable names
make sure initializers for global variables are compile-time constants
structs
diff --git a/out.c b/out.c
index 4d1f4e1..de9c865 100644
--- a/out.c
+++ b/out.c
@@ -11,6 +11,7 @@ typedef uint64_t u64;
typedef float f32;
typedef double f64;
typedef unsigned char bool;
+typedef struct { void *data; u64 n; } slice_;
#define false ((bool)0)
#define true ((bool)1)
@@ -49,14 +50,8 @@ void main__(void) {
a2_ = y;
}(puti(a2_));
};
- i64( asdf[78636112]); {
- i64( expr__[78636112]); {
- size_t i;i64(*arr__in) = expr__; i64(*arr__out) = ((i64([78636112]))calloc(1, sizeof(i64([100])));
- for (i = 0; i < 78636112; i++) arr__out[i] = arr__in[i];
- }{
- size_t i;i64(*arr__in) = asdf; i64(*arr__out) = expr__;
- for (i = 0; i < 78636112; i++) arr__out[i] = arr__in[i];
- }}
+ slice_ foo = {NULL, 0};
+ slice_ bar = {NULL, 0};
}}
diff --git a/parse.c b/parse.c
index 21c1e12..58d53c2 100644
--- a/parse.c
+++ b/parse.c
@@ -180,6 +180,12 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) {
written += type_to_str_(t->arr.of, buffer + written, bufsize - written);
return written;
} break;
+ case TYPE_SLICE: {
+ size_t written = str_copy(buffer, bufsize, "[");
+ written += str_copy(buffer + written, bufsize - written, "]");
+ written += type_to_str_(t->slice, buffer + written, bufsize - written);
+ return written;
+ } break;
case TYPE_TUPLE: {
size_t written = str_copy(buffer, bufsize, "(");
arr_foreach(t->tuple, Type, child) {
@@ -192,7 +198,7 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) {
}
case TYPE_PTR: {
size_t written = str_copy(buffer, bufsize, "&");
- written += type_to_str_(t->ptr.of, buffer + written, bufsize - written);
+ written += type_to_str_(t->ptr, buffer + written, bufsize - written);
return written;
}
}
@@ -371,10 +377,22 @@ static bool parse_type(Parser *p, Type *type) {
break;
}
case KW_LSQUARE: {
- /* array type */
- Token *start = t->token;
+ /* array/slice */
+ type->where = t->token->where;
type->kind = TYPE_ARR;
t->token++; /* move past [ */
+ if (token_is_kw(t->token, KW_RSQUARE)) {
+ /* slice */
+ type->kind = TYPE_SLICE;
+ type->slice = parser_malloc(p, sizeof *type->slice);
+ t->token++; /* move past ] */
+ if (!parse_type(p, type->slice)) return false;
+ if (type->slice->kind == TYPE_TUPLE) {
+ err_print(type->where, "You cannot have a slice of tuples.");
+ return false;
+ }
+ break;
+ }
Token *end = expr_find_end(p, 0, NULL);
type->arr.n_expr = parser_new_expr(p);
if (!parse_expr(p, type->arr.n_expr, end)) return false;
@@ -382,13 +400,10 @@ static bool parse_type(Parser *p, Type *type) {
type->arr.of = parser_malloc(p, sizeof *type->arr.of);
if (!parse_type(p, type->arr.of)) return false;
if (type->arr.of->kind == TYPE_TUPLE) {
- err_print(type->arr.of->where, "You cannot have an array of tuples.");
+ err_print(type->where, "You cannot have an array of tuples.");
return false;
}
- type->flags = 0;
- type->where = start->where;
- break;
- }
+ } break;
case KW_LPAREN:
/* tuple! */
type->kind = TYPE_TUPLE;
@@ -417,11 +432,11 @@ static bool parse_type(Parser *p, Type *type) {
case KW_AMPERSAND:
/* pointer */
type->kind = TYPE_PTR;
- type->ptr.of = parser_malloc(p, sizeof *type->ptr.of);
+ type->ptr = parser_malloc(p, sizeof *type->ptr);
t->token++; /* move past & */
- if (!parse_type(p, type->ptr.of)) return false;
- if (type->ptr.of->kind == TYPE_TUPLE) {
- err_print(type->ptr.of->where, "You cannot have a pointer to a tuple.");
+ if (!parse_type(p, type->ptr)) return false;
+ if (type->ptr->kind == TYPE_TUPLE) {
+ err_print(type->ptr->where, "You cannot have a pointer to a tuple.");
return false;
}
break;
diff --git a/test.toc b/test.toc
index abb1623..6bb39f3 100644
--- a/test.toc
+++ b/test.toc
@@ -13,4 +13,7 @@ main @= fn() {
while y < 10 {
puti({y = y + 1; y});
}
+ foo : []int;
+ bar : []float;
+
}; \ No newline at end of file
diff --git a/types.c b/types.c
index 6ae52a9..cedc75d 100644
--- a/types.c
+++ b/types.c
@@ -62,8 +62,10 @@ static bool type_eq(Type *a, Type *b) {
case TYPE_ARR:
if (a->arr.n != b->arr.n) return false;
return type_eq(a->arr.of, b->arr.of);
+ case TYPE_SLICE:
+ return type_eq(a->slice, b->slice);
case TYPE_PTR:
- return type_eq(a->ptr.of, b->ptr.of);
+ return type_eq(a->ptr, b->ptr);
}
assert(0);
return false;
@@ -340,7 +342,11 @@ static bool type_resolve(Evaluator *ev, Type *t) {
}
break;
case TYPE_PTR:
- if (!type_resolve(ev, t->ptr.of))
+ if (!type_resolve(ev, t->ptr))
+ return false;
+ break;
+ case TYPE_SLICE:
+ if (!type_resolve(ev, t->slice))
return false;
break;
case TYPE_UNKNOWN:
@@ -360,7 +366,10 @@ static bool types_type(Typer *tr, Type *t) {
if (!types_type(tr, t->arr.of)) return false;
break;
case TYPE_PTR:
- if (!types_type(tr, t->ptr.of)) return false;
+ if (!types_type(tr, t->ptr)) return false;
+ break;
+ case TYPE_SLICE:
+ if (!types_type(tr, t->slice)) return false;
break;
case TYPE_TUPLE: {
arr_foreach(t->tuple, Type, x)
@@ -396,6 +405,8 @@ static bool type_can_be_truthy(Type *t) {
return false;
case TYPE_PTR:
return true;
+ case TYPE_SLICE:
+ return true;
}
assert(0);
return false;
@@ -424,13 +435,17 @@ static Status type_cast_status(Type *from, Type *to) {
case BUILTIN_I64:
case BUILTIN_U64:
switch (to->kind) {
- case TYPE_UNKNOWN: return STATUS_NONE;
- case TYPE_VOID: return STATUS_ERR;
- case TYPE_BUILTIN: return STATUS_NONE;
- case TYPE_ARR: return STATUS_ERR;
- case TYPE_PTR: return STATUS_WARN;
- case TYPE_FN: return STATUS_ERR;
- case TYPE_TUPLE: return STATUS_ERR;
+ case TYPE_BUILTIN:
+ case TYPE_UNKNOWN:
+ return STATUS_NONE;
+ case TYPE_PTR:
+ return STATUS_WARN;
+ case TYPE_FN:
+ case TYPE_TUPLE:
+ case TYPE_SLICE:
+ case TYPE_ARR:
+ case TYPE_VOID:
+ return STATUS_ERR;
}
break;
case BUILTIN_F32:
@@ -456,17 +471,23 @@ static Status type_cast_status(Type *from, Type *to) {
return STATUS_WARN;
if (to->kind == TYPE_PTR)
return STATUS_NONE;
- if (to->kind == TYPE_ARR && type_eq(to->arr.of, from->ptr.of))
+ if (to->kind == TYPE_ARR && type_eq(from->ptr, to->arr.of))
return STATUS_NONE;
if (to->kind == TYPE_FN)
return STATUS_WARN;
return STATUS_ERR;
case TYPE_ARR:
- if (to->kind == TYPE_PTR && type_eq(to->ptr.of, from->arr.of))
+ if (to->kind == TYPE_PTR && type_eq(from->arr.of, to->ptr))
return STATUS_NONE;
- if (to->kind == TYPE_ARR && !type_eq(to, from))
+ if (to->kind == TYPE_ARR && !type_eq(from, to))
return STATUS_WARN;
return STATUS_ERR;
+ case TYPE_SLICE:
+ if (to->kind == TYPE_PTR && type_eq(from->slice, to->ptr))
+ return STATUS_NONE;
+ if (to->kind == TYPE_ARR && type_eq(from->slice, to->arr.of))
+ return STATUS_NONE;
+ return STATUS_ERR;
}
assert(0);
return STATUS_ERR;
@@ -606,8 +627,8 @@ static bool types_expr(Typer *tr, Expression *e) {
if (e->new.type.kind == TYPE_ARR) {
*t = e->new.type;
} else {
- t->ptr.of = typer_malloc(tr, sizeof *t->ptr.of);
- t->ptr.of = &e->new.type;
+ t->ptr = typer_malloc(tr, sizeof *t->ptr);
+ t->ptr = &e->new.type;
}
break;
case EXPR_IF: {
@@ -865,8 +886,8 @@ static bool types_expr(Typer *tr, Expression *e) {
return false;
}
t->kind = TYPE_PTR;
- t->ptr.of = typer_malloc(tr, sizeof *t->ptr.of); /* OPTIM */
- *t->ptr.of = *of_type;
+ t->ptr = typer_malloc(tr, sizeof *t->ptr);
+ *t->ptr = *of_type;
break;
case UNARY_DEREF:
if (of_type->kind != TYPE_PTR) {
@@ -876,7 +897,7 @@ static bool types_expr(Typer *tr, Expression *e) {
return false;
}
- *t = *of_type->ptr.of;
+ *t = *of_type->ptr;
break;
case UNARY_DEL:
if (of_type->kind != TYPE_PTR) {
diff --git a/types.h b/types.h
index ea7fc23..182e80d 100644
--- a/types.h
+++ b/types.h
@@ -58,6 +58,11 @@ typedef struct {
ArrBlock *blocks;
} BlockArr;
+typedef struct {
+ U64 n;
+ void *data;
+} Slice;
+
typedef union Value {
U8 u8;
U16 u16;
@@ -75,6 +80,7 @@ typedef union Value {
void *arr;
void *ptr;
union Value *tuple;
+ Slice slice;
} Value;
#define IDECL_FLAG_HAS_VAL 0x01
@@ -229,7 +235,8 @@ typedef enum {
TYPE_FN,
TYPE_TUPLE,
TYPE_ARR,
- TYPE_PTR
+ TYPE_PTR,
+ TYPE_SLICE
} TypeKind;
typedef enum {
@@ -267,9 +274,8 @@ typedef struct Type {
struct Expression *n_expr;
};
} arr;
- struct {
- struct Type *of;
- } ptr;
+ struct Type *ptr;
+ struct Type *slice;
};
} Type;