diff --git a/src/snc/expr.h b/src/snc/expr.h index 9ff21050c8ae4bf43eea268b8d07fd9d5e97b3b1..67431a2a811f2fbd8d2e41e61e54257d080e3803 100644 --- a/src/snc/expr.h +++ b/src/snc/expr.h @@ -46,5 +46,6 @@ Expr *decl_create(Token name); Expr *decl_postfix_array(Expr *d, char *s); Expr *decl_postfix_function(Expr *d, Expr *args); Expr *decl_prefix_pointer(Expr *d); +Expr *decl_prefix_const(Expr *d); #endif /*INCLparseh*/ diff --git a/src/snc/snl.lem b/src/snc/snl.lem index 7e017f307f293308d718d9a617190fcb2278ee9c..f61b7887efb473fcc18c0a6d2d3b3343f4fc65b8 100644 --- a/src/snc/snl.lem +++ b/src/snc/snl.lem @@ -194,6 +194,7 @@ declarator(p) ::= declarator(x) LPAREN param_decls(ps) RPAREN. [POST] { p = decl_postfix_function(x, ps); } declarator(p) ::= LPAREN declarator(x) RPAREN. [PRE] { p = x; } declarator(p) ::= ASTERISK declarator(x). [PRE] { p = decl_prefix_pointer(x); } +declarator(p) ::= CONST declarator(x). [PRE] { p = decl_prefix_const(x); } param_decls(p) ::= param_decl(x). { p = x; } param_decls(p) ::= param_decls(xs) COMMA param_decl(x). { p = link_expr(xs, x); } @@ -257,6 +258,8 @@ type_expr(p) ::= basetype(t) abs_decl(d). { p = decl_add_base_type(d, t); } abs_decl(p) ::= LPAREN abs_decl(x) RPAREN. { p = x; } abs_decl(p) ::= ASTERISK. [PRE] { p = decl_prefix_pointer(abs_decl_create()); } abs_decl(p) ::= ASTERISK abs_decl(d). [PRE] { p = decl_prefix_pointer(d); } +abs_decl(p) ::= CONST. [PRE] { p = decl_prefix_const(abs_decl_create()); } +abs_decl(p) ::= CONST abs_decl(d). [PRE] { p = decl_prefix_const(d); } abs_decl(p) ::= subscript(s). [POST] { p = decl_postfix_array(abs_decl_create(), s.str); } abs_decl(p) ::= abs_decl(d) subscript(s). [POST]{ p = decl_postfix_array(d, s.str); } abs_decl(p) ::= LPAREN param_decls(ps) RPAREN. [POST] diff --git a/src/snc/snl.re b/src/snc/snl.re index 267b7d9505f84dca5c490fa756cccabc1329dae0..3d514522b19845afd23f31080ea9031124f73d32 100644 --- a/src/snc/snl.re +++ b/src/snc/snl.re @@ -234,6 +234,7 @@ snl: "break" { KEYWORD(BREAK, "break"); } "char" { TYPEWORD(CHAR, "char"); } "connect" { KEYWORD(CONNECT, "connect"); } + "const" { TYPEWORD(CONST, "const"); } "continue" { KEYWORD(CONTINUE, "continue"); } "double" { TYPEWORD(DOUBLE, "double"); } "else" { KEYWORD(ELSE, "else"); } diff --git a/src/snc/var_types.c b/src/snc/var_types.c index 3c2cb6e1754a16d9b2b86b13c679803a6f96b815..e22e6839014e0627c3f7a28fbb414d02918787f8 100644 --- a/src/snc/var_types.c +++ b/src/snc/var_types.c @@ -64,6 +64,33 @@ Expr *decl_add_base_type(Expr *ds, Type basetype) } t->parent->val.function.return_type = t; break; + case T_CONST: + switch (t->tag) { + case T_NONE: + error_at_expr(d, "cannot declare constant foreign entity\n"); + break; + case T_EVFLAG: + error_at_expr(d, "cannot declare constant event flag\n"); + break; + case T_VOID: + error_at_expr(d, "cannot declare constant void\n"); + break; + case T_ARRAY: + error_at_expr(d, "cannot declare constant array\n"); + break; + case T_FUNCTION: + warning_at_expr(d, "declaring constant function is redundant\n"); + break; + case T_CONST: + warning_at_expr(d, "declaring constant constant is redundant\n"); + break; + case T_PRIM: + case T_FOREIGN: + case T_POINTER: + break; + } + t->parent->val.constant.value_type = t; + break; default: assert(impossible); } @@ -163,6 +190,19 @@ Expr *decl_prefix_pointer(Expr *d) return d; } +Expr *decl_prefix_const(Expr *d) +{ + Type *t = new(Type); + +#ifdef DEBUG + report("decl_prefix_const\n"); +#endif + assert(d->type == D_DECL); /* pre-condition */ + t->tag = T_CONST; + t->parent = d->extra.e_decl->type; + d->extra.e_decl->type = t; + return d; +} Type mk_prim_type(enum prim_type_tag tag) { @@ -248,6 +288,7 @@ static unsigned type_assignable_array(Type *t, int depth) case T_FUNCTION: case T_EVFLAG: case T_VOID: + case T_CONST: return FALSE; case T_ARRAY: return type_assignable_array(t->val.array.elem_type, depth + 1); @@ -278,6 +319,16 @@ static void gen_array_pointer(Type *t, enum type_tag last_tag, const char *prefi if (paren) gen_code(")"); break; + case T_CONST: + if (paren) + gen_code("("); + else + gen_code(" "); + gen_code("const"); + gen_array_pointer(t->parent, t->tag, prefix, name); + if (paren) + gen_code(")"); + break; case T_ARRAY: gen_array_pointer(t->parent, t->tag, prefix, name); gen_code("[%d]", t->val.array.num_elems); diff --git a/src/snc/var_types.h b/src/snc/var_types.h index ba48b05f7662feb6f43bfbfacc14260d68e37812..2194fbeca11ce3bcb76a01426f25630071e6e62e 100644 --- a/src/snc/var_types.h +++ b/src/snc/var_types.h @@ -18,6 +18,7 @@ enum type_tag { T_POINTER, T_ARRAY, T_FUNCTION, + T_CONST, }; enum foreign_type_tag { @@ -36,6 +37,10 @@ struct pointer_type { struct type *value_type; }; +struct constant_type { + struct type *value_type; +}; + struct function_type { struct expression *param_decls; struct type *return_type; @@ -56,6 +61,7 @@ struct type { struct pointer_type pointer; struct array_type array; struct function_type function; + struct constant_type constant; } val; struct type *parent; }; diff --git a/test/compiler/type_expr.st b/test/compiler/type_expr.st index fa2415b06c80afccf1a53a15d2a80e4b6e29e708..7f95c815a05ae8eb27cce17344a82928bf1a2531 100644 --- a/test/compiler/type_expr.st +++ b/test/compiler/type_expr.st @@ -33,6 +33,9 @@ entry { void (*pf4)(int**) = (void (*)(int**))n; void (*pf5)(double**,int) = (void (*)(double**,int))n; void (*pf6)(double**,int(**)[2]) = (void (*)(double**,int(**)[2]))n; + int const c = (int const)n; + int const *pc = (int const *)n; + unsigned long *const cp = (unsigned long *const)n; double **pd = (double**)(int*)n; double **ppd = (double**)(int(*)[3])n; void (*lf)( @@ -44,6 +47,9 @@ entry { void (*pf4)(int**), void (*pf5)(double**,int), void (*pf6)(double**,int(**)[2]), + int const c, + int const *pc, + unsigned long *const cp, double **pd, double **ppd ) = (void (*)( @@ -55,10 +61,13 @@ entry { void (*pf4)(int**), void (*pf5)(double**,int), void (*pf6)(double**,int(**)[2]), + int const c, + int const *pc, + unsigned long *const cp, double **pd, double **ppd ))n; - lf(p,pp,pf1,pf2,pf3,pf4,pf5,pf6,pd,ppd); + lf(p,pp,pf1,pf2,pf3,pf4,pf5,pf6,c,pc,cp,pd,ppd); } #include "../simple.st"