ref: f65cbaf876d37084d8fc421b4642847bf5ac9162
parent: c49aefbd03db6f3253160b34ff2ed0812615a84f
author: Ori Bernstein <[email protected]>
date: Tue Oct 8 18:42:05 EDT 2013
Propagate the constness of expressions.
--- a/6/simp.c
+++ b/6/simp.c
@@ -1474,7 +1474,7 @@
} else if (!dcl->decl.isconst && !e) {
lappend(&s->blobs, &s->nblobs, dcl);
} else {
- fatal(dcl->line, "Declaration %s initialized with nonconstant value", declname(dcl));
+ die("Non-constant initializer for %s\n", declname(dcl));
}
}
--- a/libstd/sys-osx.myr
+++ b/libstd/sys-osx.myr
@@ -1,4 +1,5 @@
use "types.use"
+use "errno-osx.use"
pkg std =
type scno = int64
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -825,6 +825,7 @@
fatal(n->line, "Undeclared var %s.%s", nsname->name.ns, nsname->name.name);
var = mkexpr(n->line, Ovar, nsname, NULL);
var->expr.did = s->decl.did;
+ var->expr.isconst = s->decl.isconst;
if (s->decl.isgeneric)
settype(st, var, tyfreshen(st, s->decl.type));
else
@@ -960,10 +961,12 @@
size_t i, nargs;
Node *s;
Type *t;
+ int isconst;
assert(n->type == Nexpr);
args = n->expr.args;
nargs = n->expr.nargs;
+ isconst = 1;
for (i = 0; i < nargs; i++) {
/* Nlit, Nvar, etc should not be inferred as exprs */
if (args[i]->type == Nexpr) {
@@ -972,8 +975,11 @@
if (exprop(args[i]) == Omemb)
checkns(st, args[i], &args[i]);
inferexpr(st, args[i], ret, sawret);
+ isconst = isconst && args[i]->expr.isconst;
}
}
+ if (ispureop[exprop(n)])
+ n->expr.isconst = isconst;
infernode(st, n->expr.idx, NULL, NULL);
switch (exprop(n)) {
/* all operands are same type */
@@ -984,8 +990,12 @@
case Oneg: /* -@a -> @a */
t = type(st, args[0]);
constrain(st, n, type(st, args[0]), cstrtab[Tcnum]);
- for (i = 1; i < nargs; i++)
+ isconst = args[0]->expr.isconst;
+ for (i = 1; i < nargs; i++) {
+ isconst = isconst && args[i]->expr.isconst;
t = unify(st, n, t, type(st, args[i]));
+ }
+ n->expr.isconst = isconst;
settype(st, n, tf(st, t));
break;
case Omod: /* @a % @a -> @a */
@@ -1012,8 +1022,12 @@
t = type(st, args[0]);
constrain(st, n, type(st, args[0]), cstrtab[Tcnum]);
constrain(st, n, type(st, args[0]), cstrtab[Tcint]);
- for (i = 1; i < nargs; i++)
+ isconst = args[0]->expr.isconst;
+ for (i = 1; i < nargs; i++) {
+ isconst = isconst && args[i]->expr.isconst;
t = unify(st, n, t, type(st, args[i]));
+ }
+ n->expr.isconst = isconst;
settype(st, n, tf(st, t));
break;
case Oasn: /* @a = @a -> @a */
@@ -1021,6 +1035,8 @@
for (i = 1; i < nargs; i++)
t = unify(st, n, t, type(st, args[i]));
settype(st, n, tf(st, t));
+ if (args[0]->expr.isconst)
+ fatal(n->line, "Attempting to assign constant \"%s\"", ctxstr(st, args[0]));
break;
/* operands same type, returning bool */
@@ -1099,10 +1115,12 @@
if (!s)
fatal(n->line, "Undeclared var %s", ctxstr(st, args[0]));
+ n->expr.isconst = s->decl.isconst;
if (s->decl.isgeneric)
t = tyfreshen(st, tf(st, s->decl.type));
else
t = s->decl.type;
+ n->expr.isconst = s->decl.isconst;
settype(st, n, t);
n->expr.did = s->decl.did;
if (s->decl.isgeneric && !st->ingeneric) {
@@ -1175,6 +1193,8 @@
if (n->decl.init) {
inferexpr(st, n->decl.init, NULL, NULL);
unify(st, n, type(st, n), type(st, n->decl.init));
+ if (n->decl.isconst && !n->decl.init->expr.isconst)
+ fatal(n->line, "non-const initializer for \"%s\"", ctxstr(st, n));
} else {
if (n->decl.isconst && !n->decl.isextern)
fatal(n->line, "non-extern \"%s\" has no initializer", ctxstr(st, n));