[pure-lang-svn] SF.net SVN: pure-lang:[555] pure/trunk
Status: Beta
Brought to you by:
agraef
From: <ag...@us...> - 2008-08-21 11:31:01
|
Revision: 555 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=555&view=rev Author: agraef Date: 2008-08-21 11:31:10 +0000 (Thu, 21 Aug 2008) Log Message: ----------- Fix const name capture in expression preprocessing. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc pure/trunk/interpreter.hh Added Paths: ----------- pure/trunk/test/test019.log pure/trunk/test/test019.pure Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-08-20 21:08:37 UTC (rev 554) +++ pure/trunk/ChangeLog 2008-08-21 11:31:10 UTC (rev 555) @@ -1,7 +1,14 @@ -2008-08-20 Albert Graef <Dr....@t-...> +2008-08-21 Albert Graef <Dr....@t-...> * 0.5 release. + * interpreter.cc (subst): Defer const substitutions (and + propagation of type tags) until all variable bindings have been + processed, to prevent name capture in const substitutions. + Reported by Eddie Rucker. + +2008-08-20 Albert Graef <Dr....@t-...> + * expr.cc (env::operator=): Bugfix: Only set temporary level of a constant or free variable if it wasn't defined previously at a lower level. Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-08-20 21:08:37 UTC (rev 554) +++ pure/trunk/interpreter.cc 2008-08-21 11:31:10 UTC (rev 555) @@ -740,7 +740,7 @@ save_globals(g); compile(); // promote type tags and substitute constants: - env vars; expr u = subst(vars, x); + env vars; expr u = csubst(subst(vars, x)); compile(u); x = u; pure_expr *res = doeval(u, e); @@ -767,7 +767,7 @@ compile(); env vars; // promote type tags and substitute constants: - expr rhs = subst(vars, x); + expr rhs = csubst(subst(vars, x)); expr lhs = bind(vars, pat); build_env(vars, lhs); for (env::const_iterator it = vars.begin(); it != vars.end(); ++it) { @@ -864,7 +864,7 @@ compile(); env vars; // promote type tags and substitute constants: - expr rhs = subst(vars, x); + expr rhs = csubst(subst(vars, x)); expr lhs = bind(vars, pat); build_env(vars, lhs); for (env::const_iterator it = vars.begin(); it != vars.end(); ++it) { @@ -1368,6 +1368,11 @@ assert(!r.lhs.is_null()); closure(r, false); if (toplevel) { + // substitute constants: + expr u = expr(r.lhs), + v = expr(csubst(r.rhs)), + w = expr(csubst(r.qual)); + r = rule(u, v, w); compile(r.rhs); compile(r.qual); } @@ -1625,14 +1630,7 @@ } else { expr u = subst(vars, x.xval1(), idx), v = subst(vars, x.xval2(), idx); - expr w = expr(u, v); - // promote type tags - expr f; uint32_t n = count_args(w, f); - if (n == 1) - promote_ttags(f, w, w.xval2()); - else if (n == 2) - promote_ttags(f, w, w.xval1().xval2(), w.xval2()); - return w; + return expr(u, v); } // conditionals: case EXPR::COND: { @@ -1705,18 +1703,108 @@ // not a bound variable if (x.ttag() != 0) throw err("error in expression (misplaced type tag)"); - it = globenv.find(sym.f); - if (it != globenv.end() && it->second.t == env_info::cvar) - // substitute constant value - return *it->second.cval; - else - return x; + return x; } const env_info& info = it->second; return expr(EXPR::VAR, sym.f, idx, info.ttag, *info.p); } } +expr interpreter::csubst(expr x) +{ + if (x.is_null()) return x; + switch (x.tag()) { + // constants: + case EXPR::VAR: + case EXPR::FVAR: + case EXPR::INT: + case EXPR::BIGINT: + case EXPR::DBL: + case EXPR::STR: + case EXPR::PTR: + return x; + // application: + case EXPR::APP: + if (x.xval1().tag() == EXPR::APP && + x.xval1().xval1().tag() == symtab.catch_sym().f) { + expr u = csubst(x.xval1().xval2()), + v = csubst(x.xval2()); + return expr(symtab.catch_sym().x, u, v); + } else { + expr u = csubst(x.xval1()), + v = csubst(x.xval2()); + expr w = expr(u, v); + // promote type tags + expr f; uint32_t n = count_args(w, f); + if (n == 1) + promote_ttags(f, w, w.xval2()); + else if (n == 2) + promote_ttags(f, w, w.xval1().xval2(), w.xval2()); + return w; + } + // conditionals: + case EXPR::COND: { + expr u = csubst(x.xval1()), + v = csubst(x.xval2()), + w = csubst(x.xval3()); + return expr::cond(u, v, w); + } + // nested closures: + case EXPR::LAMBDA: { + expr u = x.xval1(), v = csubst(x.xval2()); + return expr::lambda(u, v); + } + case EXPR::CASE: { + expr u = csubst(x.xval()); + const rulel *r = x.rules(); + rulel *s = new rulel; + for (rulel::const_iterator it = r->begin(); it != r->end(); ++it) { + expr u = it->lhs, v = csubst(it->rhs), + w = csubst(it->qual); + s->push_back(rule(u, v, w)); + } + return expr::cases(u, s); + } + case EXPR::WHEN: { + const rulel *r = x.rules(); + rulel *s = new rulel; + for (rulel::const_iterator it = r->begin(); it != r->end(); ++it) { + expr u = it->lhs, v = csubst(it->rhs); + s->push_back(rule(u, v)); + } + expr u = csubst(x.xval()); + return expr::when(u, s); + } + case EXPR::WITH: { + expr u = csubst(x.xval()); + const env *e = x.fenv(); + env *f = new env; + for (env::const_iterator it = e->begin(); it != e->end(); ++it) { + int32_t g = it->first; + const env_info& info = it->second; + const rulel *r = info.rules; + rulel s; + for (rulel::const_iterator jt = r->begin(); jt != r->end(); ++jt) { + expr u = jt->lhs, v = csubst(jt->rhs), + w = csubst(jt->qual); + s.push_back(rule(u, v, w)); + } + (*f)[g] = env_info(info.argc, s, info.temp); + } + return expr::with(u, f); + } + default: + assert(x.tag() > 0); + const symbol& sym = symtab.sym(x.tag()); + env::const_iterator it = globenv.find(sym.f); + if (it != globenv.end() && it->second.t == env_info::cvar) + // substitute constant value + return *it->second.cval; + else + return x; + } +} + expr interpreter::fsubst(const env& funs, expr x, uint8_t idx) { if (x.is_null()) return x; Modified: pure/trunk/interpreter.hh =================================================================== --- pure/trunk/interpreter.hh 2008-08-20 21:08:37 UTC (rev 554) +++ pure/trunk/interpreter.hh 2008-08-21 11:31:10 UTC (rev 555) @@ -448,6 +448,7 @@ void promote_ttags(expr f, expr x, expr u, expr v); expr bind(env& vars, expr x, bool b = true, path p = path()); expr subst(const env& vars, expr x, uint8_t idx = 0); + expr csubst(expr x); expr fsubst(const env& funs, expr x, uint8_t idx = 0); void closure(expr& l, expr& r, bool b = true); void closure(rule& r, bool b = true); Added: pure/trunk/test/test019.log =================================================================== --- pure/trunk/test/test019.log (rev 0) +++ pure/trunk/test/test019.log 2008-08-21 11:31:10 UTC (rev 555) @@ -0,0 +1,13 @@ +const i = -1; +catmap (\i/*0:*/ -> catmap (\j/*0:*/ -> [(i/*1:*/,j/*0:*/)] { + rule #0: j = [(i,j)] + state 0: #0 + <var> state 1 + state 1: #0 +}) (3..4) { + rule #0: i = catmap (\j -> [(i,j)]) (3..4) + state 0: #0 + <var> state 1 + state 1: #0 +}) (1..2); +[(1,3),(1,4),(2,3),(2,4)] Added: pure/trunk/test/test019.pure =================================================================== --- pure/trunk/test/test019.pure (rev 0) +++ pure/trunk/test/test019.pure 2008-08-21 11:31:10 UTC (rev 555) @@ -0,0 +1,3 @@ +// const name capture regression, reported by Eddie Rucker +const i = -1; +[(i,j); i=1..2; j=3..4]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |