summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-04-23 15:58:51 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-04-23 15:58:51 -0400
commit9db4ea5189f6f1a8b264c9948090c822f5e008b1 (patch)
treeba181369ebff8160bf8b3c8dba4236c02bc6e1e5
parentdf03769e7bad52137bfe685035e2e4ece2bcd044 (diff)
made EXPR_IDENT a string before typing
-rw-r--r--cgen.c2
-rw-r--r--copy.c2
-rw-r--r--eval.c3
-rw-r--r--identifiers.c5
-rw-r--r--infer.c2
-rw-r--r--main.c6
-rw-r--r--misc.c12
-rw-r--r--parse.c15
-rw-r--r--test.toc11
-rw-r--r--types.c52
-rw-r--r--types.h15
11 files changed, 77 insertions, 48 deletions
diff --git a/cgen.c b/cgen.c
index b2d64f2..f73debd 100644
--- a/cgen.c
+++ b/cgen.c
@@ -1349,7 +1349,7 @@ static void cgen_expr(CGenerator *g, Expression *e) {
cgen_expr(g, lhs);
bool is_ptr = lhs->type.kind == TYPE_PTR;
cgen_write(g, is_ptr ? "->" :".");
- cgen_ident_simple(g, e->binary.dot.field->name);
+ cgen_ident_simple(g, e->binary.field->name);
cgen_write(g, ")");
} else if (struct_type->kind == TYPE_SLICE) {
/* access slice data */
diff --git a/copy.c b/copy.c
index 2c746a1..7da09d4 100644
--- a/copy.c
+++ b/copy.c
@@ -246,9 +246,7 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) {
case EXPR_LITERAL_STR:
case EXPR_LITERAL_CHAR:
case EXPR_LITERAL_BOOL:
- break;
case EXPR_IDENT:
- copier_ident_translate(c, &out->ident);
break;
case EXPR_UNARY_OP:
out->unary.of = copy_expr_(c, in->unary.of);
diff --git a/eval.c b/eval.c
index 9a8fa98..f8ef498 100644
--- a/eval.c
+++ b/eval.c
@@ -734,13 +734,12 @@ static Status eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr, void
} else {
struc_data = struc.struc;
}
- *p = (char *)struc_data + dot_expr->binary.dot.field->offset;
+ *p = (char *)struc_data + dot_expr->binary.field->offset;
} else if (struct_type->kind == TYPE_SLICE) {
void *ptr;
if (!eval_address_of(ev, dot_expr->binary.lhs, &ptr))
return false;
/* access struct data */
- assert(ident_eq_str(dot_expr->binary.rhs->ident, "data"));
*p = &((Slice *)ptr)->data;
} else {
void *ptr;
diff --git a/identifiers.c b/identifiers.c
index 2daa112..0f5d59a 100644
--- a/identifiers.c
+++ b/identifiers.c
@@ -55,6 +55,11 @@ static inline bool ident_eq_str(Identifier i, const char *s) {
return ident_str_eq_str(i->str, s);
}
+static inline bool ident_eq_string(Identifier i, String s) {
+ if (i->len != s.len) return false;
+ if (memcmp(i->str, s.str, s.len) != 0) return false;
+ return true;
+}
static inline Identifier ident_insert_with_len(Identifiers *ids, char *s, size_t len) {
IdentSlot *slot = (IdentSlot *)str_hash_table_insert_(&ids->table, s, len);
diff --git a/infer.c b/infer.c
index e131583..8367dce 100644
--- a/infer.c
+++ b/infer.c
@@ -17,7 +17,7 @@ static bool infer_from_expr(Typer *tr, Expression *match, Value to, Type *to_typ
case EXPR_IDENT:
/* an identifier! maybe it's one of idents... */
arr_foreach(idents, Identifier, ident) {
- if (*ident == match->ident) {
+ if (ident_eq_string(*ident, match->ident_str)) {
long idx = ident - idents;
types[idx] = *to_type;
vals[idx] = to;
diff --git a/main.c b/main.c
index 1529b68..930d947 100644
--- a/main.c
+++ b/main.c
@@ -8,7 +8,6 @@
/*
@TODO:
-EXPR_IDENT should be a string before typing, also struct member accesses
do we need the possibility that IdentSlot.decl is NULL?
use
- use with struct members (e.g. SuperPoint ::= struct { use p: Point; })
@@ -22,12 +21,13 @@ is there a problem where we can get TYPE_UNKNOWN in cgen, triggering an assert(0
-also make sure you can't do x:#C("5");
local structs should not be named in C
make sure global slices work
-allow use ??? if an error has already occurred
+allow `use ???;` if an error has already occurred
if something gets included into a namespace, and its typing fails, the namespace should still be of type namespace, not ???
make sure you can do a[i] where a is &[5]int or &[]char or something
do we consistently handle x := &some_array_or_slice; x.len
-&void
simplify eval macros with val_to_u/i64
+#if should not create a block
+&void
&&, ||
start making a standard library... (printf; stringbuilder would be nice to have)
switch
diff --git a/misc.c b/misc.c
index c38996f..4e82ff8 100644
--- a/misc.c
+++ b/misc.c
@@ -48,6 +48,17 @@ size_t str_copy(char *dest, size_t destsz, const char *src) {
return destsz-1;
}
+static char *cstr(char const *str, size_t len) {
+ char *ret = malloc(len+1);
+ memcpy(ret, str, len);
+ ret[len] = 0;
+ return ret;
+}
+
+static bool str_eq_cstr(String s, char const *str) {
+ return strncmp(s.str, str, s.len) == 0;
+}
+
static inline U32 rand_u32(U32 seed) {
U64 seed64 = (U64)seed;
return (U32)((seed64 * 0x832f0fda4e1a8642 + 0x41d49cd5459a2ab4) >> 32);
@@ -65,3 +76,4 @@ static char const *indefinite_article(char const *s) {
return "an";
return "a";
}
+
diff --git a/parse.c b/parse.c
index 0de36f8..d7bae47 100644
--- a/parse.c
+++ b/parse.c
@@ -1241,7 +1241,8 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
} break;
case TOKEN_IDENT:
e->kind = EXPR_IDENT;
- e->ident = parser_ident_insert(p, t->token->ident);
+ e->ident_str.str = t->token->ident;
+ e->ident_str.len = ident_str_len(e->ident_str.str);
break;
case TOKEN_LITERAL_STR:
e->kind = EXPR_LITERAL_STR;
@@ -2667,13 +2668,21 @@ static void fprint_expr(FILE *out, Expression *e) {
fprint_char_literal(out, e->charl);
break;
case EXPR_IDENT:
- fprint_ident_debug(out, e->ident);
+ if (found_type) {
+ fprint_ident_debug(out, e->ident);
+ } else {
+ fwrite(e->ident_str.str, 1, e->ident_str.len, out);
+ }
break;
case EXPR_BINARY_OP: {
fprintf(out, "(");
fprint_expr(out, e->binary.lhs);
fprintf(out, ")%s(", binary_op_to_str(e->binary.op));
- fprint_expr(out, e->binary.rhs);
+ if (e->binary.op == BINARY_DOT && found_type && e->binary.lhs->type.kind == TYPE_STRUCT) {
+ fprint_ident(out, e->binary.field->name);
+ } else {
+ fprint_expr(out, e->binary.rhs);
+ }
fprintf(out, ")");
} break;
case EXPR_UNARY_OP:
diff --git a/test.toc b/test.toc
index 10043da..1f6a725 100644
--- a/test.toc
+++ b/test.toc
@@ -1,6 +1,5 @@
#include "std/io.toc";
/*
-
sum ::= fn(n::=, t::=, a: [n]t) t {
total : t = 0;
for x := a {
@@ -16,15 +15,13 @@ main ::= fn() {
*x = i;
}
puti(sum(numbers) as int);
-
}
*/
-
-ll ::= struct (t::Type) {
- head: t;
- next: &ll(t);
+Point ::= struct {
+ x, y : int;
}
main ::= fn() {
- x: ll(int);
+ p: Point;
+ p.x = 12;
}
diff --git a/types.c b/types.c
index b3c794e..22e4350 100644
--- a/types.c
+++ b/types.c
@@ -1476,14 +1476,14 @@ static void get_builtin_val_type(Allocator *a, BuiltinVal val, Type *t) {
/* gets a struct's constant or parameter, and puts it into e->val. */
-static Status get_struct_constant(StructDef *struc, Identifier member, Expression *e) {
+static Status get_struct_constant(StructDef *struc, String ident, Expression *e) {
if (struc->params && !(struc->params[0].flags & DECL_FOUND_VAL)) {
err_print(e->where, "To access constants from a parameterized struct, you must supply its arguments.");
return false;
}
- Identifier i = ident_translate(member, &struc->body.idents);
+ Identifier i = ident_get_with_len(&struc->body.idents, ident.str, ident.len);
if (!i) {
- char *member_s = ident_to_str(member);
+ char *member_s = cstr(ident.str, ident.len);
char *struc_s = struc->name ? ident_to_str(struc->name) : "anonymous struct";
err_print(e->where, "%s is not a member of structure %s.", member_s, struc_s);
info_print(struc->where, "struct was declared here.");
@@ -1505,9 +1505,10 @@ static Status get_struct_constant(StructDef *struc, Identifier member, Expressio
e->type = *decl_type_at_index(i->decl, ident_idx);
return true;
} else {
- char *member_s = ident_to_str(member);
+ char *member_s = cstr(ident.str, ident.len);
char *struc_s = struc->name ? ident_to_str(struc->name) : "anonymous struct";
err_print(e->where, "Cannot get value %s from struct %s. Are you missing parameters to this struct?", member_s, struc_s);
+ free(member_s);
return false;
}
}
@@ -1941,11 +1942,13 @@ static Status types_expr(Typer *tr, Expression *e) {
}
case EXPR_IDENT: {
Block *b = tr->block;
- Identifier i = e->ident;
+ char *i_str = e->ident_str.str;
+ size_t i_len = e->ident_str.len;
+ Identifier final_ident = NULL;
bool undeclared = true;
while (1) { /* for each block we are inside... */
/* @OPTIM: only hash once */
- Identifier translated = ident_translate(i, b ? &b->idents : tr->globals);
+ Identifier translated = ident_get_with_len(b ? &b->idents : tr->globals, i_str, i_len);
if (ident_is_declared(translated)) {
#if 0
printf("translated %s from\n", ident_to_str(i));
@@ -1953,7 +1956,7 @@ static Status types_expr(Typer *tr, Expression *e) {
printf(" to \n");
print_block_location(translated->idents->body);
#endif
- i = translated;
+ final_ident = translated;
undeclared = false;
}
Use **uses = b ? b->uses : tr->uses;
@@ -1971,7 +1974,7 @@ static Status types_expr(Typer *tr, Expression *e) {
Namespace *nms = val.nms;
Block *body = &nms->body;
/* look up identifier in namespace */
- translated_use = ident_translate(i, &body->idents);
+ translated_use = ident_get_with_len(&body->idents, i_str, i_len);
} else {
/* it's a struct */
was_a_struct = true;
@@ -1980,16 +1983,17 @@ static Status types_expr(Typer *tr, Expression *e) {
struct_type = struct_type->ptr;
assert(struct_type->kind == TYPE_STRUCT);
StructDef *struc = struct_type->struc;
- translated_use = ident_translate(i, &struc->body.idents);
+ translated_use = ident_get_with_len(&struc->body.idents, i_str, i_len);
}
if (ident_is_declared(translated_use)) {
if (undeclared) {
previous_use_which_uses_i = use;
undeclared = false;
- i = translated_use;
+ final_ident = translated_use;
} else {
- char *s = ident_to_str(i);
+ char *s = cstr(i_str, i_len);
err_print(e->where, "Conflicting declarations for identifier %s.", s);
+ free(s);
char *also = "";
if (previous_use_which_uses_i) {
/* i was use'd twice */
@@ -2010,7 +2014,8 @@ static Status types_expr(Typer *tr, Expression *e) {
e->binary.lhs = used;
e->binary.rhs = typer_calloc(tr, 1, sizeof *e->binary.rhs);
e->binary.rhs->kind = EXPR_IDENT;
- e->binary.rhs->ident = i;
+ e->binary.rhs->ident_str.str = i_str;
+ e->binary.rhs->ident_str.len = i_len;
/* re-type */
if (!types_expr(tr, e))
return false;
@@ -2025,7 +2030,7 @@ static Status types_expr(Typer *tr, Expression *e) {
break;
}
}
- e->ident = i;
+ e->ident = final_ident;
if (undeclared) {
char *s = ident_to_str(e->ident);
err_print(e->where, "Undeclared identifier \"%s\".", s);
@@ -3029,7 +3034,8 @@ static Status types_expr(Typer *tr, Expression *e) {
return false;
}
rhs->kind = EXPR_IDENT;
- rhs->ident = ident_insert_with_len(typer_get_idents(tr), val.slice.data, (size_t)val.slice.len);
+ rhs->ident_str.str = val.slice.data;
+ rhs->ident_str.len = (size_t)val.slice.len;
/* re-type with new expression */
e->flags = (ExprFlags)~(ExprFlags)EXPR_FOUND_TYPE;
return types_expr(tr, e);
@@ -3114,25 +3120,25 @@ static Status types_expr(Typer *tr, Expression *e) {
free(s);
return false;
}
- if (!get_struct_constant(struc->struc, rhs->ident, e))
+ if (!get_struct_constant(struc->struc, rhs->ident_str, e))
return false;
break;
} else if (struct_type->kind == TYPE_STRUCT) {
StructDef *struc = struct_type->struc;
assert(struc->flags & STRUCT_DEF_RESOLVED);
- Identifier struct_ident = ident_translate(rhs->ident, &struc->body.idents);
+ Identifier struct_ident = ident_get_with_len(&struc->body.idents, rhs->ident_str.str, rhs->ident_str.len);
if (ident_is_declared(struct_ident) && !(struct_ident->decl->flags & DECL_IS_CONST)) {
Field *field = struct_ident->decl->field;
field += ident_index_in_decl(struct_ident, struct_ident->decl);
- e->binary.dot.field = field;
+ e->binary.field = field;
*t = *field->type;
} else {
- if (!get_struct_constant(struct_type->struc, rhs->ident, e))
+ if (!get_struct_constant(struct_type->struc, rhs->ident_str, e))
return false;
}
break;
} else if (struct_type->kind == TYPE_SLICE || struct_type->kind == TYPE_ARR || type_is_builtin(struct_type, BUILTIN_VARARGS)) {
- if (ident_eq_str(rhs->ident, "data") && struct_type->kind == TYPE_SLICE) {
+ if (str_eq_cstr(rhs->ident_str, "data") && struct_type->kind == TYPE_SLICE) {
/* allow access of slice pointer */
t->kind = TYPE_PTR;
t->ptr = typer_calloc(tr, 1, sizeof *t->ptr);
@@ -3140,7 +3146,7 @@ static Status types_expr(Typer *tr, Expression *e) {
t->ptr->flags = TYPE_IS_RESOLVED;
break;
}
- if (!ident_eq_str(rhs->ident, "len")) {
+ if (!str_eq_cstr(rhs->ident_str, "len")) {
char *s = type_to_str(struct_type);
err_print(rhs->where, "Field of %s must be .len", s);
free(s);
@@ -3170,10 +3176,10 @@ static Status types_expr(Typer *tr, Expression *e) {
Namespace *nms = nms_val.nms;
lhs->kind = EXPR_VAL;
lhs->val.nms = nms;
- Identifier original = rhs->ident;
- rhs->ident = ident_translate(original, &nms->body.idents);
+ String str = rhs->ident_str;
+ rhs->ident = ident_get_with_len(&nms->body.idents, str.str, str.len);
if (!ident_is_declared(rhs->ident)) {
- char *s = ident_to_str(original);
+ char *s = cstr(str.str, str.len);
err_print(e->where, "\"%s\" is not a member of this namespace.", s);
free(s);
return false;
diff --git a/types.h b/types.h
index aabf246..d3a4e35 100644
--- a/types.h
+++ b/types.h
@@ -336,10 +336,12 @@ typedef struct NumLiteral {
};
} NumLiteral;
-typedef struct StrLiteral {
+typedef struct String {
char *str;
size_t len;
-} StrLiteral;
+} String;
+
+typedef String StrLiteral;
typedef struct {
U32 line;
@@ -793,10 +795,10 @@ typedef struct Expression {
struct {
BinaryOp op;
struct Expression *lhs;
- struct Expression *rhs;
union {
- Field *field; /* for struct. */
- } dot;
+ struct Expression *rhs;
+ Field *field; /* for struct., after resolving */
+ };
} binary;
CallExpr call;
struct {
@@ -808,7 +810,8 @@ typedef struct Expression {
BuiltinVal val;
} which;
} builtin;
- Identifier ident;
+ String ident_str; /* before typing */
+ Identifier ident; /* after typing */
NewExpr new;
Namespace *nms;
struct {