diff options
Diffstat (limited to 'bootstrap')
-rw-r--r-- | bootstrap/compiler.h | 3 | ||||
-rw-r--r-- | bootstrap/out.c | 9 | ||||
-rw-r--r-- | bootstrap/outexpr.c | 2 | ||||
-rw-r--r-- | bootstrap/outstmt.c | 2 | ||||
-rw-r--r-- | bootstrap/parsedecl.c | 127 | ||||
-rw-r--r-- | bootstrap/parsestmt.c | 6 | ||||
-rw-r--r-- | bootstrap/token.c | 10 | ||||
-rw-r--r-- | bootstrap/token.h | 31 |
8 files changed, 175 insertions, 15 deletions
diff --git a/bootstrap/compiler.h b/bootstrap/compiler.h index 1aafb6e..e892df6 100644 --- a/bootstrap/compiler.h +++ b/bootstrap/compiler.h @@ -152,14 +152,15 @@ struct TypeRefNumeric { enum TypeRefKind { TR_UNKNOWN, - TR_NUMERIC, TR_BOOL, + TR_INT, TR_STRING, TR_CLASS }; struct TypeRef { enum TypeRefKind kind; + unsigned quals; union { struct TypeRefNumeric *num; struct Type *class_; diff --git a/bootstrap/out.c b/bootstrap/out.c index f5bfcca..845a875 100644 --- a/bootstrap/out.c +++ b/bootstrap/out.c @@ -30,16 +30,19 @@ void emit_ident(struct Ident *ident) outf("%.*s", ident->node.length, ident->node.name); } -/* FIXME int, bool, array... ?? currently it only supports "classes" */ +/* FIXME arrays, optional types, generics... */ void emit_typeref_prefix(struct TypeRef *tr) { /* TODO output parantheses for nested types e.g. array of pointer etc. */ switch (tr->kind) { case TR_UNKNOWN: ast_error("TR_UNKNOWN encountered at codegen time"); - case TR_NUMERIC: case TR_BOOL: - /* No suffix */ + outf("bool "); + break; + case TR_INT: + /* TODO unsigned and uint64 */ + outf("int "); break; case TR_STRING: case TR_CLASS: diff --git a/bootstrap/outexpr.c b/bootstrap/outexpr.c index a5916ba..c6e6f36 100644 --- a/bootstrap/outexpr.c +++ b/bootstrap/outexpr.c @@ -140,8 +140,10 @@ static void declare_expr_temps(struct Expr *expr, share the ID with the preceding E_SEQPOINT and and hence already declared at this point. */ outf("int");/* TODO use expr->tr */ + /*emit_typeref_prefix(expr->typeref);*/ outc(' '); emit_subexpr_varname(expr, target_ident, target_num); + /*emit_typeref_suffix(expr->typeref);*/ outf(";\n"); } } diff --git a/bootstrap/outstmt.c b/bootstrap/outstmt.c index bfc82bc..d5286b5 100644 --- a/bootstrap/outstmt.c +++ b/bootstrap/outstmt.c @@ -28,7 +28,7 @@ static void emit_compare(struct TypeRef *tr, const char *res_name, int res_id, static void emit_bool(struct Stmt *stmt, struct Expr *expr) { - static const struct TypeRef booltr = { TR_BOOL, { NULL } }; + static const struct TypeRef booltr = { TR_BOOL, 0, { NULL } }; emit_expr(&booltr, "b", stmt->id, expr); } diff --git a/bootstrap/parsedecl.c b/bootstrap/parsedecl.c index aedf274..7c01886 100644 --- a/bootstrap/parsedecl.c +++ b/bootstrap/parsedecl.c @@ -414,8 +414,18 @@ static enum Token parse_paramlist(struct Var **list_out, size_t *count_out) struct Var *var; t = tokenize(&li); - /* TODO var/out parameters */ - if (t != T_UpperIdent) { + /* TODO var/out parameters + (again, there's a difference between modifying an + object and replacing it...) */ + switch ((int)t) { + case T_UpperIdent: + case T_KW_bool: + case T_KW_byte: + case T_KW_int: + case T_KW_long: + TOKEN_CASES_QUALIFIERS + break; + default: if (count_out) { *count_out = count; } @@ -441,22 +451,121 @@ static enum Token parse_paramlist(struct Var **list_out, size_t *count_out) ¤t_type->inner_types : &module->types); - generic types */ +struct QualifierInfo { + unsigned qual; + int position; +}; + static struct TypeRef *parse_type_usage(void) { enum Token tok; struct LexemeInfo li; struct TypeRef *tr = malloc(sizeof(struct TypeRef)); + int qualifier_position = 0; + static const struct QualifierInfo qualinfos[NUM_QUALIFIERS] = { + /* TODO "modifiable object" vs "replaceable object" + could use <- vs = operators for "replaceable", + but that doens't work inside structs! */ + { Q_VAR, 1 }, + { Q_ALIASED, 2 }, + { Q_VOLATILE, 2 }, + { Q_WRAPPING, 3 }, + { Q_SIGNED, 4 }, + { Q_UNSIGNED, 4 } + }; + unsigned quals = 0; NO_NULL(tr); - /* TODO needs to handle different types (identifier, array, etc.) */ - /* TODO needs to handle generic types */ - tok = tokenize(&li); - if (tok == T_UpperIdent) { - tr->kind = TR_CLASS; - tr->u.class_ = map_named_type(li.string, li.len); + /* TODO needs to handle: + - arrays + - optional types + - generic types */ + for (;;) { + tok = tokenize(&li); + switch ((int)tok) { + /* Types */ + case T_UpperIdent: + tr->kind = TR_CLASS; + tr->u.class_ = map_named_type(li.string, li.len); + goto done; + case T_LowerIdent: + if ((quals & (Q_WRAPPING|Q_SIGNED|Q_UNSIGNED)) == 0) { + error("Expected a type"); + } + unread_token(); + goto implicit_int; + case T_KW_bool: + tr->kind = TR_BOOL; + goto done; + case T_KW_byte: + if ((quals & Q_UNSIGNED) != 0) { + error("The `byte` type always has the full unsigned range"); + } + tr->kind = TR_INT; + /* TODO set range */ + goto done; + case T_KW_int: + if ((quals & (Q_WRAPPING|Q_SIGNED|Q_UNSIGNED)) != 0) { + error("Redundant `int` keyword after wrapping/signed/unsigned"); + } + implicit_int: + tr->kind = TR_INT; + /* TODO set range */ + goto done; + /* XXX separate size_t type? + - but the platform dependence makes it trickier + (behaviour should be the same across platforms) + - maybe the size_t type could trap on overflow? + (basically, a variant of OoM, except it's the address space) + - a size type also makes sense for constraining the length + to up to the system size, even if the "logical" maximum + is larger (e.g. if the application allows up to e.g. 2^40 + but is compiled on a 32 bit platform. + - BUT with an unknown range of size types, it beomes + inconvenient, because size can't be converted to int + without an assert/if. + - have a "large-array" type? which could optionally + be compressed and/or "windowed memory mapped"? + - a size_t type could also serve as documentation */ + case T_KW_long: + tr->kind = TR_INT; + /* TODO set range */ + goto done; + TOKEN_CASES_QUALIFIERS { + struct QualifierInfo info = qualinfos[tok - FIRST_QUALIFIER]; + if (qualifier_position >= info.position) { +fprintf(stderr, "qp=%d, ip=%d\n", qualifier_position, info.position); + error(info.position == qualifier_position ? + "Conflicting type qualifier" : + "Wrong order of type qualifiers"); + } else if (info.position == 4 && (quals&Q_WRAPPING) != 0) { + error("wrapping integers are implicitly unsigned"); + } + qualifier_position = info.position; + quals |= info.qual; + break; } + default: + error("Expected a type here"); + } + } + done: + if (tr->kind == TR_BOOL) { + if ((quals & (unsigned)~Q_VAR) != 0) { + error("bool cannot have any qualifiers other than `var`"); + } + } else if (tr->kind == TR_CLASS) { /* TODO also arrays etc. */ + if ((quals & (Q_WRAPPING|Q_SIGNED|Q_UNSIGNED)) != 0) { + error("wrapping/signed/unsigned are not applicable for objects"); + } } else { - error("Expected a type here"); + if ((quals & (Q_ALIASED|Q_VOLATILE)) != 0) { + error("aliased/volatile are not applicable for int/bool/long"); + } + } + if ((quals & Q_WRAPPING) != 0) { + quals |= Q_UNSIGNED; } + tr->quals = quals; return tr; } diff --git a/bootstrap/parsestmt.c b/bootstrap/parsestmt.c index 3daba26..1e3bd9f 100644 --- a/bootstrap/parsestmt.c +++ b/bootstrap/parsestmt.c @@ -243,7 +243,11 @@ static enum Token parse_stmt_block(struct Stmt **stmt_out) error(msg); } break; } - case T_KW_var: + TOKEN_CASES_QUALIFIERS + case T_KW_bool: + case T_KW_byte: + case T_KW_int: + case T_KW_long: case T_UpperIdent: { /* Variable definition */ struct Var *var; diff --git a/bootstrap/token.c b/bootstrap/token.c index d1223f0..197fbd0 100644 --- a/bootstrap/token.c +++ b/bootstrap/token.c @@ -155,12 +155,16 @@ static enum Token tok_alphanum(struct LexemeInfo *li_out) CMP_KW(3, and) CMP_KW(3, end) CMP_KW(3, for) + CMP_KW(3, int) CMP_KW(3, mod) CMP_KW(3, not) /* XXX should there be `and`/`or`, or `all_of`/`any_of`/`none_of`? maybe there should be a T... safe-vararg, like in Java. */ + CMP_KW(3, var) break; case 4: + CMP_KW(4, bool) + CMP_KW(4, byte) CMP_KW(4, case) CMP_KW(4, code) CMP_KW(4, elif) @@ -168,6 +172,7 @@ static enum Token tok_alphanum(struct LexemeInfo *li_out) CMP_KW(4, enum) CMP_KW(4, from) CMP_KW(4, func) + CMP_KW(4, long) CMP_KW(4, none) CMP_KW(4, sets) CMP_KW(4, true) @@ -186,9 +191,11 @@ static enum Token tok_alphanum(struct LexemeInfo *li_out) CMP_KW(6, export) CMP_KW(6, record) CMP_KW(6, return) + CMP_KW(6, signed) CMP_KW(6, switch) break; case 7: + CMP_KW(7, aliased) CMP_KW(7, default) CMP_KW(7, loopend) CMP_KW(7, returns) @@ -197,6 +204,9 @@ static enum Token tok_alphanum(struct LexemeInfo *li_out) case 8: CMP_KW(8, continue) CMP_KW(8, modifies) + CMP_KW(8, unsigned) + CMP_KW(8, volatile) + CMP_KW(8, wrapping) break; case 9: CMP_KW(9, loopempty) diff --git a/bootstrap/token.h b/bootstrap/token.h index 06a5048..d3a906a 100644 --- a/bootstrap/token.h +++ b/bootstrap/token.h @@ -44,8 +44,18 @@ enum Token { T_KW_record, T_KW_templates, T_KW_trait, + /* Builtin types */ + T_KW_bool, + T_KW_byte, + T_KW_int, + T_KW_long, /* Qualifiers */ T_KW_var, + T_KW_aliased, + T_KW_volatile, + T_KW_wrapping, + T_KW_signed, + T_KW_unsigned, /* Generics */ T_KW_of, T_KW_to, @@ -88,6 +98,18 @@ enum Token { T_KW_none }; +#define FIRST_QUALIFIER T_KW_var +#define LAST_QUALIFIER T_KW_unsigned +#define NUM_QUALIFIERS (LAST_QUALIFIER+1 - FIRST_QUALIFIER) +#define TOKEN_CASES_QUALIFIERS \ + case T_KW_var: \ + case T_KW_aliased: \ + case T_KW_volatile: \ + case T_KW_wrapping: \ + case T_KW_signed: \ + case T_KW_unsigned: + + #define TOKEN_CASES_VALUE_START \ case T_LowerIdent: \ case T_Integer: \ @@ -100,6 +122,15 @@ enum Token { case T_KW_true: \ case T_KW_none: +/* Type qualifiers */ +#define Q_VAR 0x01 +#define Q_ALIASED 0x02 +#define Q_VOLATILE 0x04 +#define Q_SIGNED 0x08 +#define Q_UNSIGNED 0x10 +#define Q_WRAPPING 0x20 + + struct LexemeInfo { size_t len; |