Thread: [pure-lang-svn] SF.net SVN: pure-lang: [74] pure/trunk (Page 2)
Status: Beta
Brought to you by:
agraef
From: <ag...@us...> - 2008-05-12 06:42:21
|
Revision: 74 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=74&view=rev Author: agraef Date: 2008-05-11 23:42:28 -0700 (Sun, 11 May 2008) Log Message: ----------- Redirect warning and error messages to the logfile. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc pure/trunk/interpreter.hh pure/trunk/lexer.ll Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-12 06:36:42 UTC (rev 73) +++ pure/trunk/ChangeLog 2008-05-12 06:42:28 UTC (rev 74) @@ -1,3 +1,7 @@ +2008-05-12 Albert Graef <Dr....@t-...> + + * Makefile: Redirect warning and error messages to the logfile. + 2008-05-10 Albert Graef <Dr....@t-...> * interpreter.cc (uminop): Handle the value -0x80000000 at the Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-05-12 06:36:42 UTC (rev 73) +++ pure/trunk/interpreter.cc 2008-05-12 06:42:28 UTC (rev 74) @@ -491,6 +491,38 @@ } } +#if DEBUG>1 +void print_map(ostream& os, const Env *e) +{ + static size_t indent = 0; + string blanks(indent, ' '); + interpreter& interp = *interpreter::g_interp; + os << blanks << ((e->tag>0)?interp.symtab.sym(e->tag).s:"anonymous") + << " (" << (void*)e << ") {\n" << blanks << "XMAP:\n"; + list<VarInfo>::const_iterator xi; + for (xi = e->xtab.begin(); xi != e->xtab.end(); xi++) { + const VarInfo& x = *xi; + assert(x.vtag > 0); + os << blanks << " " << interp.symtab.sym(x.vtag).s << " (#" << x.v << ") " + << (uint32_t)x.idx << ":"; + const path &p = x.p; + for (size_t i = 0; i < p.len(); i++) os << p[i]; + os << endl; + } + for (size_t i = 0, n = e->fmap.size(); i < n; i++) { + os << blanks << "FMAP #" << i << ":\n"; + indent += 2; + map<int32_t,Env>::const_iterator fi; + for (fi = e->fmap[i].begin(); fi != e->fmap[i].end(); fi++) { + const Env& e = fi->second; + print_map(os, &e); + } + indent -= 2; + } + os << blanks << "}\n"; +} +#endif + void interpreter::compile() { using namespace llvm; @@ -506,6 +538,9 @@ if (verbose&verbosity::code) std::cout << *info.m << endl; // regenerate LLVM code (prolog) Env& f = globalfuns[ftag] = Env(ftag, info, false, false); +#if DEBUG>1 + print_map(std::cerr, &f); +#endif push("compile", &f); globalfuns[ftag].f = fun_prolog(symtab.sym(ftag).s); pop(&f); @@ -1527,7 +1562,8 @@ args = e.args; envs = e.envs; argv = e.argv; b = e.b; local = e.local; parent = e.parent; } - fmap = e.fmap; xmap = e.xmap; xtab = e.xtab; prop = e.prop; m = e.m; + fmap = e.fmap; fmap_idx = e.fmap_idx; + xmap = e.xmap; xtab = e.xtab; prop = e.prop; m = e.m; return *this; } @@ -1545,7 +1581,7 @@ interp.JIT->freeMachineCodeForFunction(f); f->dropAllReferences(); if (h != f) h->dropAllReferences(); fp = 0; - fmap.clear(); + fmap.clear(); fmap_idx = 0; to_be_deleted.push_back(f); if (h != f) to_be_deleted.push_back(h); } else { #if DEBUG>2 @@ -1562,7 +1598,8 @@ } fp = 0; // delete all nested environments and reinitialize other body-related data - fmap.clear(); xmap.clear(); xtab.clear(); prop.clear(); m = 0; argv = 0; + fmap.clear(); fmap_idx = 0; + xmap.clear(); xtab.clear(); prop.clear(); m = 0; argv = 0; // now that all references have been removed, delete the function pointers for (list<Function*>::iterator fi = to_be_deleted.begin(); fi != to_be_deleted.end(); fi++) { @@ -1678,36 +1715,6 @@ #endif } -#if DEBUG>1 -void print_map(ostream& os, const Env *e) -{ - static size_t indent = 0; - string blanks(indent, ' '); - interpreter& interp = *interpreter::g_interp; - os << blanks << ((e->tag>0)?interp.symtab.sym(e->tag).s:"anonymous") - << " {\n" << blanks << "XMAP:\n"; - list<VarInfo>::const_iterator xi; - for (xi = e->xtab.begin(); xi != e->xtab.end(); xi++) { - const VarInfo& x = *xi; - assert(x.vtag > 0); - os << blanks << " " << interp.symtab.sym(x.vtag).s << " (#" << x.v << ") " - << (uint32_t)x.idx << ":"; - const path &p = x.p; - for (size_t i = 0; i < p.len(); i++) os << p[i]; - os << endl; - } - os << blanks << "FMAP:\n"; - indent += 2; - map<int32_t,Env>::const_iterator fi; - for (fi = e->fmap.begin(); fi != e->fmap.end(); fi++) { - const Env& e = fi->second; - print_map(os, &e); - } - indent -= 2; - os << blanks << "}\n"; -} -#endif - void Env::build_map(expr x) { // build the maps for a (rhs) expression @@ -1727,8 +1734,8 @@ assert(ei != envstk.end()); fenv = *ei++; } - assert(fenv->fmap.find(x.vtag()) != fenv->fmap.end()); - fenv = &fenv->fmap[x.vtag()]; + assert(fenv->act_fmap().find(x.vtag()) != fenv->act_fmap().end()); + fenv = &fenv->act_fmap()[x.vtag()]; if (!fenv->local) break; // fenv now points to the environment of the (local) function assert(fenv != this && fenv->tag == x.vtag()); @@ -1788,7 +1795,7 @@ if (n == 2 && f.tag() == interp.symtab.catch_sym().f) { expr h = x.xval1().xval2(), y = x.xval2(); push("catch"); - Env& e = fmap[-x.hash()] = Env(0, 0, y, true, true); + Env& e = act_fmap()[-x.hash()] = Env(0, 0, y, true, true); e.build_map(y); e.promote_map(); pop(); build_map(h); @@ -1805,14 +1812,14 @@ break; case EXPR::LAMBDA: { push("lambda"); - Env& e = fmap[-x.hash()] = Env(0, 1, x.xval2(), true, true); + Env& e = act_fmap()[-x.hash()] = Env(0, 1, x.xval2(), true, true); e.build_map(x.xval2()); e.promote_map(); pop(); break; } case EXPR::CASE: { push("case"); - Env& e = fmap[-x.hash()] = Env(0, 1, x.xval(), true, true); + Env& e = act_fmap()[-x.hash()] = Env(0, 1, x.xval(), true, true); e.build_map(*x.rules()); e.promote_map(); pop(); build_map(x.xval()); @@ -1829,13 +1836,13 @@ for (env::const_iterator p = fe->begin(); p != fe->end(); p++) { int32_t ftag = p->first; const env_info& info = p->second; - fmap[ftag] = Env(ftag, info, false, true); + act_fmap()[ftag] = Env(ftag, info, false, true); } // Now recursively build the maps for the child environments. for (env::const_iterator p = fe->begin(); p != fe->end(); p++) { int32_t ftag = p->first; const env_info& info = p->second; - Env& e = fmap[ftag]; + Env& e = act_fmap()[ftag]; e.build_map(info); e.promote_map(); } pop(); @@ -1859,7 +1866,7 @@ rulel::const_iterator s = r; expr y = (++s == end)?x:s->rhs; push("when"); - Env& e = fmap[-y.hash()] = Env(0, 1, y, true, true); + Env& e = act_fmap()[-y.hash()] = Env(0, 1, y, true, true); e.build_map(x, s, end); e.promote_map(); pop(); build_map(r->rhs); @@ -1879,12 +1886,16 @@ { // build the maps for a global function definition assert(info.t == env_info::fun); + // we need a separate submap for each rule + size_t n = info.rules->size(); + fmap.resize(n); rulel::const_iterator r = info.rules->begin(); while (r != info.rules->end()) { build_map(r->rhs); if (!r->qual.is_null()) build_map(r->qual); - r++; + r++; fmap_idx++; } + fmap_idx = 0; #if DEBUG>1 if (!local) print_map(std::cerr, this); #endif @@ -2652,8 +2663,8 @@ Env& act = act_env(); rulel::const_iterator s = r; expr y = (++s == end)?x:s->rhs; - assert(act.fmap.find(-y.hash()) != act.fmap.end()); - Env& e = act.fmap[-y.hash()]; + assert(act.act_fmap().find(-y.hash()) != act.act_fmap().end()); + Env& e = act.act_fmap()[-y.hash()]; push("when", &e); fun_prolog("anonymous"); BasicBlock *bodybb = new BasicBlock("body"); @@ -3069,7 +3080,7 @@ int offs = idx-1; if (idx == 0) { // function in current environment ('with'-bound) - f = &act_env().fmap[tag]; + f = &act_env().act_fmap()[tag]; } else { // function in an outer environment, the de Bruijn index idx tells us // where on the current environment stack it's at @@ -3077,7 +3088,7 @@ size_t i = idx; for (; i > 0; e++, i--) assert(e != envstk.end()); // look up the function in the environment - f = &(*e)->fmap[tag]; + f = &(*e)->act_fmap()[tag]; } if (f->n == n) { // bingo! saturated call @@ -3158,8 +3169,8 @@ // through pure_catch() expr h = x.xval1().xval2(), y = x.xval2(); Env& act = act_env(); - assert(act.fmap.find(-x.hash()) != act.fmap.end()); - Env& e = act.fmap[-x.hash()]; + assert(act.act_fmap().find(-x.hash()) != act.act_fmap().end()); + Env& e = act.act_fmap()[-x.hash()]; push("catch", &e); fun_prolog("anonymous"); e.CreateRet(codegen(y)); @@ -3184,8 +3195,8 @@ // anonymous closure: case EXPR::LAMBDA: { Env& act = act_env(); - assert(act.fmap.find(-x.hash()) != act.fmap.end()); - Env& e = act.fmap[-x.hash()]; + assert(act.act_fmap().find(-x.hash()) != act.act_fmap().end()); + Env& e = act.act_fmap()[-x.hash()]; push("lambda", &e); fun("anonymous", x.pm(), true); pop(&e); @@ -3196,8 +3207,8 @@ // case expression: treated like an anonymous closure (see the lambda case // above) which gets applied to the subject term to be matched Env& act = act_env(); - assert(act.fmap.find(-x.hash()) != act.fmap.end()); - Env& e = act.fmap[-x.hash()]; + assert(act.act_fmap().find(-x.hash()) != act.act_fmap().end()); + Env& e = act.act_fmap()[-x.hash()]; push("case", &e); fun("anonymous", x.pm(), true); pop(&e); @@ -3223,16 +3234,16 @@ // mutually recursive definitions for (p = fe->begin(); p != fe->end(); p++) { int32_t ftag = p->first; - assert(act.fmap.find(ftag) != act.fmap.end()); - Env& e = act.fmap[ftag]; + assert(act.act_fmap().find(ftag) != act.act_fmap().end()); + Env& e = act.act_fmap()[ftag]; push("with", &e); - act.fmap[ftag].f = fun_prolog(symtab.sym(ftag).s); + act.act_fmap()[ftag].f = fun_prolog(symtab.sym(ftag).s); pop(&e); } for (p = fe->begin(); p != fe->end(); p++) { int32_t ftag = p->first; const env_info& info = p->second; - Env& e = act.fmap[ftag]; + Env& e = act.act_fmap()[ftag]; push("with", &e); fun_body(info.m); pop(&e); @@ -3498,7 +3509,7 @@ assert(!envstk.empty()); if (idx == 0) { // function in current environment ('with'-bound) - Env& f = act_env().fmap[tag]; + Env& f = act_env().act_fmap()[tag]; return fbox(f, thunked); } // If we come here, the function is defined in an outer environment. Locate @@ -3508,7 +3519,7 @@ size_t i = idx; for (; i > 0; e++, i--) assert(e != envstk.end()); // look up the function in the environment - Env& f = (*e)->fmap[tag]; + Env& f = (*e)->act_fmap()[tag]; assert(f.f); // Now create the closure. This is essentially just like fbox(), but we are // called inside a nested environment here, and hence the de Bruijn indices @@ -4469,14 +4480,17 @@ Env& f = act_env(); assert(s->tr.empty()); // we're in a final state here const rulev& rules = pm->r; + assert(f.fmap.size() == 1 || f.fmap.size() == rules.size()); const ruleml& rl = s->r; ruleml::const_iterator r = rl.begin(); assert(r != rl.end()); + assert(f.fmap_idx == 0); BasicBlock* rulebb = new BasicBlock(mklabel("rule.state", s->s, rl.front())); f.builder.CreateBr(rulebb); while (r != rl.end()) { const rule& rr = rules[*r]; reduced.insert(*r); + if (f.fmap.size() > 1) f.fmap_idx = *r; f.f->getBasicBlockList().push_back(rulebb); f.builder.SetInsertPoint(rulebb); #if DEBUG>1 @@ -4534,4 +4548,5 @@ f.CreateRet(codegen(rr.rhs)); rulebb = nextbb; } + if (f.fmap.size() > 1) f.fmap_idx = 0; } Modified: pure/trunk/interpreter.hh =================================================================== --- pure/trunk/interpreter.hh 2008-05-12 06:36:42 UTC (rev 73) +++ pure/trunk/interpreter.hh 2008-05-12 06:42:28 UTC (rev 74) @@ -111,8 +111,14 @@ map<xmap_key,uint32_t > xmap; // info about captured variables list<VarInfo> xtab; - // local function environments - map<int32_t,Env> fmap; + // local function environments; note that there's actually a separate child + // environment for each rule of the parent function (this gets initialized + // to a single empty environment) + vector< map<int32_t,Env> > fmap; + // the current fmap index; this gets updated each time a new rule is added + size_t fmap_idx; + // convenience function to access the current fmap + map<int32_t,Env>& act_fmap() { return fmap[fmap_idx]; } // propagation links for environment variables (pointers to call sites) // e in prop means that there's a call with de Bruijn index prop[e] at e map<Env*,uint8_t> prop; @@ -161,11 +167,11 @@ // default constructor Env() : tag(0), n(0), m(0), l(0), f(0), h(0), fp(0), args(0), envs(0), argv(0), - b(false), local(false), parent(0), refc(0) {} + fmap(1), fmap_idx(0), b(false), local(false), parent(0), refc(0) {} // environment for an anonymous closure with given body x Env(int32_t _tag, uint32_t _n, expr x, bool _b, bool _local = false) : tag(_tag), n(_n), m(0), l(0), f(0), h(0), fp(0), args(n), envs(0), - argv(0), b(_b), local(_local), parent(0), refc(0) + argv(0), fmap(1), fmap_idx(0), b(_b), local(_local), parent(0), refc(0) { if (envstk.empty()) { assert(!local); @@ -179,7 +185,7 @@ // environment for a named closure with given definition info Env(int32_t _tag, const env_info& info, bool _b, bool _local = false) : tag(_tag), n(info.argc), m(0), l(0), f(0), h(0), fp(0), args(n), envs(0), - argv(0), b(_b), local(_local), parent(0), refc(0) + argv(0), fmap(1), fmap_idx(0), b(_b), local(_local), parent(0), refc(0) { if (envstk.empty()) { assert(!local); Modified: pure/trunk/lexer.ll =================================================================== --- pure/trunk/lexer.ll 2008-05-12 06:36:42 UTC (rev 73) +++ pure/trunk/lexer.ll 2008-05-12 06:42:28 UTC (rev 74) @@ -764,9 +764,12 @@ void interpreter::print_defs(ostream& os, const Env& e) { + if (!e.f) return; // not used, probably a shadowed rule if (e.h && e.h != e.f) e.h->print(os); e.f->print(os); - map<int32_t,Env>::const_iterator f; - for (f = e.fmap.begin(); f != e.fmap.end(); f++) - print_defs(os, f->second); + for (size_t i = 0, n = e.fmap.size(); i < n; i++) { + map<int32_t,Env>::const_iterator f; + for (f = e.fmap[i].begin(); f != e.fmap[i].end(); f++) + print_defs(os, f->second); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-13 18:41:46
|
Revision: 79 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=79&view=rev Author: agraef Date: 2008-05-13 11:41:46 -0700 (Tue, 13 May 2008) Log Message: ----------- 64 bit: bigint fixes. Modified Paths: -------------- pure/trunk/interpreter.cc pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-05-13 07:07:01 UTC (rev 78) +++ pure/trunk/interpreter.cc 2008-05-13 18:41:46 UTC (rev 79) @@ -191,7 +191,8 @@ declare_extern((void*)pure_int, "pure_int", "expr*", 1, "int"); declare_extern((void*)pure_bigint, - "pure_bigint", "expr*", 2, "int", "int*"); + "pure_bigint", "expr*", 2, "int", + sizeof(mp_limb_t)==8?"long*":"int*"); declare_extern((void*)pure_double, "pure_double", "expr*", 1, "double"); declare_extern((void*)pure_string_dup, @@ -203,7 +204,7 @@ declare_extern((void*)pure_apply, "pure_apply", "expr*", 2, "expr*", "expr*"); declare_extern((void*)pure_cmp_bigint, - "pure_cmp_bigint", "int", 3, "expr*", "int", "int*"); + "pure_cmp_bigint", "int", 3, "expr*", "int", "long*"); declare_extern((void*)pure_cmp_string, "pure_cmp_string", "int", 2, "expr*", "char*"); @@ -2066,12 +2067,16 @@ return Type::Int8Ty; else if (name == "int") return Type::Int32Ty; + else if (name == "long") + return Type::Int64Ty; else if (name == "double") return Type::DoubleTy; else if (name == "char*") return PointerType::get(Type::Int8Ty, 0); else if (name == "int*") return PointerType::get(Type::Int32Ty, 0); + else if (name == "long*") + return PointerType::get(Type::Int64Ty, 0); else if (name == "double*") return PointerType::get(Type::DoubleTy, 0); else if (name == "expr*") @@ -2097,12 +2102,16 @@ return "char"; else if (type == Type::Int32Ty) return "int"; + else if (type == Type::Int64Ty) + return "long"; else if (type == Type::DoubleTy) return "double"; else if (type == PointerType::get(Type::Int8Ty, 0)) return "char*"; else if (type == PointerType::get(Type::Int32Ty, 0)) return "int*"; + else if (type == PointerType::get(Type::Int64Ty, 0)) + return "long*"; else if (type == PointerType::get(Type::DoubleTy, 0)) return "double*"; else if (type == ExprPtrTy) @@ -3698,31 +3707,30 @@ /* We're a bit lazy in that we only support 32 and 64 bit limbs here, but that should probably work on most if not all systems where GMP is available. */ -#ifdef _LONG_LONG_LIMB - // assume 64 bit limbs - assert(sizeof(mp_limb_t) == 8); - // second arg: array of unsigned long ints (least significant limb first) - size_t n = (size_t)(z->_mp_size>=0 ? z->_mp_size : -z->_mp_size); - vector<Constant*> u(n); - for (size_t i = 0; i < n; i++) u[i] = UInt64(z->_mp_d[i]); - Constant *limbs = ConstantArray::get(ArrayType::get(Type::Int64Ty, n), u); Env& e = act_env(); - GlobalVariable *v = new GlobalVariable - (ArrayType::get(Type::Int64Ty, n), true, - GlobalVariable::InternalLinkage, limbs, "", module); -#else - // assume 32 bit limbs - assert(sizeof(mp_limb_t) == 4); - // second arg: array of unsigned ints (least significant limb first) - size_t n = (size_t)(z->_mp_size>=0 ? z->_mp_size : -z->_mp_size); - vector<Constant*> u(n); - for (size_t i = 0; i < n; i++) u[i] = UInt(z->_mp_d[i]); - Constant *limbs = ConstantArray::get(ArrayType::get(Type::Int32Ty, n), u); - Env& e = act_env(); - GlobalVariable *v = new GlobalVariable - (ArrayType::get(Type::Int32Ty, n), true, - GlobalVariable::InternalLinkage, limbs, "", module); -#endif + GlobalVariable *v; + if (sizeof(mp_limb_t) == 8) { + // 64 bit limbs + // second arg: array of unsigned long ints (least significant limb first) + size_t n = (size_t)(z->_mp_size>=0 ? z->_mp_size : -z->_mp_size); + vector<Constant*> u(n); + for (size_t i = 0; i < n; i++) u[i] = UInt64(z->_mp_d[i]); + Constant *limbs = ConstantArray::get(ArrayType::get(Type::Int64Ty, n), u); + v = new GlobalVariable + (ArrayType::get(Type::Int64Ty, n), true, + GlobalVariable::InternalLinkage, limbs, "", module); + } else { + // assume 32 bit limbs + assert(sizeof(mp_limb_t) == 4); + // second arg: array of unsigned ints (least significant limb first) + size_t n = (size_t)(z->_mp_size>=0 ? z->_mp_size : -z->_mp_size); + vector<Constant*> u(n); + for (size_t i = 0; i < n; i++) u[i] = UInt(z->_mp_d[i]); + Constant *limbs = ConstantArray::get(ArrayType::get(Type::Int32Ty, n), u); + v = new GlobalVariable + (ArrayType::get(Type::Int32Ty, n), true, + GlobalVariable::InternalLinkage, limbs, "", module); + } // "cast" the int array to a int* ptr = e.CreateGEP(v, Zero, Zero); } Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-05-13 07:07:01 UTC (rev 78) +++ pure/trunk/runtime.cc 2008-05-13 18:41:46 UTC (rev 79) @@ -714,27 +714,25 @@ case EXPR::STR: return pure_pointer(x->data.s); case EXPR::INT: return pure_pointer((void*)x->data.i); case EXPR::BIGINT: -#ifdef _LONG_LONG_LIMB - return pure_pointer((void*)x->data.z->_mp_d[0]); -#else - if (sizeof(void*) == 4) + if (sizeof(mp_limb_t) == 8) + return pure_pointer((void*)x->data.z->_mp_d[0]); + else if (sizeof(void*) == 4) return pure_pointer((void*)mpz_get_ui(x->data.z)); else { uint64_t u = x->data.z->_mp_d[0]+(((uint64_t)x->data.z->_mp_d[1])<<32); return pure_pointer((void*)u); } -#endif default: return 0; } } static pure_expr *pointer_to_bigint(void *p) { -#ifdef _LONG_LONG_LIMB - // In this case the pointer value ought to fit into a single limb. - limb_t u[1] = { (uint64_t)p }; - return pure_bigint(1, u); -#else + if (sizeof(mp_limb_t) == 8) { + // In this case the pointer value ought to fit into a single limb. + limb_t u[1] = { (uint64_t)p }; + return pure_bigint(1, u); + } // 4 byte limbs. if (sizeof(void*) == 4) { // 4 byte pointers. Note that we still cast to 64 bit first, since @@ -747,7 +745,6 @@ limb_t u[2] = { (uint32_t)(uint64_t)p, (uint32_t)(((uint64_t)p)>>32) }; return pure_bigint(2, u); } -#endif } extern "C" Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-05-13 07:07:01 UTC (rev 78) +++ pure/trunk/runtime.h 2008-05-13 18:41:46 UTC (rev 79) @@ -12,11 +12,7 @@ #endif /* Our "limb" type. Used to pass bigint constants to the runtime. */ -#ifdef _LONG_LONG_LIMB // try to match what GMP uses -typedef uint64_t limb_t; -#else -typedef uint32_t limb_t; -#endif +typedef mp_limb_t limb_t; /* Closure data. This is a bit on the heavy side, so expressions which need it (i.e., functions) refer to this extra data via an allocated pointer. */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-14 09:06:13
|
Revision: 82 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=82&view=rev Author: agraef Date: 2008-05-14 02:06:19 -0700 (Wed, 14 May 2008) Log Message: ----------- Enable -O in the default build, update docs. Modified Paths: -------------- pure/trunk/INSTALL pure/trunk/Makefile pure/trunk/TODO Modified: pure/trunk/INSTALL =================================================================== --- pure/trunk/INSTALL 2008-05-13 22:03:15 UTC (rev 81) +++ pure/trunk/INSTALL 2008-05-14 09:06:19 UTC (rev 82) @@ -69,27 +69,27 @@ page. See "Downloads" on the Pure website for a quick link to the download section. -STEP 5. Build and install the release version of Pure as follows: +STEP 5. Build and install Pure as follows (x.y denotes the current Pure +version number, 0.3 at the time of this writing): $ cd pure-x.y -$ make build=release +$ make $ sudo make install -Here, x.y denotes the current Pure version number (0.2 at the time of this -writing). If you want to install the debugging-enabled version, run just -'make' instead of 'make build=release'. +Please note that compiling Pure takes a while (especially runtime.cc), so +please have some patience. -To check that Pure is working correctly on your computer, also run: +After the build is complete, you can check that Pure is working correctly on +your computer, as follows: $ make check -STEP 6. The Pure interpreter should be ready to go now. (On some systems you -might first have to run ldconfig to update the dynamic linker cache.) +STEP 6. The Pure interpreter should be ready to go now. Run Pure interactively as: $ pure -Pure 0.1 Copyright (c) 2008 by Albert Graef +Pure 0.3 Copyright (c) 2008 by Albert Graef This program is free software distributed under the GNU Public License (GPL V3 or later). Please see the COPYING file for details. Loaded prelude from /usr/local/lib/pure/prelude.pure. @@ -129,8 +129,7 @@ $ svn co http://pure-lang.svn.sourceforge.net/svnroot/pure-lang pure-lang -STEP 5': Build and install the debugging-enabled version (of course you can -also build the release version, as described in step 5 above): +STEP 5': Build and install Pure: $ cd pure-lang/pure/trunk $ make @@ -168,17 +167,24 @@ will run the Pure interpreter with that setting in Bourne-compatible shells. -For the release version, you should build the interpreter as follows: +As of Pure 0.3, the standard build now also includes basic optimization (-O). +This build should be ok for most purposes, and has the advantage that it does +additional runtime checks which may give more useful diagnostics if there is +anything wrong with the interpreter. +However, you can also build a "release" version of the interpreter, as +follows: + $ make build=release -This disables all runtime checks and debugging information in the interpreter. -(Don't worry, your Pure programs will still be executed "safely" and shouldn't -segfault unless you run out of memory or there's a bug in the interpreter.) -The 'release' build gives you *much* faster execution times (factor of 2 -compared to the default flags on my Linux system running gcc 4.1, YMMV). It -also takes a *long* time to compile runtime.cc, but it's really worth the -wait, so please be patient. ;-) +This disables all runtime checks and debugging information in the interpreter +and also uses a higher level of optimization. (Don't worry, your Pure programs +will still be executed "safely" and shouldn't segfault unless you run out of +memory or stack space, or there's a bug in the interpreter.) The 'release' +build will usually give you faster execution times, but the differences aren't +really that big anymore (5% compared to the default flags on my Linux system +running gcc 4.1, YMMV), so you are encouraged to use the default build unless +performance is really critical. Please also have a look at the Makefile for details on the build and installation process and other available targets and options. @@ -190,25 +196,42 @@ ALL PLATFORMS --- --------- -Compiling the release version (make build=release) with gcc with all warnings +Compiling the release version (make build=release) using gcc with all warnings turned on (which is the default) will give you the warning "dereferencing type-punned pointer will break strict-aliasing rules" at some point in util.cc. This is harmless and can be ignored. +If your Pure program runs out of stack space, the interpreter will segfault. +This is *not* a bug, it happens because runtime stack checks are disabled by +default for performance reasons. You can enable stack checks by setting the +PURE_STACK environment variable accordingly; see the pure(1) manual page for +details. The interpreter will then generate orderly "stack fault" exceptions +in case of a stack overflow. + 64 BIT SYSTEMS -- --- ------- -Please note that at the time of this writing only the release build of Pure -(make build=release) appears to work on (some) 64 bit systems. We're working -on these issues right now, so please stay tuned. +In general, 64 bit systems are supported by Pure. However, if you use your own +custom set of build flags with gcc, make sure that you have at least -O +enabled when compiling runtime.cc. There's a bug (seen at least on some 64 bit +Linux versions) which causes wrong code to be executed by the Pure interpreter +if you don't do this. The default and release builds should work fine. 32 bit +builds also seem to be unaffected. +We haven't been able to pin this one down yet, so if you have to use custom +build options and run into this bug (easily verified because most of the tests +run by 'make check' will fail), then for the time being please use the +workaround described above. Also please watch the mailing list for updates on +this issue. + LINUX ----- Linux is the primary development platform for this software, and the sources -should build out of the box on all recent Linux distributions. (Some -unresolved issues have been reported with Ubuntu on PowerPC, though, see the -mailing list for details and updates on this.) +should build out of the box on all recent Linux distributions. Please see +above for unresolved issues on 64 bit Linux systems and how to work around +them. Also, some issues have been reported with Ubuntu (32 bit) on PowerPC, +see the mailing list for details and updates on this. MAC OSX --- --- Modified: pure/trunk/Makefile =================================================================== --- pure/trunk/Makefile 2008-05-13 22:03:15 UTC (rev 81) +++ pure/trunk/Makefile 2008-05-14 09:06:19 UTC (rev 82) @@ -39,11 +39,18 @@ # 'debug' adds more debugging output (useful to debug the interpreter). # 'release' optimizes for execution speed (release version). -# The latter disables all runtime checks and debugging information and gives -# you *much* faster execution times (factor of 2 compared to the default flags -# on my Linux system running gcc 4.1, YMMV). It also takes a *long* time to -# compile runtime.cc, so be patient. ;-) +# The 'default' build compiles with a moderate optimization level and runtime +# checks as well as debugging information, and should be ok for most +# installations, unless you really need/want the best performance in which +# case the release build should be used. The latter gives me a 5% speedup on +# my single-cpu AMD system running Linux and gcc 4.1, YMMV. The 'debug' build +# adds a lot of extra debugging output both in the interpreter and the +# generated code, and is really only useful for maintainers debugging the +# interpreter. +# Note that both the 'default' and the 'release' build take quite a while to +# compile (especially runtime.cc), so please be patient. ;-) + # To build with a given profile, just say 'make build=<profile>', e.g.: 'make # build=release'. (This option only has to be specified at build time, not for # installation or any other targets except 'all'.) @@ -57,8 +64,8 @@ # with the options if you're using a different compiler. ifeq ($(build),default) -CXXFLAGS = -g -Wall $(LLVM_FLAGS) -CFLAGS = -g -Wall +CXXFLAGS = -g -O -Wall $(LLVM_FLAGS) +CFLAGS = -g -O -Wall else ifeq ($(build),debug) CXXFLAGS = -g -Wall -DDEBUG=2 $(LLVM_FLAGS) @@ -68,8 +75,8 @@ CXXFLAGS = -O3 -DNDEBUG -Wall $(LLVM_FLAGS) CFLAGS = -O3 -DNDEBUG -Wall else -CXXFLAGS = -g -Wall $(LLVM_FLAGS) -CFLAGS = -g -Wall +CXXFLAGS = -g -O -Wall $(LLVM_FLAGS) +CFLAGS = -g -O -Wall .PHONY: warn warn: all @echo "WARNING: Invalid build profile '$(build)'." Modified: pure/trunk/TODO =================================================================== --- pure/trunk/TODO 2008-05-13 22:03:15 UTC (rev 81) +++ pure/trunk/TODO 2008-05-14 09:06:19 UTC (rev 82) @@ -2,11 +2,11 @@ TODO ==== -While the interpreter already starts becoming useful, there's still a lot of +While the interpreter is already useful as it is, there's still a lot of things that remain to be done. Most important items, in no particular order: -- Check 64 bit compilation. The code should be 64 bit clean already, but this - assertion still needs to be tested. Feedback appreciated. +- Resolve any remaining issues on 64 bit systems. See the INSTALL file for + details. - Symbolic (Pure-level) debugger, profiler. The necessary hooks are mostly there, we just need to add a few runtime calls in the generated code. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-14 20:36:24
|
Revision: 87 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=87&view=rev Author: agraef Date: 2008-05-14 13:36:31 -0700 (Wed, 14 May 2008) Log Message: ----------- Comment changes. Modified Paths: -------------- pure/trunk/INSTALL pure/trunk/Makefile Modified: pure/trunk/INSTALL =================================================================== --- pure/trunk/INSTALL 2008-05-14 20:13:10 UTC (rev 86) +++ pure/trunk/INSTALL 2008-05-14 20:36:31 UTC (rev 87) @@ -184,9 +184,9 @@ This disables all runtime checks and debugging information in the interpreter and also uses a higher level of optimization. The 'release' build will usually give you faster execution times, but the differences aren't really that big -anymore (5% compared to the default flags on my Linux system running gcc 4.1, -YMMV), so you are encouraged to use the 'default' build unless performance is -really critical. +anymore (5-10% compared to the default flags on my Linux system running gcc +4.1, YMMV), so you are encouraged to use the 'default' build unless +performance is really critical. You can also do a 'debug' build as follows: Modified: pure/trunk/Makefile =================================================================== --- pure/trunk/Makefile 2008-05-14 20:13:10 UTC (rev 86) +++ pure/trunk/Makefile 2008-05-14 20:36:31 UTC (rev 87) @@ -48,8 +48,8 @@ # The 'release' build disables all runtime checks and debugging information # and compiles with additional optimizations which makes programs go a little -# faster (some 5% on a single-cpu AMD system running Linux and gcc 4.1, YMMV); -# use this if performance is critical. +# faster (some 5-10% on a single-cpu AMD system running Linux and gcc 4.1, +# YMMV); use this if performance is critical. # The 'debug' build is like 'default' but without any optimizations; it builds # faster than 'default', but runs *much* slower, and isn't recommended for This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-16 16:37:37
|
Revision: 89 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=89&view=rev Author: agraef Date: 2008-05-16 09:37:31 -0700 (Fri, 16 May 2008) Log Message: ----------- Fixed C compilation problems with runtime.h. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/runtime.h Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-16 08:46:10 UTC (rev 88) +++ pure/trunk/ChangeLog 2008-05-16 16:37:31 UTC (rev 89) @@ -1,3 +1,8 @@ +2008-05-16 Albert Graef <Dr....@t-...> + + * runtime.h: Fix compilation problems when header gets included + from C. + 2008-05-14 Albert Graef <Dr....@t-...> * funcall.h: Reduce maximum number of function parameters to Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-05-16 08:46:10 UTC (rev 88) +++ pure/trunk/runtime.h 2008-05-16 16:37:31 UTC (rev 89) @@ -4,6 +4,7 @@ /* The Pure runtime interface. */ #include <stdint.h> +#include <stdbool.h> #include <setjmp.h> #include <gmp.h> @@ -124,9 +125,12 @@ /* Run a Pure function and catch exceptions. If everything goes normal, pure_invoke returns the return value of the executed function. Otherwise it returns 0 and sets e to the exception value, as given by pure_throw(). - XXXFIXME: Only supports parameterless functions right now. */ + XXXFIXME: This only works with C++ and only supports parameterless + functions right now. */ +#ifdef __cplusplus pure_expr *pure_invoke(void *f, pure_expr*& e); +#endif /* Count a new reference to an expression. This should be called whenever you want to store an expression somewhere, in order to prevent it from being This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-17 05:16:01
|
Revision: 90 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=90&view=rev Author: agraef Date: 2008-05-16 22:16:09 -0700 (Fri, 16 May 2008) Log Message: ----------- Overhaul of internal type system, fix up pure_expr data structure so that data fields are always aligned on 8 byte boundaries. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc pure/trunk/interpreter.hh pure/trunk/runtime.h Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-16 16:37:31 UTC (rev 89) +++ pure/trunk/ChangeLog 2008-05-17 05:16:09 UTC (rev 90) @@ -1,3 +1,26 @@ +2008-05-17 Albert Graef <Dr....@t-...> + + * interpreter.cc, runtime.h: Reorganize pure_expr data structure + so that the data fields are *always* aligned on 8 byte boundaries. + This should now also work on 32 bit architectures where doubles + are aligned on 8 byte boundaries, such as Linux on 32 bit PPC. + Reported by Tim Haynes. + + * interpreter.cc: Fixed some case labels in switch instructions + which should be signed rather than unsigned values. Also made + void* a pointer to a dummy struct in LLVM IR, so that it can be + distinguished from all other pointer types, and added support for + short (16 bit) and long (64 bit) integer types (as well as the + corresponding pointer types) in the C interface. + + Please note that the typename 'long' *always* denotes signed 64 + bit integers in Pure's extern declarations, even if the C 'long' + type is actually 32 bit (as it usually is even on most 64 bit + systems). + + FIXME: At present 'long' is still converted to/from Pure (32 bit) + ints only, marshalling from/to Pure bigints is not supported yet. + 2008-05-16 Albert Graef <Dr....@t-...> * runtime.h: Fix compilation problems when header gets included Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-05-16 16:37:31 UTC (rev 89) +++ pure/trunk/interpreter.cc 2008-05-17 05:16:09 UTC (rev 90) @@ -89,11 +89,17 @@ // systems which do not allow the program to dlopen itself. JIT->InstallLazyFunctionCreator(resolve_external); - // Generic pointer type. LLVM doesn't like void*, so we use short* instead. - // (This is a bit of a kludge. We'd rather use char*, but we need to keep - // char* and void* apart, and short* isn't used for anything else here.) + // Generic pointer type. LLVM doesn't like void*, so we use a pointer to a + // dummy struct instead. (This is a bit of a kludge. We'd rather use char*, + // as suggested in the LLVM documentation, but we need to keep char* and + // void* apart.) + { + std::vector<const Type*> elts; + VoidPtrTy = PointerType::get(StructType::get(elts), 0); + } - VoidPtrTy = PointerType::get(Type::Int16Ty, 0); + // Char pointer type. + CharPtrTy = PointerType::get(Type::Int8Ty, 0); // Create the expr struct type. @@ -101,11 +107,12 @@ structure as defined by the runtime. In order to perform certain operations like built-in arithmetic, conditionals and expression matching in an efficient manner, we need to know about the layout of the relevant - fields in memory. The runtime will add additional variants and fields of + fields in memory. The runtime may add additional variants and fields of its own. The declarations below correspond to the following C struct: struct expr { int32_t tag; // see expr.hh, determines the variant + uint32_t refc; // reference counter union { struct { // application struct expr *x, *y; @@ -127,6 +134,7 @@ PATypeHolder StructTy = OpaqueType::get(); std::vector<const Type*> elts; elts.push_back(Type::Int32Ty); + elts.push_back(Type::Int32Ty); elts.push_back(PointerType::get(StructTy, 0)); elts.push_back(PointerType::get(StructTy, 0)); ExprTy = StructType::get(elts); @@ -134,20 +142,18 @@ ExprTy = cast<StructType>(StructTy.get()); module->addTypeName("struct.expr", ExprTy); } - // Other variants. Note that on 64 bit systems we have to add a dummy field - // so that the following value field is aligned properly. { std::vector<const Type*> elts; elts.push_back(Type::Int32Ty); - if (sizeof(void*)==8) elts.push_back(Type::Int32Ty); // dummy elts.push_back(Type::Int32Ty); + elts.push_back(Type::Int32Ty); IntExprTy = StructType::get(elts); module->addTypeName("struct.intexpr", IntExprTy); } { std::vector<const Type*> elts; elts.push_back(Type::Int32Ty); - if (sizeof(void*)==8) elts.push_back(Type::Int32Ty); // dummy + elts.push_back(Type::Int32Ty); elts.push_back(Type::DoubleTy); DblExprTy = StructType::get(elts); module->addTypeName("struct.dblexpr", DblExprTy); @@ -155,15 +161,15 @@ { std::vector<const Type*> elts; elts.push_back(Type::Int32Ty); - if (sizeof(void*)==8) elts.push_back(Type::Int32Ty); // dummy - elts.push_back(PointerType::get(Type::Int8Ty, 0)); + elts.push_back(Type::Int32Ty); + elts.push_back(CharPtrTy); StrExprTy = StructType::get(elts); module->addTypeName("struct.strexpr", StrExprTy); } { std::vector<const Type*> elts; elts.push_back(Type::Int32Ty); - if (sizeof(void*)==8) elts.push_back(Type::Int32Ty); // dummy + elts.push_back(Type::Int32Ty); elts.push_back(VoidPtrTy); PtrExprTy = StructType::get(elts); module->addTypeName("struct.ptrexpr", PtrExprTy); @@ -1456,7 +1462,11 @@ #define Zero UInt(0) #define One UInt(1) #define Two UInt(2) -#define ValFldIndex (sizeof(void*)==8?Two:One) +#define Three UInt(3) +#define RefcFldIndex One +#define ValFldIndex Two +#define ValFld2Index Three +#define SubFldIndex(i) UInt(i+2) #define NullExprPtr ConstantPointerNull::get(ExprPtrTy) #define NullExprPtrPtr ConstantPointerNull::get(ExprPtrPtrTy) @@ -2066,6 +2076,8 @@ return Type::Int1Ty; else if (name == "char") return Type::Int8Ty; + else if (name == "short") + return Type::Int16Ty; else if (name == "int") return Type::Int32Ty; else if (name == "long") @@ -2073,7 +2085,9 @@ else if (name == "double") return Type::DoubleTy; else if (name == "char*") - return PointerType::get(Type::Int8Ty, 0); + return CharPtrTy; + else if (name == "short*") + return PointerType::get(Type::Int16Ty, 0); else if (name == "int*") return PointerType::get(Type::Int32Ty, 0); else if (name == "long*") @@ -2101,14 +2115,18 @@ return "bool"; else if (type == Type::Int8Ty) return "char"; + else if (type == Type::Int16Ty) + return "short"; else if (type == Type::Int32Ty) return "int"; else if (type == Type::Int64Ty) return "long"; else if (type == Type::DoubleTy) return "double"; - else if (type == PointerType::get(Type::Int8Ty, 0)) + else if (type == CharPtrTy) return "char*"; + else if (type == PointerType::get(Type::Int16Ty, 0)) + return "short*"; else if (type == PointerType::get(Type::Int32Ty, 0)) return "int*"; else if (type == PointerType::get(Type::Int64Ty, 0)) @@ -2222,7 +2240,7 @@ // In Pure, we allow void* to be passed for a char*, to bypass the // automatic marshalling from Pure to C strings. Oh well. ok = gt->getParamType(i)==argt[i] || - gt->getParamType(i)==PointerType::get(Type::Int8Ty, 0) && + gt->getParamType(i)==CharPtrTy && argt[i] == VoidPtrTy; } if (!ok) { @@ -2317,6 +2335,18 @@ idx[1] = ValFldIndex; Value *iv = b.CreateLoad(b.CreateGEP(pv, idx, idx+2), "intval"); unboxed[i] = b.CreateTrunc(iv, Type::Int8Ty); + } else if (argt[i] == Type::Int16Ty) { + BasicBlock *okbb = new BasicBlock("ok"); + Value *idx[2] = { Zero, Zero }; + Value *tagv = b.CreateLoad(b.CreateGEP(x, idx, idx+2), "tag"); + b.CreateCondBr + (b.CreateICmpEQ(tagv, SInt(EXPR::INT), "cmp"), okbb, failedbb); + f->getBasicBlockList().push_back(okbb); + b.SetInsertPoint(okbb); + Value *pv = b.CreateBitCast(x, IntExprPtrTy, "intexpr"); + idx[1] = ValFldIndex; + Value *iv = b.CreateLoad(b.CreateGEP(pv, idx, idx+2), "intval"); + unboxed[i] = b.CreateTrunc(iv, Type::Int16Ty); } else if (argt[i] == Type::Int32Ty) { BasicBlock *okbb = new BasicBlock("ok"); Value *idx[2] = { Zero, Zero }; @@ -2353,7 +2383,7 @@ idx[1] = ValFldIndex; Value *dv = b.CreateLoad(b.CreateGEP(pv, idx, idx+2), "dblval"); unboxed[i] = dv; - } else if (argt[i] == PointerType::get(Type::Int8Ty, 0)) { + } else if (argt[i] == CharPtrTy) { BasicBlock *okbb = new BasicBlock("ok"); Value *idx[2] = { Zero, Zero }; Value *tagv = b.CreateLoad(b.CreateGEP(x, idx, idx+2), "tag"); @@ -2363,7 +2393,10 @@ b.SetInsertPoint(okbb); Value *sv = b.CreateCall(module->getFunction("pure_get_cstring"), x); unboxed[i] = sv; temps = true; - } else if (argt[i] == PointerType::get(Type::Int32Ty, 0)) { + } else if (argt[i] == PointerType::get(Type::Int16Ty, 0) || + argt[i] == PointerType::get(Type::Int32Ty, 0) || + argt[i] == PointerType::get(Type::Int64Ty, 0) || + argt[i] == PointerType::get(Type::DoubleTy, 0)) { BasicBlock *okbb = new BasicBlock("ok"); Value *idx[2] = { Zero, Zero }; Value *tagv = b.CreateLoad(b.CreateGEP(x, idx, idx+2), "tag"); @@ -2375,18 +2408,6 @@ idx[1] = ValFldIndex; Value *ptrv = b.CreateLoad(b.CreateGEP(pv, idx, idx+2), "ptrval"); unboxed[i] = b.CreateBitCast(ptrv, argt[i]); - } else if (argt[i] == PointerType::get(Type::DoubleTy, 0)) { - BasicBlock *okbb = new BasicBlock("ok"); - Value *idx[2] = { Zero, Zero }; - Value *tagv = b.CreateLoad(b.CreateGEP(x, idx, idx+2), "tag"); - b.CreateCondBr - (b.CreateICmpEQ(tagv, SInt(EXPR::PTR), "cmp"), okbb, failedbb); - f->getBasicBlockList().push_back(okbb); - b.SetInsertPoint(okbb); - Value *pv = b.CreateBitCast(x, PtrExprPtrTy, "ptrexpr"); - idx[1] = ValFldIndex; - Value *ptrv = b.CreateLoad(b.CreateGEP(pv, idx, idx+2), "ptrval"); - unboxed[i] = b.CreateBitCast(ptrv, argt[i]); } else if (argt[i] == ExprPtrTy) { // passed through unboxed[i] = x; @@ -2425,12 +2446,12 @@ phi->addIncoming(ptrv, ptrbb); phi->addIncoming(mpzv, mpzbb); unboxed[i] = phi; - if (gt->getParamType(i)==PointerType::get(Type::Int8Ty, 0)) + if (gt->getParamType(i)==CharPtrTy) // An external builtin already has this parameter declared as char*. // We allow void* to be passed anyway, so just cast it to char* to // make the LLVM typechecker happy. unboxed[i] = b.CreateBitCast - (unboxed[i], PointerType::get(Type::Int8Ty, 0)); + (unboxed[i], CharPtrTy); } else assert(0 && "invalid C type"); } @@ -2449,6 +2470,9 @@ // char treated as an unsigned integer here u = b.CreateCall(module->getFunction("pure_int"), b.CreateZExt(u, Type::Int32Ty)); + else if (type == Type::Int16Ty) + u = b.CreateCall(module->getFunction("pure_int"), + b.CreateSExt(u, Type::Int32Ty)); else if (type == Type::Int32Ty) u = b.CreateCall(module->getFunction("pure_int"), u); else if (type == Type::Int64Ty) @@ -2456,14 +2480,14 @@ b.CreateTrunc(u, Type::Int32Ty)); else if (type == Type::DoubleTy) u = b.CreateCall(module->getFunction("pure_double"), u); - else if (type == PointerType::get(Type::Int8Ty, 0)) + else if (type == CharPtrTy) u = b.CreateCall(module->getFunction("pure_cstring_dup"), u); - else if (type == PointerType::get(Type::Int32Ty, 0)) + else if (type == PointerType::get(Type::Int16Ty, 0) || + type == PointerType::get(Type::Int32Ty, 0) || + type == PointerType::get(Type::Int64Ty, 0) || + type == PointerType::get(Type::DoubleTy, 0)) u = b.CreateCall(module->getFunction("pure_pointer"), b.CreateBitCast(u, VoidPtrTy)); - else if (type == PointerType::get(Type::DoubleTy, 0)) - u = b.CreateCall(module->getFunction("pure_pointer"), - b.CreateBitCast(u, VoidPtrTy)); else if (type == ExprPtrTy) { // check that we actually got a valid pointer; otherwise the call failed BasicBlock *okbb = new BasicBlock("ok"); @@ -2603,7 +2627,7 @@ path& p = *info.p; size_t n = p.len(); for (size_t i = 0; i < n; i++) - x = f.CreateLoadGEP(x, Zero, UInt(p[i]+1), mklabel("x", i, p[i]+1)); + x = f.CreateLoadGEP(x, Zero, SubFldIndex(p[i]), mklabel("x", i, p[i]+1)); // store the value in a global variable of the same name const symbol& sym = symtab.sym(tag); GlobalVar& v = globalvars[tag]; @@ -3481,7 +3505,7 @@ Value *v = e.args[k]; size_t n = p.len(); for (size_t i = 0; i < n; i++) - v = e.CreateLoadGEP(v, Zero, UInt(p[i]+1), mklabel("x", i, p[i]+1)); + v = e.CreateLoadGEP(v, Zero, SubFldIndex(p[i]), mklabel("x", i, p[i]+1)); return v; } @@ -4180,12 +4204,12 @@ // next match the first subterm... f.f->getBasicBlockList().push_back(ok1bb); f.builder.SetInsertPoint(ok1bb); - Value *x1 = f.CreateLoadGEP(x, Zero, One, "x1"); + Value *x1 = f.CreateLoadGEP(x, Zero, ValFldIndex, "x1"); simple_match(x1, s, ok2bb, failedbb); // and finally the second subterm... f.f->getBasicBlockList().push_back(ok2bb); f.builder.SetInsertPoint(ok2bb); - Value *x2 = f.CreateLoadGEP(x, Zero, Two, "x2"); + Value *x2 = f.CreateLoadGEP(x, Zero, ValFld2Index, "x2"); simple_match(x2, s, matchedbb, failedbb); break; } @@ -4258,27 +4282,27 @@ // helper macros to set up for the next state -#define next_state(t) \ - do { \ - state *s = t->st; \ - list<Value*> ys = xs; ys.pop_front(); \ - if (ys.empty()) \ - try_rules(pm, s, failedbb, reduced); \ - else \ - complex_match(pm, ys, s, failedbb, reduced); \ +#define next_state(t) \ + do { \ + state *s = t->st; \ + list<Value*> ys = xs; ys.pop_front(); \ + if (ys.empty()) \ + try_rules(pm, s, failedbb, reduced); \ + else \ + complex_match(pm, ys, s, failedbb, reduced); \ } while (0) // same as above, but handles the case of an application where we recurse into // subterms -#define next_state2(t) \ - do { \ - state *s = t->st; \ - list<Value*> ys = xs; ys.pop_front(); \ - Value *x1 = f.CreateLoadGEP(x, Zero, One, "x1"); \ - Value *x2 = f.CreateLoadGEP(x, Zero, Two, "x2"); \ - ys.push_front(x2); ys.push_front(x1); \ - complex_match(pm, ys, s, failedbb, reduced); \ +#define next_state2(t) \ + do { \ + state *s = t->st; \ + list<Value*> ys = xs; ys.pop_front(); \ + Value *x1 = f.CreateLoadGEP(x, Zero, ValFldIndex, "x1"); \ + Value *x2 = f.CreateLoadGEP(x, Zero, ValFld2Index, "x2"); \ + ys.push_front(x2); ys.push_front(x1); \ + complex_match(pm, ys, s, failedbb, reduced); \ } while (0) /* This is the core of the decision tree construction algorithm. It emits code @@ -4352,7 +4376,7 @@ assert(!tmap[t->tag].bb); tmap[t->tag].bb = bb; tmap[t->tag].t = &*t; - sw->addCase(UInt(t->tag), bb); + sw->addCase(SInt(t->tag), bb); } else { // transition on a constant, add it to the corresponding list tmap[t->tag].tlist.push_back(trans_info(&*t, bb)); @@ -4361,7 +4385,7 @@ // target to the outer switch tmap[t->tag].bb = new BasicBlock(mklabel("begin.state", s->s, -t->tag)); - sw->addCase(UInt(t->tag), tmap[t->tag].bb); + sw->addCase(SInt(t->tag), tmap[t->tag].bb); } } } @@ -4458,7 +4482,7 @@ for (t = t1, i = 0; t != s->tr.end() && t->tag == EXPR::VAR; t++, i++) { vtransbb.push_back (new BasicBlock(mklabel("trans.state", s->s, t->st->s))); - sw->addCase(UInt(t->ttag), vtransbb[i]); + sw->addCase(SInt(t->ttag), vtransbb[i]); } // now handle the transitions on the different type tags for (t = t1, i = 0; t != s->tr.end() && t->tag == EXPR::VAR; t++, i++) { Modified: pure/trunk/interpreter.hh =================================================================== --- pure/trunk/interpreter.hh 2008-05-16 16:37:31 UTC (rev 89) +++ pure/trunk/interpreter.hh 2008-05-17 05:16:09 UTC (rev 90) @@ -388,7 +388,7 @@ llvm::StructType *ExprTy, *IntExprTy, *DblExprTy, *StrExprTy, *PtrExprTy; llvm::PointerType *ExprPtrTy, *ExprPtrPtrTy; llvm::PointerType *IntExprPtrTy, *DblExprPtrTy, *StrExprPtrTy, *PtrExprPtrTy; - llvm::PointerType *VoidPtrTy; + llvm::PointerType *VoidPtrTy, *CharPtrTy; const llvm::Type *named_type(string name); const char *type_name(const llvm::Type *type); map<int32_t,GlobalVar> globalvars; Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-05-16 16:37:31 UTC (rev 89) +++ pure/trunk/runtime.h 2008-05-17 05:16:09 UTC (rev 90) @@ -32,6 +32,7 @@ /* Public fields, these *must* be layed out exactly as indicated. The JIT depends on it! */ int32_t tag; // type tag or symbol, see expr.hh for possible values + uint32_t refc; // reference counter union { struct _pure_expr *x[2]; // application arguments (EXPR::APP) int32_t i; // integer (EXPR::INT) @@ -42,7 +43,6 @@ pure_closure *clos; // closure (0 if none) } data; /* Internal fields (DO NOT TOUCH). The JIT doesn't care about these. */ - uint32_t refc; // reference counter struct _pure_expr *xp; // freelist pointer } pure_expr; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-17 06:39:22
|
Revision: 91 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=91&view=rev Author: agraef Date: 2008-05-16 23:39:30 -0700 (Fri, 16 May 2008) Log Message: ----------- Fixed error messages for failed global variable bindings (let). Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-17 05:16:09 UTC (rev 90) +++ pure/trunk/ChangeLog 2008-05-17 06:39:30 UTC (rev 91) @@ -1,5 +1,7 @@ 2008-05-17 Albert Graef <Dr....@t-...> + * interpreter.cc (define): Fixed error messages. + * interpreter.cc, runtime.h: Reorganize pure_expr data structure so that the data fields are *always* aligned on 8 byte boundaries. This should now also work on 32 bit architectures where doubles Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-05-17 05:16:09 UTC (rev 90) +++ pure/trunk/interpreter.cc 2008-05-17 06:39:30 UTC (rev 91) @@ -744,14 +744,20 @@ void interpreter::define(rule *r) { last = expr(); - pure_expr *res = defn(r->lhs, r->rhs); + pure_expr *e, *res = defn(r->lhs, r->rhs, e); + if ((verbose&verbosity::defs) != 0) + cout << "let " << r->lhs << " = " << r->rhs << ";\n"; if (!res) { ostringstream msg; - msg << "failed match: " << r->lhs << " = " << r->rhs; + if (e) { + msg << "unhandled exception '" << e << "' while evaluating '" + << "let " << r->lhs << " = " << r->rhs << "'"; + pure_freenew(e); + } else + msg << "failed match while evaluating '" + << "let " << r->lhs << " = " << r->rhs << "'"; throw err(msg.str()); } - if ((verbose&verbosity::defs) != 0) - cout << "let " << r->lhs << " = " << r->rhs << ";\n"; delete r; pure_freenew(res); if (interactive && stats) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-17 19:45:21
|
Revision: 94 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=94&view=rev Author: agraef Date: 2008-05-17 12:45:28 -0700 (Sat, 17 May 2008) Log Message: ----------- Fixed broken pure_free_internal routine. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/runtime.cc Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-17 12:43:37 UTC (rev 93) +++ pure/trunk/ChangeLog 2008-05-17 19:45:28 UTC (rev 94) @@ -1,5 +1,8 @@ 2008-05-17 Albert Graef <Dr....@t-...> + * runtime.cc (pure_free_internal): Fixed a glitch which was + causing big memleaks. Reported by Libor Spacek. + * interpreter.cc (define): Fixed error messages. * interpreter.cc, runtime.h: Reorganize pure_expr data structure @@ -18,11 +21,10 @@ Please note that the typename 'long' *always* denotes signed 64 bit integers in Pure's extern declarations, even if the C 'long' type is actually 32 bit (as it usually is even on most 64 bit - systems). + systems). Also note that at present 'long' is still converted + to/from Pure (32 bit) ints only, marshalling from/to Pure bigints + is not supported yet. - FIXME: At present 'long' is still converted to/from Pure (32 bit) - ints only, marshalling from/to Pure bigints is not supported yet. - 2008-05-16 Albert Graef <Dr....@t-...> * runtime.h: Fix compilation problems when header gets included Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-05-17 12:43:37 UTC (rev 93) +++ pure/trunk/runtime.cc 2008-05-17 19:45:28 UTC (rev 94) @@ -22,21 +22,37 @@ // Debug expression allocations. #if DEBUG>2 set<pure_expr*> mem_allocations; -#define MEMDEBUG_NEW(x) mem_allocations.insert(x); \ +#if DEBUG>9 +#define MEMDEBUG_NEW(x) mem_allocations.insert(x); \ cerr << "NEW: " << (void*)x << ": " << x << endl; -#define MEMDEBUG_FREE(x) mem_allocations.erase(x); \ +#define MEMDEBUG_FREE(x) mem_allocations.erase(x); \ cerr << "FREE: " << (void*)x << ": " << x << endl; +#else +#define MEMDEBUG_NEW(x) mem_allocations.insert(x); +#define MEMDEBUG_FREE(x) mem_allocations.erase(x); +#endif #define MEMDEBUG_INIT mem_allocations.clear(); -#define MEMDEBUG_SUMMARY cerr << "SUMMARY:\n"; \ - for (set<pure_expr*>::iterator x = mem_allocations.begin(); \ - x != mem_allocations.end(); x++) \ - cerr << (void*)(*x) << ": " << (*x) << endl; \ - mem_allocations.clear(); +#define MEMDEBUG_SUMMARY(ret) mem_mark(ret); \ + if (!mem_allocations.empty()) { cerr << "POSSIBLE LEAKS:\n"; \ + for (set<pure_expr*>::iterator x = mem_allocations.begin(); \ + x != mem_allocations.end(); x++) \ + cerr << (void*)(*x) << " (refc = " << (*x)->refc << "): " \ + << (*x) << endl; \ + mem_allocations.clear(); \ + } +static void mem_mark(pure_expr *x) +{ + mem_allocations.erase(x); + if (x->tag == EXPR::APP) { + mem_mark(x->data.x[0]); + mem_mark(x->data.x[1]); + } +} #else #define MEMDEBUG_NEW(x) #define MEMDEBUG_FREE(x) #define MEMDEBUG_INIT -#define MEMDEBUG_SUMMARY +#define MEMDEBUG_SUMMARY(ret) #endif // Expression pointers are allocated in larger chunks for better performance. @@ -115,30 +131,25 @@ delete x->data.clos; } +#if 1 + +/* This is implemented (mostly) non-recursively to prevent stack overflows, + using the xp field to form a stack on the fly. */ + static inline void pure_free_internal(pure_expr *x) { assert(x && "pure_free: null expression"); assert(x->refc > 0 && "pure_free: unreferenced expression"); assert(!x->xp && "pure_free: corrupt expression data"); - // Implemented (mostly) non-recursively to prevent stack overflows, using - // the xp field to form a stack on the fly. - pure_expr *xp; + pure_expr *xp = 0, *y; loop: -#if DEBUG>2 - if (x->tag >= 0 && x->data.clos) - cerr << "pure_free: " << (x->data.clos->local?"local":"global") - << " closure " << x << " (" << (void*)x << "), refc = " - << x->refc << endl; -#endif if (--x->refc == 0) { switch (x->tag) { case EXPR::APP: - xp = x->data.x[0]; - assert(!xp->xp); - xp->xp = x->data.x[1]; - free_expr(x); - x = xp; + y = x->data.x[0]; + assert(!x->xp); + x->xp = xp; xp = x; x = y; goto loop; case EXPR::INT: case EXPR::DBL: @@ -158,17 +169,54 @@ if (x->data.clos) pure_free_clos(x); break; } - xp = x->xp; x->xp = 0; - free_expr(x); - } else { - xp = x->xp; x->xp = 0; } + while (xp && x == xp->data.x[1]) { + if (x->refc == 0) free_expr(x); + x = xp; xp = x->xp; + } + if (x->refc == 0) free_expr(x); if (xp) { - x = xp; + x = xp->data.x[1]; goto loop; } } +#else + +/* This version is only included here for reference and debugging purposes, + normal builds should use the non-recursive version above. */ + +static +void pure_free_internal(pure_expr *x) +{ + if (--x->refc == 0) { + switch (x->tag) { + case EXPR::APP: + pure_free_internal(x->data.x[0]); + pure_free_internal(x->data.x[1]); + break; + case EXPR::INT: + case EXPR::DBL: + break; + case EXPR::BIGINT: + mpz_clear(x->data.z); + break; + case EXPR::STR: + free(x->data.s); + break; + case EXPR::PTR: + break; + default: + assert(x->tag >= 0); + if (x->data.clos) pure_free_clos(x); + break; + } + free_expr(x); + } +} + +#endif + static void inline pure_unref_internal(pure_expr *x) { @@ -594,13 +642,13 @@ if (tmps != e) pure_freenew(tmps); tmps = next; } - MEMDEBUG_SUMMARY + MEMDEBUG_SUMMARY(e) return 0; } else { pure_expr *res = fp(); // normal return interp.estk.pop_front(); - MEMDEBUG_SUMMARY + MEMDEBUG_SUMMARY(res) #if DEBUG>1 pure_expr *tmps = interp.tmps; while (tmps) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-18 09:07:34
|
Revision: 96 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=96&view=rev Author: agraef Date: 2008-05-18 02:07:35 -0700 (Sun, 18 May 2008) Log Message: ----------- Overhaul of memory debugging code. Modified Paths: -------------- pure/trunk/interpreter.hh pure/trunk/runtime.cc Modified: pure/trunk/interpreter.hh =================================================================== --- pure/trunk/interpreter.hh 2008-05-17 20:06:47 UTC (rev 95) +++ pure/trunk/interpreter.hh 2008-05-18 09:07:35 UTC (rev 96) @@ -394,6 +394,9 @@ map<int32_t,GlobalVar> globalvars; map<int32_t,Env> globalfuns; list<pure_exception> estk; +#if DEBUG + set<pure_expr*> mem_allocations; +#endif map<int32_t,ExternInfo> externals; llvm::Function *declare_extern(void *fp, string name, string restype, int n, ...); Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-05-17 20:06:47 UTC (rev 95) +++ pure/trunk/runtime.cc 2008-05-18 09:07:35 UTC (rev 96) @@ -19,31 +19,36 @@ >= interpreter::stackmax) \ pure_throw(stack_exception()) -// Debug expression allocations. +// Debug expression allocations. Warns about expression memory leaks. +// NOTE: Bookkeeping starts and ends at each toplevel pure_invoke call. +// Enabling this code will make the interpreter *much* slower. #if DEBUG>2 -int mem_level = 0; -set<pure_expr*> mem_allocations; -#if DEBUG>9 -#define MEMDEBUG_NEW(x) mem_allocations.insert(x); \ +#if DEBUG>9 // enable this to print each and every expression (de)allocation +#define MEMDEBUG_NEW(x) interpreter::g_interp->mem_allocations.insert(x); \ cerr << "NEW: " << (void*)x << ": " << x << endl; -#define MEMDEBUG_FREE(x) mem_allocations.erase(x); \ +#define MEMDEBUG_FREE(x) interpreter::g_interp->mem_allocations.erase(x); \ cerr << "FREE: " << (void*)x << ": " << x << endl; #else -#define MEMDEBUG_NEW(x) mem_allocations.insert(x); -#define MEMDEBUG_FREE(x) mem_allocations.erase(x); +#define MEMDEBUG_NEW(x) interpreter::g_interp->mem_allocations.insert(x); +#define MEMDEBUG_FREE(x) interpreter::g_interp->mem_allocations.erase(x); #endif -#define MEMDEBUG_INIT if (mem_level++==0) mem_allocations.clear(); -#define MEMDEBUG_SUMMARY(ret) if (--mem_level==0) { mem_mark(ret); \ - if (!mem_allocations.empty()) { cerr << "POSSIBLE LEAKS:\n"; \ - for (set<pure_expr*>::iterator x = mem_allocations.begin(); \ - x != mem_allocations.end(); x++) \ - cerr << (void*)(*x) << " (refc = " << (*x)->refc << "): " \ - << (*x) << endl; \ - mem_allocations.clear(); \ - } } +#define MEMDEBUG_INIT if (interpreter::g_interp->estk.empty()) \ + interpreter::g_interp->mem_allocations.clear(); +#define MEMDEBUG_SUMMARY(ret) if (interpreter::g_interp->estk.empty()) {\ + mem_mark(ret); \ + if (!interpreter::g_interp->mem_allocations.empty()) { \ + cerr << "** WARNING: leaked expressions:\n"; \ + for (set<pure_expr*>::iterator x = \ + interpreter::g_interp->mem_allocations.begin(); \ + x != interpreter::g_interp->mem_allocations.end(); x++) \ + cerr << (void*)(*x) << " (refc = " << (*x)->refc << "): " \ + << (*x) << endl; \ + interpreter::g_interp->mem_allocations.clear(); \ + } \ + } static void mem_mark(pure_expr *x) { - mem_allocations.erase(x); + interpreter::g_interp->mem_allocations.erase(x); if (x->tag == EXPR::APP) { mem_mark(x->data.x[0]); mem_mark(x->data.x[1]); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-18 09:51:44
|
Revision: 98 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=98&view=rev Author: agraef Date: 2008-05-18 02:51:44 -0700 (Sun, 18 May 2008) Log Message: ----------- Add shadow stack to keep track of allocated function arguments. Modified Paths: -------------- pure/trunk/interpreter.hh pure/trunk/runtime.cc Modified: pure/trunk/interpreter.hh =================================================================== --- pure/trunk/interpreter.hh 2008-05-18 09:28:00 UTC (rev 97) +++ pure/trunk/interpreter.hh 2008-05-18 09:51:44 UTC (rev 98) @@ -394,6 +394,7 @@ map<int32_t,GlobalVar> globalvars; map<int32_t,Env> globalfuns; list<pure_exception> estk; + vector<pure_expr*> sstk; #if DEBUG set<pure_expr*> mem_allocations; #endif Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-05-18 09:28:00 UTC (rev 97) +++ pure/trunk/runtime.cc 2008-05-18 09:51:44 UTC (rev 98) @@ -682,8 +682,18 @@ void pure_new_args(pure_expr *x, ...) { va_list ap; + interpreter& interp = *interpreter::g_interp; + size_t cap = interp.sstk.capacity(), sz = interp.sstk.size(); + if (cap < sz+MAXARGS) { + if (sz == 0) + cap = 0x10000; // 64K + else + cap = cap << 1; + interp.sstk.reserve(cap); + } va_start(ap, x); while (x) { + interp.sstk.push_back(x); if (x->refc > 0) x->refc++; else @@ -697,6 +707,8 @@ void pure_free_args(pure_expr *x, ...) { va_list ap; + interpreter& interp = *interpreter::g_interp; + size_t count = 0; va_start(ap, x); if (x) x->refc++; while (1) { @@ -706,8 +718,12 @@ x->refc--; else pure_free_internal(x); + count++; }; va_end(ap); + size_t sz = interp.sstk.size(); + assert(sz >= count); + interp.sstk.resize(sz-count); } extern "C" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-18 10:04:34
|
Revision: 99 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=99&view=rev Author: agraef Date: 2008-05-18 03:04:41 -0700 (Sun, 18 May 2008) Log Message: ----------- Vector implementation of shadow stack is too heavy, try STL stack instead. Modified Paths: -------------- pure/trunk/interpreter.hh pure/trunk/runtime.cc Modified: pure/trunk/interpreter.hh =================================================================== --- pure/trunk/interpreter.hh 2008-05-18 09:51:44 UTC (rev 98) +++ pure/trunk/interpreter.hh 2008-05-18 10:04:41 UTC (rev 99) @@ -12,6 +12,7 @@ #include <llvm/Support/LLVMBuilder.h> #include <time.h> +#include <stack> #include <set> #include <string> #include "expr.hh" @@ -394,7 +395,7 @@ map<int32_t,GlobalVar> globalvars; map<int32_t,Env> globalfuns; list<pure_exception> estk; - vector<pure_expr*> sstk; + stack<pure_expr*> sstk; #if DEBUG set<pure_expr*> mem_allocations; #endif Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-05-18 09:51:44 UTC (rev 98) +++ pure/trunk/runtime.cc 2008-05-18 10:04:41 UTC (rev 99) @@ -683,17 +683,9 @@ { va_list ap; interpreter& interp = *interpreter::g_interp; - size_t cap = interp.sstk.capacity(), sz = interp.sstk.size(); - if (cap < sz+MAXARGS) { - if (sz == 0) - cap = 0x10000; // 64K - else - cap = cap << 1; - interp.sstk.reserve(cap); - } va_start(ap, x); while (x) { - interp.sstk.push_back(x); + interp.sstk.push(x); if (x->refc > 0) x->refc++; else @@ -708,7 +700,6 @@ { va_list ap; interpreter& interp = *interpreter::g_interp; - size_t count = 0; va_start(ap, x); if (x) x->refc++; while (1) { @@ -718,12 +709,9 @@ x->refc--; else pure_free_internal(x); - count++; + interp.sstk.pop(); }; va_end(ap); - size_t sz = interp.sstk.size(); - assert(sz >= count); - interp.sstk.resize(sz-count); } extern "C" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-18 10:44:41
|
Revision: 100 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=100&view=rev Author: agraef Date: 2008-05-18 03:44:48 -0700 (Sun, 18 May 2008) Log Message: ----------- STL containers are too darn slow, we do our own implementation of the shadow stack instead. Modified Paths: -------------- pure/trunk/interpreter.cc pure/trunk/interpreter.hh pure/trunk/runtime.cc Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-05-18 10:04:41 UTC (rev 99) +++ pure/trunk/interpreter.cc 2008-05-18 10:44:48 UTC (rev 100) @@ -62,6 +62,9 @@ stackdir = c_stack_dir(); } + sstk_sz = 0; sstk_cap = 0x10000; // 64K + sstk = (pure_expr**)malloc(sstk_cap*sizeof(pure_expr*)); + // Initialize the JIT. using namespace llvm; Modified: pure/trunk/interpreter.hh =================================================================== --- pure/trunk/interpreter.hh 2008-05-18 10:04:41 UTC (rev 99) +++ pure/trunk/interpreter.hh 2008-05-18 10:44:48 UTC (rev 100) @@ -12,7 +12,6 @@ #include <llvm/Support/LLVMBuilder.h> #include <time.h> -#include <stack> #include <set> #include <string> #include "expr.hh" @@ -395,7 +394,7 @@ map<int32_t,GlobalVar> globalvars; map<int32_t,Env> globalfuns; list<pure_exception> estk; - stack<pure_expr*> sstk; + pure_expr** sstk; size_t sstk_cap, sstk_sz; #if DEBUG set<pure_expr*> mem_allocations; #endif Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-05-18 10:04:41 UTC (rev 99) +++ pure/trunk/runtime.cc 2008-05-18 10:44:48 UTC (rev 100) @@ -683,9 +683,16 @@ { va_list ap; interpreter& interp = *interpreter::g_interp; + pure_expr**& sstk = interp.sstk; + size_t cap = interp.sstk_cap, sz = interp.sstk_sz; + if (cap < sz+MAXARGS) { + cap = cap << 1; + sstk = (pure_expr**)realloc(sstk, cap*sizeof(pure_expr*)); + interp.sstk_cap = cap; + } va_start(ap, x); while (x) { - interp.sstk.push(x); + sstk[sz++] = x; if (x->refc > 0) x->refc++; else @@ -693,13 +700,14 @@ x = va_arg(ap, pure_expr*); }; va_end(ap); + interp.sstk_sz = sz; } extern "C" void pure_free_args(pure_expr *x, ...) { va_list ap; - interpreter& interp = *interpreter::g_interp; + size_t count = 0; va_start(ap, x); if (x) x->refc++; while (1) { @@ -709,9 +717,11 @@ x->refc--; else pure_free_internal(x); - interp.sstk.pop(); + count++; }; va_end(ap); + assert(interpreter::g_interp->sstk_sz >= count); + interpreter::g_interp->sstk_sz -= count; } extern "C" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-22 14:42:13
|
Revision: 106 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=106&view=rev Author: agraef Date: 2008-05-22 07:42:19 -0700 (Thu, 22 May 2008) Log Message: ----------- Reenable some optimizations to speed up trivial cases of function calls and returns, which were previously removed (cf. rev. 97) to facilitate implementation of the shadow stack. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-22 07:14:45 UTC (rev 105) +++ pure/trunk/ChangeLog 2008-05-22 14:42:19 UTC (rev 106) @@ -4,8 +4,8 @@ handling. Fixed the shadow stack and memory debugging code. Both function arguments and environment are now visible on the shadow stack, and all remaining memory leaks have been fixed. Note that, - compared to previous revisions, the shadow stack slows down the - interpreter a little bit and it also needs some additional memory. + compared to previous revisions, the shadow stack slows down + compiled code by some 10% and it needs some additional memory. OTOH, it also provides additional data that will be needed in the planned symbolic debugger, and it seems to be the most efficient way to handle dangling expression pointers after an exception Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-05-22 07:14:45 UTC (rev 105) +++ pure/trunk/interpreter.cc 2008-05-22 14:42:19 UTC (rev 106) @@ -253,6 +253,13 @@ declare_extern((void*)pure_pop_tail_args, "pure_pop_tail_args", "void", -2, "expr*", "int"); + declare_extern((void*)pure_push_arg, + "pure_push_arg", "void", 1, "expr*"); + declare_extern((void*)pure_pop_arg, + "pure_pop_arg", "void", 1, "expr*"); + declare_extern((void*)pure_pop_tail_arg, + "pure_pop_tail_arg", "void", 1, "expr*"); + declare_extern((void*)pure_debug, "pure_debug", "void", -2, "int", "char*"); } @@ -1678,6 +1685,7 @@ ReturnInst *ret = builder.CreateRet(v); Instruction *pi = ret; Function *free_fun = interp.module->getFunction("pure_pop_args"); + Function *free1_fun = interp.module->getFunction("pure_pop_arg"); if (isa<CallInst>(v)) { CallInst* c = cast<CallInst>(v); // Check whether the call is actually subject to tail call elimination (as @@ -1691,8 +1699,12 @@ if (isa<CallInst>(it)) { CallInst* c1 = cast<CallInst>(it); if (c1->getCalledFunction() == - interp.module->getFunction("pure_push_args")) + interp.module->getFunction("pure_push_args") || + c1->getCalledFunction() == + interp.module->getFunction("pure_push_arg")) { free_fun = interp.module->getFunction("pure_pop_tail_args"); + free1_fun = interp.module->getFunction("pure_pop_tail_arg"); + } } } pi = c; @@ -1700,7 +1712,12 @@ // We must garbage-collect args and environment here, immediately before the // call (if any), or the return instruction otherwise. vector<Value*> myargs; - if (n+m != 0) { + if (pi != ret && n == 1 && m == 0) + new CallInst(free1_fun, args[0], "", pi); + else if (pi != ret && n == 0 && m == 1) { + Value *v = new GetElementPtrInst(envs, Zero, "", pi); + new CallInst(free1_fun, new LoadInst(v, "", pi), "", pi); + } else if (n+m != 0) { if (pi == ret) myargs.push_back(v); else @@ -3075,10 +3092,14 @@ if (n>0) { for (i = 0; i < n; i++) argv[i] = codegen(args[i]); - vector<Value*> argv1; - argv1.push_back(UInt(n)); - argv1.insert(argv1.end(), argv.begin(), argv.end()); - act_env().CreateCall(module->getFunction("pure_push_args"), argv1); + if (n == 1) + act_env().CreateCall(module->getFunction("pure_push_arg"), argv); + else { + vector<Value*> argv1; + argv1.push_back(UInt(n)); + argv1.insert(argv1.end(), argv.begin(), argv.end()); + act_env().CreateCall(module->getFunction("pure_push_args"), argv1); + } } return act_env().CreateCall(info.f, argv); } @@ -3360,10 +3381,14 @@ return fcall(f, x); else { // create a boxed closure - vector<Value*> newargs; - newargs.push_back(UInt(f.m)); - newargs.insert(newargs.end(), x.begin(), x.end()); - act_env().CreateCall(module->getFunction("pure_new_args"), newargs); + if (f.m == 1) + act_env().CreateCall(module->getFunction("pure_new"), x); + else { + vector<Value*> newargs; + newargs.push_back(UInt(f.m)); + newargs.insert(newargs.end(), x.begin(), x.end()); + act_env().CreateCall(module->getFunction("pure_new_args"), newargs); + } return call("pure_clos", f.local, thunked, f.tag, f.h, f.n, x); } } @@ -3578,10 +3603,14 @@ return fcall(f, x); else { // create a boxed closure - vector<Value*> newargs; - newargs.push_back(UInt(f.m)); - newargs.insert(newargs.end(), x.begin(), x.end()); - act_env().CreateCall(module->getFunction("pure_new_args"), newargs); + if (f.m == 1) + act_env().CreateCall(module->getFunction("pure_new"), x); + else { + vector<Value*> newargs; + newargs.push_back(UInt(f.m)); + newargs.insert(newargs.end(), x.begin(), x.end()); + act_env().CreateCall(module->getFunction("pure_new_args"), newargs); + } return call("pure_clos", f.local, thunked, f.tag, f.h, f.n, x); } } @@ -3605,7 +3634,11 @@ x.push_back(e.argv); } // count references to parameters - if (n+m > 0) { + if (n == 1 && m == 0) + e.CreateCall(module->getFunction("pure_push_arg"), args); + else if (n == 0 && m == 1) + e.CreateCall(module->getFunction("pure_push_arg"), env); + else if (n+m > 0) { vector<Value*> args1; args1.push_back(UInt(n+m)); args1.insert(args1.end(), args.begin(), args.end()); @@ -4039,10 +4072,14 @@ x[i] = f.CreateLoadGEP(f.envs, UInt(i)); assert(x[i]->getType() == ExprPtrTy); } - vector<Value*> newargs; - newargs.push_back(UInt(f.m)); - newargs.insert(newargs.end(), x.begin(), x.end()); - act_env().CreateCall(module->getFunction("pure_new_args"), newargs); + if (f.m == 1) + act_env().CreateCall(module->getFunction("pure_new"), x); + else { + vector<Value*> newargs; + newargs.push_back(UInt(f.m)); + newargs.insert(newargs.end(), x.begin(), x.end()); + act_env().CreateCall(module->getFunction("pure_new_args"), newargs); + } Value *defaultv = call("pure_clos", f.local, true, f.tag, f.h, f.n, x); for (size_t i = 0; i < f.n; ++i) { Value *arg = f.args[i]; Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-05-22 07:14:45 UTC (rev 105) +++ pure/trunk/runtime.cc 2008-05-22 14:42:19 UTC (rev 106) @@ -1027,6 +1027,66 @@ } extern "C" +void pure_push_arg(pure_expr *x) +{ + interpreter& interp = *interpreter::g_interp; + size_t sz = interp.sstk_sz; + resize_sstk(interp.sstk, interp.sstk_cap, sz, 2); + pure_expr** sstk = interp.sstk; + sstk[sz++] = 0; sstk[sz++] = x; + if (x->refc > 0) + x->refc++; + else + pure_new_internal(x); +#if SSTK_DEBUG>1 + cerr << "++ stack: (sz = " << sz << ")\n"; + for (size_t i = 0; i < sz; i++) { + pure_expr *x = sstk[i]; + if (i == interp.sstk_sz) cerr << "** pushed:\n"; + if (x) + cerr << i << ": " << (void*)x << ": " << x << endl; + else + cerr << i << ": " << "** frame **\n"; + } +#endif + interp.sstk_sz = sz; +} + +extern "C" +void pure_pop_arg(pure_expr *x) +{ +#if SSTK_DEBUG + pure_pop_args(0, 1, x); +#else + interpreter& interp = *interpreter::g_interp; + interp.sstk_sz -= 2; + if (x->refc > 1) + x->refc--; + else + pure_free_internal(x); +#endif +} + +extern "C" +void pure_pop_tail_arg(pure_expr *x) +{ +#if SSTK_DEBUG + pure_pop_tail_args(0, 1, x); +#else + interpreter& interp = *interpreter::g_interp; + pure_expr **sstk = interp.sstk; + size_t lastsz = interp.sstk_sz, oldsz = lastsz; + while (lastsz > 0 && sstk[--lastsz]) ; + memmove(sstk+lastsz-2, sstk+lastsz, (oldsz-lastsz)*sizeof(pure_expr*)); + interp.sstk_sz -= 2; + if (x->refc > 1) + x->refc--; + else + pure_free_internal(x); +#endif +} + +extern "C" void pure_debug(int32_t tag, const char *format, ...) { cout << "break at "; Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-05-22 07:14:45 UTC (rev 105) +++ pure/trunk/runtime.h 2008-05-22 14:42:19 UTC (rev 106) @@ -183,6 +183,12 @@ void pure_pop_args(pure_expr *x, uint32_t n, ...); void pure_pop_tail_args(pure_expr *x, uint32_t n, ...); +/* Optimize the special case of a single argument to be pushed/popped. */ + +void pure_push_arg(pure_expr *x); +void pure_pop_arg(pure_expr *x); +void pure_pop_tail_arg(pure_expr *x); + /* Debugging support. Preliminary. */ void pure_debug(int32_t tag, const char *format, ...); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-23 01:15:03
|
Revision: 107 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=107&view=rev Author: agraef Date: 2008-05-22 18:15:11 -0700 (Thu, 22 May 2008) Log Message: ----------- Fix segfaults caused by closures being called after their environments and LLVM IR was freed. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc pure/trunk/interpreter.hh Added Paths: ----------- pure/trunk/test/test10.log pure/trunk/test/test10.pure Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-22 14:42:19 UTC (rev 106) +++ pure/trunk/ChangeLog 2008-05-23 01:15:11 UTC (rev 107) @@ -1,3 +1,21 @@ +2008-05-23 Albert Graef <Dr....@t-...> + + * interpreter.cc: If there are any child environments, doeval and + dodefn both create semi-permanent environments now, so that the + child environments and the corresponding LLVM IR survive for the + entire lifetime of any embedded closures, which might still be + called at a later time. This fixes the segfaults occurring when a + closure gets called after its associated environment was purged. A + partial fix for some situations (as reported earlier by Chris + Double) was already in the 0.2 release, but this didn't deal with + all cases, such as closures constructed in a call to the eval + function, as reported by Eddie Rucker. + + TODO: The current solution leaks memory, as the doeval/dodefn + environments aren't reclaimed any more. This still needs to be + fixed, by counting references on the global ancestor environments + of each closure constructed in doeval and dodefn. + 2008-05-22 Albert Graef <Dr....@t-...> * interpreter.cc, runtime.cc: Major overhaul of expression memory Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-05-22 14:42:19 UTC (rev 106) +++ pure/trunk/interpreter.cc 2008-05-23 01:15:11 UTC (rev 107) @@ -787,7 +787,6 @@ // patch up the global variable table to replace it with a cbox. map<int32_t,GlobalVar>::iterator v = globalvars.find(f); if (v != globalvars.end()) { - v->second.clear(); pure_expr *cv = pure_const(f); if (v->second.x) pure_free(v->second.x); v->second.x = pure_new(cv); @@ -1554,8 +1553,7 @@ v.v = new GlobalVariable (ExprPtrTy, false, GlobalVariable::ExternalLinkage, 0, sym.s, module); JIT->addGlobalMapping(v.v, &v.x); - } else - v.clear(); + } if (v.x) pure_free(v.x); v.x = pure_new(x); environ[tag] = env_info(&v.x, temp); restore_globals(g); @@ -1575,15 +1573,6 @@ return os << ")"; } -void GlobalVar::clear() -{ - if (e) { - assert(e->refc > 0); - if (--e->refc == 0) delete e; - e = 0; - } -} - Env& Env::operator= (const Env& e) { if (f) { @@ -2569,8 +2558,7 @@ (ExprPtrTy, false, GlobalVariable::InternalLinkage, 0, mkvarlabel(sym.f), module); JIT->addGlobalMapping(v.v, &v.x); - } else - v.clear(); + } if (v.x) pure_free(v.x); v.x = pure_new(cv); Value *defaultv = b.CreateLoad(v.v); vector<Value*> myargs(2); @@ -2597,7 +2585,13 @@ } // Create an anonymous function to call in order to evaluate the target // expression. - Env f(0, 0, x, false); + /* NOTE: The environment is allocated dynamically, so that its child + environments survive for the entire lifetime of any embedded closures, + which might still be called at a later time. XXXFIXME: This leaks memory + right now. How do we keep track of environments that might still be + needed? */ + Env *fptr = new Env(0, 0, x, false); + Env &f = *fptr; push("doeval", &f); fun_prolog(""); #if DEBUG>1 @@ -2618,6 +2612,8 @@ // Get rid of our anonymous function. JIT->freeMachineCodeForFunction(f.f); f.f->eraseFromParent(); + // If there are no child envs, we can get rid of the environment now. + if (f.fmap[0].empty()) delete fptr; // NOTE: Result (if any) is to be freed by the caller. return res; } @@ -2631,10 +2627,6 @@ } // Create an anonymous function to call in order to evaluate the rhs // expression, match against the lhs and bind variables in lhs accordingly. - /* NOTE: Unlike doeval(), we must create a semi-permanent environment here - whose child environments persist for the entire lifetime of the variables - bound in this definition, since some of those bindings may refer to - closures (executable code) that might still be called some time. */ Env *fptr = new Env(0, 0, rhs, false); Env &f = *fptr; push("dodefn", &f); @@ -2673,9 +2665,7 @@ v.v = new GlobalVariable (ExprPtrTy, false, GlobalVariable::ExternalLinkage, 0, sym.s, module); JIT->addGlobalMapping(v.v, &v.x); - } else - v.clear(); - v.e = fptr; f.refc++; + } if (v.x) call("pure_free", f.builder.CreateLoad(v.v)); call("pure_new", x); #if DEBUG>2 @@ -2703,13 +2693,14 @@ // Get rid of our anonymous function. JIT->freeMachineCodeForFunction(f.f); f.f->eraseFromParent(); + // If there are no child envs, we can get rid of the environment now. + if (f.fmap[0].empty()) delete fptr; if (!res) { // We caught an exception, clean up the mess. for (env::const_iterator it = vars.begin(); it != vars.end(); ++it) { int32_t tag = it->first; GlobalVar& v = globalvars[tag]; if (!v.x) { - v.clear(); JIT->updateGlobalMapping(v.v, 0); v.v->eraseFromParent(); globalvars.erase(tag); @@ -3407,8 +3398,7 @@ (ExprPtrTy, false, GlobalVariable::InternalLinkage, 0, mkvarlabel(tag), module); JIT->addGlobalMapping(v.v, &v.x); - } else - v.clear(); + } if (v.x) pure_free(v.x); v.x = pure_new(cv); return act_builder().CreateLoad(v.v); } Modified: pure/trunk/interpreter.hh =================================================================== --- pure/trunk/interpreter.hh 2008-05-22 14:42:19 UTC (rev 106) +++ pure/trunk/interpreter.hh 2008-05-23 01:15:11 UTC (rev 107) @@ -69,9 +69,7 @@ // global variable llvm::GlobalVariable* v; pure_expr *x; - Env *e; - GlobalVar() { v = 0; x = 0; e = 0; } - void clear(); + GlobalVar() { v = 0; x = 0; } }; struct VarInfo { @@ -133,7 +131,7 @@ Builder builder; // parent environment (if any) Env *parent; - // reference counter (for dodefn) + // reference counter (currently unused) uint32_t refc; // convenience functions for invoking CreateGEP() and CreateLoad() llvm::Value *CreateGEP Added: pure/trunk/test/test10.log =================================================================== --- pure/trunk/test/test10.log (rev 0) +++ pure/trunk/test/test10.log 2008-05-23 01:15:11 UTC (rev 107) @@ -0,0 +1,3 @@ +\x -> x!0==[0,1,0,0]; +eval "(\\x -> (x!0) == [0,1,0,0])" [[0,1,0,0],[1,1,2]]; +1 Added: pure/trunk/test/test10.pure =================================================================== --- pure/trunk/test/test10.pure (rev 0) +++ pure/trunk/test/test10.pure 2008-05-23 01:15:11 UTC (rev 107) @@ -0,0 +1,2 @@ + +eval "(\\x -> (x!0) == [0,1,0,0])" [[0,1,0,0],[1,1,2]]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-23 01:39:05
|
Revision: 109 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=109&view=rev Author: agraef Date: 2008-05-22 18:39:13 -0700 (Thu, 22 May 2008) Log Message: ----------- Bump version number. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/Makefile Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-23 01:24:21 UTC (rev 108) +++ pure/trunk/ChangeLog 2008-05-23 01:39:13 UTC (rev 109) @@ -1,5 +1,7 @@ 2008-05-23 Albert Graef <Dr....@t-...> + * Makefile: Bump version number. + * interpreter.cc: If there are any child environments, doeval and dodefn both create semi-permanent environments now, so that the child environments and the corresponding LLVM IR survive for the Modified: pure/trunk/Makefile =================================================================== --- pure/trunk/Makefile 2008-05-23 01:24:21 UTC (rev 108) +++ pure/trunk/Makefile 2008-05-23 01:39:13 UTC (rev 109) @@ -9,7 +9,7 @@ # installation time, you can also specify a DESTDIR path if you want to # install into a staging directory, e.g.: 'make install DESTDIR=$PWD/BUILD'. -version = 0.2 +version = 0.3 dist = pure-$(version) prefix = /usr/local This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-23 05:18:29
|
Revision: 110 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=110&view=rev Author: agraef Date: 2008-05-22 22:18:37 -0700 (Thu, 22 May 2008) Log Message: ----------- Fix premature freeing of eval result. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/runtime.cc Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-23 01:39:13 UTC (rev 109) +++ pure/trunk/ChangeLog 2008-05-23 05:18:37 UTC (rev 110) @@ -1,5 +1,8 @@ 2008-05-23 Albert Graef <Dr....@t-...> + * runtime.cc (eval): Fix premature freeing of eval result. + Reported by Eddie Rucker. + * Makefile: Bump version number. * interpreter.cc: If there are any child environments, doeval and Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-05-23 01:39:13 UTC (rev 109) +++ pure/trunk/runtime.cc 2008-05-23 05:18:37 UTC (rev 110) @@ -1503,6 +1503,7 @@ assert(s); interpreter& interp = *interpreter::g_interp; pure_expr *res = interp.runstr(string(s)+";"); + interp.result = 0; if (res) pure_unref_internal(res); return res; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-24 05:29:06
|
Revision: 118 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=118&view=rev Author: agraef Date: 2008-05-23 22:29:06 -0700 (Fri, 23 May 2008) Log Message: ----------- Fix memleaks in doeval/dodefn. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/funcall.h pure/trunk/interpreter.cc pure/trunk/interpreter.hh pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-24 00:05:42 UTC (rev 117) +++ pure/trunk/ChangeLog 2008-05-24 05:29:06 UTC (rev 118) @@ -1,3 +1,8 @@ +2008-05-24 Albert Graef <Dr....@t-...> + + * pure.cc, runtime.cc, util.cc: Windows/MinGW compatibility + fixes. Suggested by Jiri Spitz. + 2008-05-23 Albert Graef <Dr....@t-...> * runtime.cc: Fix premature freeing of eval result, and a minor @@ -17,11 +22,6 @@ all cases, such as closures constructed in a call to the eval function, as reported by Eddie Rucker. - TODO: The current solution leaks memory, as the doeval/dodefn - environments aren't reclaimed any more. This still needs to be - fixed, by counting references on the global ancestor environments - of each closure constructed in doeval and dodefn. - 2008-05-22 Albert Graef <Dr....@t-...> * interpreter.cc, runtime.cc: Major overhaul of expression memory Modified: pure/trunk/funcall.h =================================================================== --- pure/trunk/funcall.h 2008-05-24 00:05:42 UTC (rev 117) +++ pure/trunk/funcall.h 2008-05-24 05:29:06 UTC (rev 118) @@ -10,74 +10,74 @@ portable. ;-) Maybe we should play some dirty tricks with the C stack instead? */ -#define funcall(fp,n,x) \ +#define funcall(ret,fp,n,x) \ switch (n) { \ - case 0: return ((pure_expr*(*)())fp)(); \ - case 1: return ((pure_expr*(*)(void*))fp)(x[0]); \ - case 2: return ((pure_expr*(*)(void*,void*))fp)(x[0],x[1]); \ - case 3: return ((pure_expr*(*)(void*,void*,void*))fp)(x[0],x[1],x[2]); \ - case 4: return ((pure_expr*(*)(void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3]); \ - case 5: return ((pure_expr*(*)(void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4]); \ - case 6: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5]); \ - case 7: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6]); \ - case 8: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7]); \ - case 9: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8]); \ - case 10: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9]); \ - case 11: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10]); \ - case 12: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11]); \ - case 13: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12]); \ - case 14: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13]); \ - case 15: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14]); \ - case 16: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15]); \ - case 17: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16]); \ - case 18: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17]); \ - case 19: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18]); \ - case 20: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19]); \ - case 21: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20]); \ - case 22: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21]); \ - case 23: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22]); \ - case 24: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23]); \ - case 25: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24]); \ - case 26: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25]); \ - case 27: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26]); \ - case 28: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27]); \ - case 29: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28]); \ - case 30: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29]); \ - case 31: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30]); \ - case 32: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31]); \ - case 33: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32]); \ - case 34: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33]); \ - case 35: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34]); \ - case 36: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35]); \ - case 37: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36]); \ - case 38: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37]); \ - case 39: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38]); \ - case 40: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39]); \ - case 41: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40]); \ - case 42: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41]); \ - case 43: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42]); \ - case 44: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43]); \ - case 45: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44]); \ - case 46: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45]); \ - case 47: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46]); \ - case 48: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47]); \ - case 49: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48]); \ - case 50: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49]); \ - case 51: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50]); \ - case 52: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51]); \ - case 53: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52]); \ - case 54: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53]); \ - case 55: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54]); \ - case 56: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55]); \ - case 57: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56]); \ - case 58: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56],x[57]); \ - case 59: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56],x[57],x[58]); \ - case 60: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56],x[57],x[58],x[59]); \ - case 61: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56],x[57],x[58],x[59],x[60]); \ - case 62: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56],x[57],x[58],x[59],x[60],x[61]); \ - case 63: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56],x[57],x[58],x[59],x[60],x[61],x[62]); \ - case 64: return ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56],x[57],x[58],x[59],x[60],x[61],x[62],x[63]); \ + case 0: ret = ((pure_expr*(*)())fp)(); break; \ + case 1: ret = ((pure_expr*(*)(void*))fp)(x[0]); break; \ + case 2: ret = ((pure_expr*(*)(void*,void*))fp)(x[0],x[1]); break; \ + case 3: ret = ((pure_expr*(*)(void*,void*,void*))fp)(x[0],x[1],x[2]); break; \ + case 4: ret = ((pure_expr*(*)(void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3]); break; \ + case 5: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4]); break; \ + case 6: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5]); break; \ + case 7: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6]); break; \ + case 8: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7]); break; \ + case 9: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8]); break; \ + case 10: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9]); break; \ + case 11: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10]); break; \ + case 12: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11]); break; \ + case 13: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12]); break; \ + case 14: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13]); break; \ + case 15: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14]); break; \ + case 16: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15]); break; \ + case 17: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16]); break; \ + case 18: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17]); break; \ + case 19: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18]); break; \ + case 20: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19]); break; \ + case 21: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20]); break; \ + case 22: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21]); break; \ + case 23: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22]); break; \ + case 24: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23]); break; \ + case 25: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24]); break; \ + case 26: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25]); break; \ + case 27: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26]); break; \ + case 28: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27]); break; \ + case 29: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28]); break; \ + case 30: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29]); break; \ + case 31: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30]); break; \ + case 32: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31]); break; \ + case 33: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32]); break; \ + case 34: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33]); break; \ + case 35: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34]); break; \ + case 36: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35]); break; \ + case 37: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36]); break; \ + case 38: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37]); break; \ + case 39: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38]); break; \ + case 40: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39]); break; \ + case 41: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40]); break; \ + case 42: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41]); break; \ + case 43: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42]); break; \ + case 44: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43]); break; \ + case 45: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44]); break; \ + case 46: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45]); break; \ + case 47: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46]); break; \ + case 48: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47]); break; \ + case 49: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48]); break; \ + case 50: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49]); break; \ + case 51: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50]); break; \ + case 52: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51]); break; \ + case 53: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52]); break; \ + case 54: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53]); break; \ + case 55: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54]); break; \ + case 56: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55]); break; \ + case 57: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56]); break; \ + case 58: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56],x[57]); break; \ + case 59: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56],x[57],x[58]); break; \ + case 60: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56],x[57],x[58],x[59]); break; \ + case 61: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56],x[57],x[58],x[59],x[60]); break; \ + case 62: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56],x[57],x[58],x[59],x[60],x[61]); break; \ + case 63: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56],x[57],x[58],x[59],x[60],x[61],x[62]); break; \ + case 64: ret = ((pure_expr*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*))fp)(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19],x[20],x[21],x[22],x[23],x[24],x[25],x[26],x[27],x[28],x[29],x[30],x[31],x[32],x[33],x[34],x[35],x[36],x[37],x[38],x[39],x[40],x[41],x[42],x[43],x[44],x[45],x[46],x[47],x[48],x[49],x[50],x[51],x[52],x[53],x[54],x[55],x[56],x[57],x[58],x[59],x[60],x[61],x[62],x[63]); break; \ default: \ assert(n <= MAXARGS && "funcall: function call exceeds maximum #args"); \ - return 0; \ + ret = 0; break; \ } Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-05-24 00:05:42 UTC (rev 117) +++ pure/trunk/interpreter.cc 2008-05-24 05:29:06 UTC (rev 118) @@ -55,7 +55,7 @@ stats(false), temp(0), ps("> "), lib(""), histfile("/.pure_history"), modname("pure"), nerrs(0), source_s(0), result(0), mem(0), exps(0), tmps(0), - module(0), JIT(0), FPM(0) + module(0), JIT(0), FPM(0), fptr(0), vptr(0) { if (!g_interp) { g_interp = this; @@ -191,8 +191,8 @@ // function pointers into the runtime map. declare_extern((void*)pure_clos, - "pure_clos", "expr*", -6, "bool", "bool", "int", - "int", "void*", "int"); + "pure_clos", "expr*", -7, "bool", "bool", "int", "int", + "void*", "void*", "int"); declare_extern((void*)pure_call, "pure_call", "expr*", 1, "expr*"); declare_extern((void*)pure_const, @@ -588,7 +588,7 @@ #endif // do a direct call to the runtime to create the fbox and cache it in // a global variable - pure_expr *fv = pure_clos(false, false, f.tag, f.n, f.fp, 0); + pure_expr *fv = pure_clos(false, false, f.tag, f.n, f.fp, 0, 0); GlobalVar& v = globalvars[f.tag]; if (!v.v) { v.v = new GlobalVariable @@ -1489,6 +1489,7 @@ #define ValFldIndex Two #define ValFld2Index Three #define SubFldIndex(i) UInt(i+2) +#define NullPtr ConstantPointerNull::get(VoidPtrTy) #define NullExprPtr ConstantPointerNull::get(ExprPtrTy) #define NullExprPtrPtr ConstantPointerNull::get(ExprPtrPtrTy) @@ -2576,6 +2577,15 @@ return f; } +Value *interpreter::envptr(Env *f) +{ + if (!fptr) return NullPtr; + if (!vptr) vptr = new GlobalVariable + (VoidPtrTy, false, GlobalVariable::InternalLinkage, 0, "$$fptr$$", module); + JIT->updateGlobalMapping(vptr, &fptr); + return act_builder().CreateLoad(vptr); +} + pure_expr *interpreter::doeval(expr x, pure_expr*& e) { char test; @@ -2590,7 +2600,8 @@ which might still be called at a later time. XXXFIXME: This leaks memory right now. How do we keep track of environments that might still be needed? */ - Env *fptr = new Env(0, 0, x, false); + Env *save_fptr = fptr; + fptr = new Env(0, 0, x, false); fptr->refc = 1; Env &f = *fptr; push("doeval", &f); fun_prolog(""); @@ -2612,8 +2623,12 @@ // Get rid of our anonymous function. JIT->freeMachineCodeForFunction(f.f); f.f->eraseFromParent(); - // If there are no child envs, we can get rid of the environment now. - if (f.fmap[0].empty()) delete fptr; + // If there are no more references, we can get rid of the environment now. + if (fptr->refc == 1) + delete fptr; + else + fptr->refc--; + fptr = save_fptr; // NOTE: Result (if any) is to be freed by the caller. return res; } @@ -2627,7 +2642,8 @@ } // Create an anonymous function to call in order to evaluate the rhs // expression, match against the lhs and bind variables in lhs accordingly. - Env *fptr = new Env(0, 0, rhs, false); + Env *save_fptr = fptr; + fptr = new Env(0, 0, rhs, false); fptr->refc = 1; Env &f = *fptr; push("dodefn", &f); fun_prolog(""); @@ -2693,8 +2709,12 @@ // Get rid of our anonymous function. JIT->freeMachineCodeForFunction(f.f); f.f->eraseFromParent(); - // If there are no child envs, we can get rid of the environment now. - if (f.fmap[0].empty()) delete fptr; + // If there are no more references, we can get rid of the environment now. + if (fptr->refc == 1) + delete fptr; + else + fptr->refc--; + fptr = save_fptr; if (!res) { // We caught an exception, clean up the mess. for (env::const_iterator it = vars.begin(); it != vars.end(); ++it) { @@ -3... [truncated message content] |
From: <ag...@us...> - 2008-05-24 11:11:02
|
Revision: 121 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=121&view=rev Author: agraef Date: 2008-05-24 04:11:10 -0700 (Sat, 24 May 2008) Log Message: ----------- Bugfixes in the scanf functions. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/lib/system.pure pure/trunk/runtime.cc pure/trunk/test/test011.log Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-24 10:30:04 UTC (rev 120) +++ pure/trunk/ChangeLog 2008-05-24 11:11:10 UTC (rev 121) @@ -1,5 +1,8 @@ 2008-05-24 Albert Graef <Dr....@t-...> + * runtime.cc, lib/system.pure: Bugfixes in the scanf + functions. Reported by Jiri Spitz. + * pure.cc, runtime.cc, util.cc: Windows/MinGW compatibility fixes. Suggested by Jiri Spitz. Modified: pure/trunk/lib/system.pure =================================================================== --- pure/trunk/lib/system.pure 2008-05-24 10:30:04 UTC (rev 120) +++ pure/trunk/lib/system.pure 2008-05-24 11:11:10 UTC (rev 121) @@ -265,7 +265,9 @@ "p" = pure_fscanf_pointer fp s buf; _ = throw (this_cant_happen ret); end; - res = if res>=1 then res + // Note: In difference to C scanf, the return value is the number of read + // characters here, with -1 denoting an error condition. + res = if res>=0 then res else (throw (scanf_error ret) when _ = free buf end); val = case t of "d" = get_int buf; @@ -350,8 +352,8 @@ "p" = pure_sscanf_pointer u s buf; _ = throw (this_cant_happen ret); end; - // Note: In difference to pure_fscanf, the return value is the number of - // read characters here, with -1 denoting an error condition. + // Note: In difference to C scanf, the return value is the number of read + // characters here, with -1 denoting an error condition. res = if res>=0 then res else (throw (scanf_error ret) when _ = free buf end); val = case t of Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-05-24 10:30:04 UTC (rev 120) +++ pure/trunk/runtime.cc 2008-05-24 11:11:10 UTC (rev 121) @@ -1742,79 +1742,95 @@ return snprintf(buf, size, format, x); } +#define myformat(format) scanf_format((char*)alloca(strlen(format)+3), format) + +static inline char *scanf_format(char *buf, const char *format) +{ + strcpy(buf, format); strcat(buf, "%n"); + return buf; +} + extern "C" int pure_fscanf(FILE *fp, const char *format) { - return fscanf(fp, format); + int count = -1; + fscanf(fp, myformat(format), &count); + return count; } extern "C" int pure_fscanf_int(FILE *fp, const char *format, int32_t *x) { - return fscanf(fp, format, x); + // wrap this up in case int on the target platform is not 32 bit + int count = -1, y; + fscanf(fp, myformat(format), &y, &count); + if (count >= 0) *x = y; + return count; } extern "C" int pure_fscanf_double(FILE *fp, const char *format, double *x) { - return fscanf(fp, format, x); + int count = -1; + fscanf(fp, myformat(format), x, &count); + return count; } extern "C" int pure_fscanf_string(FILE *fp, const char *format, const char *x) { - return fscanf(fp, format, x); + int count = -1; + fscanf(fp, myformat(format), x, &count); + return count; } extern "C" int pure_fscanf_pointer(FILE *fp, const char *format, const void **x) { - return fscanf(fp, format, x); + int count = -1; + fscanf(fp, myformat(format), x, &count); + return count; } -#define myformat(format) sscanf_format((char*)alloca(strlen(format)+3), format) - -static inline char *sscanf_format(char *buf, const char *format) -{ - strcpy(buf, format); strcat(buf, "%n"); - return buf; -} - extern "C" int pure_sscanf(const char *buf, const char *format) { - int count = -1, res = sscanf(buf, myformat(format), &count); - return (res >= 0)?count:-1; + int count = -1; + sscanf(buf, myformat(format), &count); + return count; } extern "C" int pure_sscanf_int(const char *buf, const char *format, int32_t *x) { // wrap this up in case int on the target platform is not 32 bit - int count = -1, y, res = sscanf(buf, myformat(format), &y, &count); - *x = y; - return (res >= 0)?count:-1; + int count = -1, y; sscanf(buf, myformat(format), &y, &count); + if (count >= 0) *x = y; + return count; } extern "C" int pure_sscanf_double(const char *buf, const char *format, double *x) { - int count = -1, res = sscanf(buf, myformat(format), x, &count); - return (res >= 0)?count:-1; + int count = -1; + sscanf(buf, myformat(format), x, &count); + return count; } extern "C" int pure_sscanf_string(const char *buf, const char *format, char *x) { - int count = -1, res = sscanf(buf, myformat(format), x, &count); - return (res >= 0)?count:-1; + int count = -1; + sscanf(buf, myformat(format), x, &count); + return count; } extern "C" int pure_sscanf_pointer(const char *buf, const char *format, void **x) { - int count = -1, res = sscanf(buf, myformat(format), x, &count); - return (res >= 0)?count:-1; + int count = -1; + sscanf(buf, myformat(format), x, &count); + return count; } #include <fnmatch.h> Modified: pure/trunk/test/test011.log =================================================================== --- pure/trunk/test/test011.log 2008-05-24 10:30:04 UTC (rev 120) +++ pure/trunk/test/test011.log 2008-05-24 11:11:10 UTC (rev 121) @@ -689,7 +689,7 @@ state 3: #1 #4 state 4: #2 #4 state 5: #3 #4 -} end; res/*0:*/ = if res/*0:*/>=1 then res/*0:*/ else throw (scanf_error ret/*4:01*/) when _/*0:*/ = free buf/*1:*/ { +} end; res/*0:*/ = if res/*0:*/>=0 then res/*0:*/ else throw (scanf_error ret/*4:01*/) when _/*0:*/ = free buf/*1:*/ { rule #0: _ = free buf state 0: #0 <var> state 1 @@ -727,7 +727,7 @@ <var> state 1 state 1: #0 } { - rule #0: res = if res>=1 then res else throw (scanf_error ret) when _ = free buf end + rule #0: res = if res>=0 then res else throw (scanf_error ret) when _ = free buf end state 0: #0 <var> state 1 state 1: #0 @@ -765,7 +765,7 @@ <var> state 1 state 1: #0 } end; do_fscanf _/*0:001*/ ret/*0:01*/ _/*0:1*/ = throw (this_cant_happen ret/*0:01*/) { - rule #0: do_fscanf fp ret (scanf_format_spec t s) = ret when size,s = if t=="s" then guestimate s else 16,s; buf = check_buf (calloc size 1); res = case t of "d" = pure_fscanf_int fp s buf; "g" = pure_fscanf_double fp s buf; "s" = pure_fscanf_string fp s buf; "p" = pure_fscanf_pointer fp s buf; _ = throw (this_cant_happen ret) end; res = if res>=1 then res else throw (scanf_error ret) when _ = free buf end; val = case t of "d" = get_int buf; "g" = get_double buf; "s" = cstring buf; "p" = get_pointer buf; _ = throw (this_cant_happen ret) end; _ = if t=="s" then () else free buf; ret = val:ret end + rule #0: do_fscanf fp ret (scanf_format_spec t s) = ret when size,s = if t=="s" then guestimate s else 16,s; buf = check_buf (calloc size 1); res = case t of "d" = pure_fscanf_int fp s buf; "g" = pure_fscanf_double fp s buf; "s" = pure_fscanf_string fp s buf; "p" = pure_fscanf_pointer fp s buf; _ = throw (this_cant_happen ret) end; res = if res>=0 then res else throw (scanf_error ret) when _ = free buf end; val = case t of "d" = get_int buf; "g" = get_double buf; "s" = cstring buf; "p" = get_pointer buf; _ = throw (this_cant_happen ret) end; _ = if t=="s" then () else free buf; ret = val:ret end rule #1: do_fscanf fp ret (scanf_format_str s) = ret when res = pure_fscanf fp s; ret = if res>=0 then ret else throw (scanf_error ret) end rule #2: do_fscanf _ ret _ = throw (this_cant_happen ret) state 0: #0 #1 #2 @@ -1900,7 +1900,7 @@ state 1: #0 } { - rule #0: fscanf fp format::string = tuple$reverse ret when ret = catch error_handler (foldl (do_fscanf fp) []$scanf_split_format format) end with error_handler (scanf_error ret) = throw (scanf_error (tuple$reverse ret)); error_handler x = throw x; check_buf buf = throw printf_malloc_error if null buf; check_buf buf = buf; do_fscanf fp ret (scanf_format_spec t s) = ret when size,s = if t=="s" then guestimate s else 16,s; buf = check_buf (calloc size 1); res = case t of "d" = pure_fscanf_int fp s buf; "g" = pure_fscanf_double fp s buf; "s" = pure_fscanf_string fp s buf; "p" = pure_fscanf_pointer fp s buf; _ = throw (this_cant_happen ret) end; res = if res>=1 then res else throw (scanf_error ret) when _ = free buf end; val = case t of "d" = get_int buf; "g" = get_double buf; "s" = cstring buf; "p" = get_pointer buf; _ = throw (this_cant_happen ret) end; _ = if t=="s" then () else free buf; ret = val:ret end; do_fscanf fp ret (scanf_format_str s) = ret when res = pure_fscanf fp s; ret = if res>=0 then ret else throw (scanf_error ret) end; do_fscanf _ ret _ = throw (this_cant_happen ret); guestimate format = n,format when 1,0,_,1,s = regex "^%([0-9]*)" REG_EXTENDED format 0; n,format = if null s then 1025,"%1024"+tail format else eval s+1,format end end + rule #0: fscanf fp format::string = tuple$reverse ret when ret = catch error_handler (foldl (do_fscanf fp) []$scanf_split_format format) end with error_handler (scanf_error ret) = throw (scanf_error (tuple$reverse ret)); error_handler x = throw x; check_buf buf = throw printf_malloc_error if null buf; check_buf buf = buf; do_fscanf fp ret (scanf_format_spec t s) = ret when size,s = if t=="s" then guestimate s else 16,s; buf = check_buf (calloc size 1); res = case t of "d" = pure_fscanf_int fp s buf; "g" = pure_fscanf_double fp s buf; "s" = pure_fscanf_string fp s buf; "p" = pure_fscanf_pointer fp s buf; _ = throw (this_cant_happen ret) end; res = if res>=0 then res else throw (scanf_error ret) when _ = free buf end; val = case t of "d" = get_int buf; "g" = get_double buf; "s" = cstring buf; "p" = get_pointer buf; _ = throw (this_cant_happen ret) end; _ = if t=="s" then () else free buf; ret = val:ret end; do_fscanf fp ret (scanf_format_str s) = ret when res = pure_fscanf fp s; ret = if res>=0 then ret else throw (scanf_error ret) end; do_fscanf _ ret _ = throw (this_cant_happen ret); guestimate format = n,format when 1,0,_,1,s = regex "^%([0-9]*)" REG_EXTENDED format 0; n,format = if null s then 1025,"%1024"+tail format else eval s+1,format end end state 0: #0 <var> state 1 state 1: #0 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-24 18:14:02
|
Revision: 124 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=124&view=rev Author: agraef Date: 2008-05-24 11:14:05 -0700 (Sat, 24 May 2008) Log Message: ----------- Fix memory allocation bugs in exception handling. Modified Paths: -------------- pure/trunk/interpreter.cc pure/trunk/runtime.cc Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-05-24 18:12:16 UTC (rev 123) +++ pure/trunk/interpreter.cc 2008-05-24 18:14:05 UTC (rev 124) @@ -437,7 +437,7 @@ globals g; save_globals(g); pure_expr *e, *res = eval(x, e); - if (!res && e) pure_freenew(e); + if (!res && e) pure_free(e); restore_globals(g); return res; } @@ -462,7 +462,7 @@ globals g; save_globals(g); pure_expr *e, *res = defn(pat, x, e); - if (!res && e) pure_freenew(e); + if (!res && e) pure_free(e); restore_globals(g); return res; } @@ -744,7 +744,7 @@ if (e) { msg << "unhandled exception '" << e << "' while evaluating '" << *x << "'"; - pure_freenew(e); + pure_free(e); } else msg << "unhandled exception while evaluating '" << *x << "'"; throw err(msg.str()); @@ -769,7 +769,7 @@ if (e) { msg << "unhandled exception '" << e << "' while evaluating '" << "let " << r->lhs << " = " << r->rhs << "'"; - pure_freenew(e); + pure_free(e); } else msg << "failed match while evaluating '" << "let " << r->lhs << " = " << r->rhs << "'"; Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-05-24 18:12:16 UTC (rev 123) +++ pure/trunk/runtime.cc 2008-05-24 18:14:05 UTC (rev 124) @@ -612,10 +612,7 @@ abort(); // no exception handler, bail out else { interp.estk.front().e = e; - if (e) { - assert(e->refc > 0); - pure_unref_internal(e); - } + assert(!e || e->refc > 0); longjmp(interp.estk.front().jmp, 1); } } @@ -672,21 +669,25 @@ size_t sz = interp.estk.front().sz; pure_expr *e = interp.estk.front().e; interp.estk.pop_front(); + assert(!e || e->refc > 0); + // make sure that we don't accidentally collect the exception value + if (e) e->refc++; // collect garbage pure_expr *tmps = interp.tmps; while (tmps) { pure_expr *next = tmps->xp; - if (tmps != e) pure_freenew(tmps); + pure_freenew(tmps); tmps = next; } for (size_t i = interp.sstk_sz; i-- > sz; ) if (interp.sstk[i] && interp.sstk[i]->refc > 0) pure_free_internal(interp.sstk[i]); interp.sstk_sz = sz; - if (!e) e = pure_const(interp.symtab.void_sym().f); - assert(e); - pure_unref_internal(h); - pure_expr *res = pure_apply2(h, e); + if (e && e->refc > 1) e->refc--; + if (!e) + e = pure_new_internal(pure_const(interp.symtab.void_sym().f)); + assert(e && e->refc > 0); + pure_expr *res = pure_apply(h, e); assert(res); res->refc++; pure_free_internal(x); @@ -742,17 +743,21 @@ size_t sz = interp.estk.front().sz; e = interp.estk.front().e; interp.estk.pop_front(); + assert(!e || e->refc > 0); + // make sure that we don't accidentally collect the exception value + if (e) e->refc++; // collect garbage pure_expr *tmps = interp.tmps; while (tmps) { pure_expr *next = tmps->xp; - if (tmps != e) pure_freenew(tmps); + pure_freenew(tmps); tmps = next; } for (size_t i = interp.sstk_sz; i-- > sz; ) if (interp.sstk[i] && interp.sstk[i]->refc > 0) pure_free_internal(interp.sstk[i]); interp.sstk_sz = sz; + if (e && e->refc > 1) e->refc--; MEMDEBUG_SUMMARY(e) return 0; } else { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-24 19:29:59
|
Revision: 127 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=127&view=rev Author: agraef Date: 2008-05-24 12:30:07 -0700 (Sat, 24 May 2008) Log Message: ----------- Fix memory allocation bugs in exception handling. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc pure/trunk/runtime.cc Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-24 19:27:27 UTC (rev 126) +++ pure/trunk/ChangeLog 2008-05-24 19:30:07 UTC (rev 127) @@ -1,5 +1,8 @@ 2008-05-24 Albert Graef <Dr....@t-...> + * interpreter.cc, runtime.cc: Fix more memory allocation bugs in + exception handling. + * runtime.cc, lib/system.pure: Bugfixes in the scanf functions. Reported by Jiri Spitz. Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-05-24 19:27:27 UTC (rev 126) +++ pure/trunk/interpreter.cc 2008-05-24 19:30:07 UTC (rev 127) @@ -3902,7 +3902,7 @@ assert(f); vector<Value*> args; if (tag > 0) - args.push_back(call("pure_new", cbox(tag))); + args.push_back(cbox(tag)); else args.push_back(NullExprPtr); Env& e = act_env(); Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-05-24 19:27:27 UTC (rev 126) +++ pure/trunk/runtime.cc 2008-05-24 19:30:07 UTC (rev 127) @@ -276,14 +276,13 @@ if (!interpreter::g_interp) return 0; pure_expr *f = pure_const(interpreter::g_interp->symtab.signal_sym().f); pure_expr *x = pure_int(sig); - return pure_new_internal(pure_apply2(f, x)); + return pure_apply2(f, x); } static inline pure_expr* stack_exception() { if (!interpreter::g_interp) return 0; - return pure_new_internal - (pure_const(interpreter::g_interp->symtab.segfault_sym().f)); + return pure_const(interpreter::g_interp->symtab.segfault_sym().f); } extern "C" @@ -612,7 +611,6 @@ abort(); // no exception handler, bail out else { interp.estk.front().e = e; - assert(!e || e->refc > 0); longjmp(interp.estk.front().jmp, 1); } } @@ -669,9 +667,7 @@ size_t sz = interp.estk.front().sz; pure_expr *e = interp.estk.front().e; interp.estk.pop_front(); - assert(!e || e->refc > 0); - // make sure that we don't accidentally collect the exception value - if (e) e->refc++; + if (e) pure_new_internal(e); // collect garbage pure_expr *tmps = interp.tmps; while (tmps) { @@ -683,10 +679,13 @@ if (interp.sstk[i] && interp.sstk[i]->refc > 0) pure_free_internal(interp.sstk[i]); interp.sstk_sz = sz; - if (e && e->refc > 1) e->refc--; if (!e) e = pure_new_internal(pure_const(interp.symtab.void_sym().f)); assert(e && e->refc > 0); +#if DEBUG>1 + cerr << "pure_catch: exception " << (void*)e << " (refc = " << e->refc + << "): " << e << endl; +#endif pure_expr *res = pure_apply(h, e); assert(res); res->refc++; @@ -743,9 +742,7 @@ size_t sz = interp.estk.front().sz; e = interp.estk.front().e; interp.estk.pop_front(); - assert(!e || e->refc > 0); - // make sure that we don't accidentally collect the exception value - if (e) e->refc++; + if (e) pure_new_internal(e); // collect garbage pure_expr *tmps = interp.tmps; while (tmps) { @@ -757,7 +754,11 @@ if (interp.sstk[i] && interp.sstk[i]->refc > 0) pure_free_internal(interp.sstk[i]); interp.sstk_sz = sz; - if (e && e->refc > 1) e->refc--; +#if DEBUG>1 + if (e) + cerr << "pure_invoke: exception " << (void*)e << " (refc = " << e->refc + << "): " << e << endl; +#endif MEMDEBUG_SUMMARY(e) return 0; } else { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-24 19:58:34
|
Revision: 128 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=128&view=rev Author: agraef Date: 2008-05-24 12:58:42 -0700 (Sat, 24 May 2008) Log Message: ----------- Fix sscanf %n conversion. Modified Paths: -------------- pure/trunk/lib/system.pure pure/trunk/test/test011.log pure/trunk/test/test011.pure Modified: pure/trunk/lib/system.pure =================================================================== --- pure/trunk/lib/system.pure 2008-05-24 19:30:07 UTC (rev 127) +++ pure/trunk/lib/system.pure 2008-05-24 19:58:42 UTC (rev 128) @@ -349,7 +349,7 @@ // null byte. buf = check_buf (calloc size 1); res = case t of - "n" = pure_fscanf_int fp s buf; + "n" = pure_sscanf_int u s buf; "d" = pure_sscanf_int u s buf; "g" = pure_sscanf_double u s buf; "s" = pure_sscanf_string u s buf; Modified: pure/trunk/test/test011.log =================================================================== --- pure/trunk/test/test011.log 2008-05-24 19:30:07 UTC (rev 127) +++ pure/trunk/test/test011.log 2008-05-24 19:58:42 UTC (rev 128) @@ -1042,8 +1042,8 @@ state 0: #0 <var> state 1 state 1: #0 -}; do_sscanf (u/*0:0101*/,nread/*0:01101*/,ret/*0:0111*/) (scanf_format_spec t/*0:101*/ s/*0:11*/) = u/*0:*/,nread/*8:01101*/+res/*4:*/,ret/*1:*/ when size/*0:01*/,s/*0:1*/ = if t/*0:101*/=="s" then guestimate/*1*/ s/*0:11*/ else 16,s/*0:11*/; buf/*0:*/ = check_buf/*2*/ (calloc size/*0:01*/ 1); res/*0:*/ = case t/*2:101*/ of "n" = pure_fscanf_int fp s/*2:1*/ buf/*1:*/; "d" = pure_sscanf_int u/*3:0101*/ s/*2:1*/ buf/*1:*/; "g" = pure_sscanf_double u/*3:0101*/ s/*2:1*/ buf/*1:*/; "s" = pure_sscanf_string u/*3:0101*/ s/*2:1*/ buf/*1:*/; "p" = pure_sscanf_pointer u/*3:0101*/ s/*2:1*/ buf/*1:*/; _/*0:*/ = throw (this_cant_happen ret/*3:0111*/) { - rule #0: "n" = pure_fscanf_int fp s buf +}; do_sscanf (u/*0:0101*/,nread/*0:01101*/,ret/*0:0111*/) (scanf_format_spec t/*0:101*/ s/*0:11*/) = u/*0:*/,nread/*8:01101*/+res/*4:*/,ret/*1:*/ when size/*0:01*/,s/*0:1*/ = if t/*0:101*/=="s" then guestimate/*1*/ s/*0:11*/ else 16,s/*0:11*/; buf/*0:*/ = check_buf/*2*/ (calloc size/*0:01*/ 1); res/*0:*/ = case t/*2:101*/ of "n" = pure_sscanf_int u/*3:0101*/ s/*2:1*/ buf/*1:*/; "d" = pure_sscanf_int u/*3:0101*/ s/*2:1*/ buf/*1:*/; "g" = pure_sscanf_double u/*3:0101*/ s/*2:1*/ buf/*1:*/; "s" = pure_sscanf_string u/*3:0101*/ s/*2:1*/ buf/*1:*/; "p" = pure_sscanf_pointer u/*3:0101*/ s/*2:1*/ buf/*1:*/; _/*0:*/ = throw (this_cant_happen ret/*3:0111*/) { + rule #0: "n" = pure_sscanf_int u s buf rule #1: "d" = pure_sscanf_int u s buf rule #2: "g" = pure_sscanf_double u s buf rule #3: "s" = pure_sscanf_string u s buf @@ -1113,7 +1113,7 @@ <var> state 1 state 1: #0 } { - rule #0: res = case t of "n" = pure_fscanf_int fp s buf; "d" = pure_sscanf_int u s buf; "g" = pure_sscanf_double u s buf; "s" = pure_sscanf_string u s buf; "p" = pure_sscanf_pointer u s buf; _ = throw (this_cant_happen ret) end + rule #0: res = case t of "n" = pure_sscanf_int u s buf; "d" = pure_sscanf_int u s buf; "g" = pure_sscanf_double u s buf; "s" = pure_sscanf_string u s buf; "p" = pure_sscanf_pointer u s buf; _ = throw (this_cant_happen ret) end state 0: #0 <var> state 1 state 1: #0 @@ -1151,7 +1151,7 @@ <var> state 1 state 1: #0 } end; do_sscanf (_/*0:0101*/,_/*0:01101*/,ret/*0:0111*/) _/*0:1*/ = throw (this_cant_happen ret/*0:0111*/) { - rule #0: do_sscanf (u,nread,ret) (scanf_format_spec t s) = u,nread+res,ret when size,s = if t=="s" then guestimate s else 16,s; buf = check_buf (calloc size 1); res = case t of "n" = pure_fscanf_int fp s buf; "d" = pure_sscanf_int u s buf; "g" = pure_sscanf_double u s buf; "s" = pure_sscanf_string u s buf; "p" = pure_sscanf_pointer u s buf; _ = throw (this_cant_happen ret) end; res = if res>=0 then res else throw (scanf_error ret) when _ = free buf end; val = case t of "n" = nread+get_int buf; "d" = get_int buf; "g" = get_double buf; "s" = cstring buf; "p" = get_pointer buf; _ = throw (this_cant_happen ret) end; _ = if t=="s" then () else free buf; ret = val:ret; u = drop res u end + rule #0: do_sscanf (u,nread,ret) (scanf_format_spec t s) = u,nread+res,ret when size,s = if t=="s" then guestimate s else 16,s; buf = check_buf (calloc size 1); res = case t of "n" = pure_sscanf_int u s buf; "d" = pure_sscanf_int u s buf; "g" = pure_sscanf_double u s buf; "s" = pure_sscanf_string u s buf; "p" = pure_sscanf_pointer u s buf; _ = throw (this_cant_happen ret) end; res = if res>=0 then res else throw (scanf_error ret) when _ = free buf end; val = case t of "n" = nread+get_int buf; "d" = get_int buf; "g" = get_double buf; "s" = cstring buf; "p" = get_pointer buf; _ = throw (this_cant_happen ret) end; _ = if t=="s" then () else free buf; ret = val:ret; u = drop res u end rule #1: do_sscanf (u,nread,ret) (scanf_format_str s) = u,nread+res,ret when res = pure_sscanf u s; ret = if res>=0 then ret else throw (scanf_error ret); u = drop res u end rule #2: do_sscanf (_,_,ret) _ = throw (this_cant_happen ret) state 0: #0 #1 #2 @@ -1970,7 +1970,7 @@ state 4: #0 } { - rule #0: sscanf s::string format::string = tuple$reverse ret when _,_,ret = catch error_handler (foldl do_sscanf (s,0,[])$scanf_split_format format) end with error_handler (scanf_error ret) = throw (scanf_error (tuple$reverse ret)); error_handler x = throw x; check_buf buf = throw scanf_malloc_error if null buf; check_buf buf = buf; guestimate format = n,format when 1,0,_,1,s = regex "^%([0-9]*)" REG_EXTENDED format 0; n,format = if null s then 1025,"%1024"+tail format else eval s+1,format end; do_sscanf (u,nread,ret) (scanf_format_spec t s) = u,nread+res,ret when size,s = if t=="s" then guestimate s else 16,s; buf = check_buf (calloc size 1); res = case t of "n" = pure_fscanf_int fp s buf; "d" = pure_sscanf_int u s buf; "g" = pure_sscanf_double u s buf; "s" = pure_sscanf_string u s buf; "p" = pure_sscanf_pointer u s buf; _ = throw (this_cant_happen ret) end; res = if res>=0 then res else throw (scanf_error ret) when _ = free buf end; val = case t of "n" = nread+get_int buf; "d" = get_int buf; "g" = get_double buf; "s" = cstring buf; "p" = get_pointer buf; _ = throw (this_cant_happen ret) end; _ = if t=="s" then () else free buf; ret = val:ret; u = drop res u end; do_sscanf (u,nread,ret) (scanf_format_str s) = u,nread+res,ret when res = pure_sscanf u s; ret = if res>=0 then ret else throw (scanf_error ret); u = drop res u end; do_sscanf (_,_,ret) _ = throw (this_cant_happen ret) end + rule #0: sscanf s::string format::string = tuple$reverse ret when _,_,ret = catch error_handler (foldl do_sscanf (s,0,[])$scanf_split_format format) end with error_handler (scanf_error ret) = throw (scanf_error (tuple$reverse ret)); error_handler x = throw x; check_buf buf = throw scanf_malloc_error if null buf; check_buf buf = buf; guestimate format = n,format when 1,0,_,1,s = regex "^%([0-9]*)" REG_EXTENDED format 0; n,format = if null s then 1025,"%1024"+tail format else eval s+1,format end; do_sscanf (u,nread,ret) (scanf_format_spec t s) = u,nread+res,ret when size,s = if t=="s" then guestimate s else 16,s; buf = check_buf (calloc size 1); res = case t of "n" = pure_sscanf_int u s buf; "d" = pure_sscanf_int u s buf; "g" = pure_sscanf_double u s buf; "s" = pure_sscanf_string u s buf; "p" = pure_sscanf_pointer u s buf; _ = throw (this_cant_happen ret) end; res = if res>=0 then res else throw (scanf_error ret) when _ = free buf end; val = case t of "n" = nread+get_int buf; "d" = get_int buf; "g" = get_double buf; "s" = cstring buf; "p" = get_pointer buf; _ = throw (this_cant_happen ret) end; _ = if t=="s" then () else free buf; ret = val:ret; u = drop res u end; do_sscanf (u,nread,ret) (scanf_format_str s) = u,nread+res,ret when res = pure_sscanf u s; ret = if res>=0 then ret else throw (scanf_error ret); u = drop res u end; do_sscanf (_,_,ret) _ = throw (this_cant_happen ret) end state 0: #0 <var>::string state 1 state 1: #0 @@ -2114,3 +2114,7 @@ () sscanf "this" "that"; <stdin>:7.0-19: unhandled exception 'scanf_error ()' while evaluating 'sscanf "this" "that"' +sscanf "this that" "this%n that%n"; +4,9 +sscanf "this that" "this%n%s%n"; +4,"that",9 Modified: pure/trunk/test/test011.pure =================================================================== --- pure/trunk/test/test011.pure 2008-05-24 19:30:07 UTC (rev 127) +++ pure/trunk/test/test011.pure 2008-05-24 19:58:42 UTC (rev 128) @@ -5,3 +5,5 @@ sscanf "this" "%p"; sscanf "this" "this"; sscanf "this" "that"; +sscanf "this that" "this%n that%n"; +sscanf "this that" "this%n%s%n"; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-25 05:42:39
|
Revision: 129 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=129&view=rev Author: agraef Date: 2008-05-24 22:42:48 -0700 (Sat, 24 May 2008) Log Message: ----------- Make toplevel if-then-else properly tail-recursive. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc pure/trunk/interpreter.hh pure/trunk/test/test004.log pure/trunk/test/test004.pure Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-24 19:58:42 UTC (rev 128) +++ pure/trunk/ChangeLog 2008-05-25 05:42:48 UTC (rev 129) @@ -1,3 +1,11 @@ +2008-05-25 Albert Graef <Dr....@t-...> + + * interpreter.cc: Make toplevel if-then-else properly + tail-recursive. Thus, e.g., the following function will now run in + constant stack space: count x = if x<=0 then x else count (x-1); + This also works with nested if-then-else constructs, as long as + they form the right-hand side of an equation. + 2008-05-24 Albert Graef <Dr....@t-...> * interpreter.cc, runtime.cc: Fix more memory allocation bugs in Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-05-24 19:58:42 UTC (rev 128) +++ pure/trunk/interpreter.cc 2008-05-25 05:42:48 UTC (rev 129) @@ -3197,6 +3197,15 @@ return 0; } +void interpreter::toplevel_codegen(expr x) +{ + assert(!x.is_null()); + if (x.tag() == EXPR::COND) + toplevel_cond(x.xval1(), x.xval2(), x.xval3()); + else + act_env().CreateRet(codegen(x)); +} + Value *interpreter::codegen(expr x) { assert(!x.is_null()); @@ -3487,6 +3496,40 @@ return phi; } +void interpreter::toplevel_cond(expr x, expr y, expr z) +{ + // emit tail-recursive code for a toplevel if-then-else + Env& f = act_env(); + assert(f.f!=0); + // emit the code for x + Value *iv = 0; + if (x.ttag() == EXPR::INT) + // optimize the case that x is an ::int (constant or application) + iv = get_int(x); + else if (x.ttag() != 0) { + // wrong type of constant; raise an exception + // XXXTODO: we might want to optionally invoke the debugger here + unwind(symtab.failed_cond_sym().f); + return; + } else + // typeless expression, will be checked at runtime + iv = get_int(x); + // emit the condition (turn the previous result into a flag) + Value *condv = f.builder.CreateICmpNE(iv, Zero, "cond"); + // create the basic blocks for the branches + BasicBlock *thenbb = new BasicBlock("then"); + BasicBlock *elsebb = new BasicBlock("else"); + // create the branch instruction and emit the 'then' block + f.builder.CreateCondBr(condv, thenbb, elsebb); + f.f->getBasicBlockList().push_back(thenbb); + f.builder.SetInsertPoint(thenbb); + toplevel_codegen(y); + // emit the 'else' block + f.f->getBasicBlockList().push_back(elsebb); + f.builder.SetInsertPoint(elsebb); + toplevel_codegen(z); +} + // Other value boxes. These just call primitives in the runtime which take // care of constructing these values. @@ -4321,11 +4364,11 @@ f.f->getBasicBlockList().push_back(matchedbb); f.builder.SetInsertPoint(matchedbb); #if DEBUG>1 - if (!f.name.empty()) { ostringstream msg; - msg << "exit " << f.name << ", result: " << pm->r[0].rhs; - debug(msg.str().c_str()); } + if (!f.name.empty()) { ostringstream msg; + msg << "exit " << f.name << ", result: " << pm->r[0].rhs; + debug(msg.str().c_str()); } #endif - f.CreateRet(codegen(pm->r[0].rhs)); + toplevel_codegen(pm->r[0].rhs); } else { // build the initial stack of expressions to be matched list<Value*>xs; @@ -4607,7 +4650,7 @@ msg << "exit " << f.name << ", result: " << rr.rhs; debug(msg.str().c_str()); } #endif - f.CreateRet(codegen(rr.rhs)); + toplevel_codegen(rr.rhs); break; } // check the guard @@ -4647,7 +4690,7 @@ msg << "exit " << f.name << ", result: " << rr.rhs; debug(msg.str().c_str()); } #endif - f.CreateRet(codegen(rr.rhs)); + toplevel_codegen(rr.rhs); rulebb = nextbb; } if (f.fmap.size() > 1) f.fmap_idx = 0; Modified: pure/trunk/interpreter.hh =================================================================== --- pure/trunk/interpreter.hh 2008-05-24 19:58:42 UTC (rev 128) +++ pure/trunk/interpreter.hh 2008-05-25 05:42:48 UTC (rev 129) @@ -416,6 +416,7 @@ pure_expr *doeval(expr x, pure_expr*& e); pure_expr *dodefn(env vars, expr lhs, expr rhs, pure_expr*& e); llvm::Value *codegen(expr x); + void toplevel_codegen(expr x); llvm::Value *builtin_codegen(expr x); llvm::Value *get_int(expr x); llvm::Value *get_double(expr x); @@ -428,6 +429,7 @@ llvm::Value *call(llvm::Value *x); llvm::Value *apply(llvm::Value *x, llvm::Value *y); llvm::Value *cond(expr x, expr y, expr z); + void toplevel_cond(expr x, expr y, expr z); llvm::Value *fbox(Env& f, bool thunked = false); llvm::Value *cbox(int32_t tag); llvm::Value *ibox(llvm::Value *i); Modified: pure/trunk/test/test004.log =================================================================== --- pure/trunk/test/test004.log 2008-05-24 19:58:42 UTC (rev 128) +++ pure/trunk/test/test004.log 2008-05-25 05:42:48 UTC (rev 129) @@ -75,6 +75,15 @@ } count2 100; 0 +count3 n/*0:1*/::int = if n/*0:1*/<=0 then n/*0:1*/ else count3 (n/*0:1*/-1); +{ + rule #0: count3 n::int = if n<=0 then n else count3 (n-1) + state 0: #0 + <var>::int state 1 + state 1: #0 +} +count3 100; +0 test x/*0:1*/::int = t/*0*/ x/*0:1*/ with t n/*0:1*/::int = t/*1*/ (-n/*0:1*/) if n/*0:1*/<0; t n/*0:1*/::int = u/*0*/ (n/*0:1*/+2) with u _/*0:1*/ = n/*1:1*/+1 { rule #0: u _ = n+1 state 0: #0 Modified: pure/trunk/test/test004.pure =================================================================== --- pure/trunk/test/test004.pure 2008-05-24 19:58:42 UTC (rev 128) +++ pure/trunk/test/test004.pure 2008-05-25 05:42:48 UTC (rev 129) @@ -35,12 +35,17 @@ count2 n::int = n if n<=0; = count2 (n-1) otherwise; -// This should always work. count2 100; -// Again, this should work if proper tail calls are supported, no matter what -// your stack size is. //count2 10000000; +// Definitions involving toplevel if-then-else are properly tail-recursive as +// well. + +count3 n::int = if n<=0 then n else count3 (n-1); + +count3 100; +//count3 10000000; + // Trivial tail-recursive local function which passes an environment to // another local function. Note that the callee can never be tail-called in // such a situation because it needs the extra environment parameter which is This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-25 07:00:35
|
Revision: 131 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=131&view=rev Author: agraef Date: 2008-05-25 00:00:36 -0700 (Sun, 25 May 2008) Log Message: ----------- Make 'all' and 'any' tail-recursive. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/lib/prelude.pure Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-25 06:06:17 UTC (rev 130) +++ pure/trunk/ChangeLog 2008-05-25 07:00:36 UTC (rev 131) @@ -1,5 +1,7 @@ 2008-05-25 Albert Graef <Dr....@t-...> + * lib/prelude.pure: Make 'all' and 'any' tail-recursive. + * interpreter.cc: Make toplevel if-then-else properly tail-recursive. Thus, e.g., the following function will now run in constant stack space: count x = if x<=0 then x else count (x-1); Modified: pure/trunk/lib/prelude.pure =================================================================== --- pure/trunk/lib/prelude.pure 2008-05-25 06:06:17 UTC (rev 130) +++ pure/trunk/lib/prelude.pure 2008-05-25 07:00:36 UTC (rev 131) @@ -173,10 +173,10 @@ functions have slightly different names). */ all p [] = 1; -all p (x:xs) = p x && all p xs; +all p (x:xs) = if p x then all p xs else 0; any p [] = 0; -any p (x:xs) = p x || any p xs; +any p (x:xs) = if p x then 1 else any p xs; do f [] = (); do f (x:xs) = do f xs when _ = f x end; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-25 15:56:18
|
Revision: 134 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=134&view=rev Author: agraef Date: 2008-05-25 08:56:23 -0700 (Sun, 25 May 2008) Log Message: ----------- Add marshalling between 64 bit ints and Pure bigints to the C interface. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-25 09:14:26 UTC (rev 133) +++ pure/trunk/ChangeLog 2008-05-25 15:56:23 UTC (rev 134) @@ -1,5 +1,14 @@ 2008-05-25 Albert Graef <Dr....@t-...> + * interpreter.cc, runtime.cc: Add marshalling between long (64 + bit) ints and Pure bigints in the C interface. This means that + both Pure ints and bigints can now be passed for 'long' arguments + of externals (with sign extension/truncation as necessary), and + 'long' values are promoted to Pure bigints on return. Hence C + functions taking 64 bit integers as arguments and returning them + as results can now be called from Pure without loosing bits due to + truncation. + * lib/prelude.pure: Make 'all' and 'any' tail-recursive. * interpreter.cc: Make toplevel if-then-else properly @@ -74,9 +83,7 @@ Please note that the typename 'long' *always* denotes signed 64 bit integers in Pure's extern declarations, even if the C 'long' type is actually 32 bit (as it usually is even on most 64 bit - systems). Also note that at present 'long' is still converted - to/from Pure (32 bit) ints only, marshalling from/to Pure bigints - is not supported yet. + systems). 2008-05-16 Albert Graef <Dr....@t-...> Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-05-25 09:14:26 UTC (rev 133) +++ pure/trunk/interpreter.cc 2008-05-25 15:56:23 UTC (rev 134) @@ -199,6 +199,8 @@ "pure_const", "expr*", 1, "int"); declare_extern((void*)pure_int, "pure_int", "expr*", 1, "int"); + declare_extern((void*)pure_long, + "pure_long", "expr*", 1, "long"); declare_extern((void*)pure_bigint, "pure_bigint", "expr*", 2, "int", sizeof(mp_limb_t)==8?"long*":"int*"); @@ -224,6 +226,8 @@ "pure_free_cstrings", "void", 0); declare_extern((void*)pure_get_bigint, "pure_get_bigint", "void*", 1, "expr*"); + declare_extern((void*)pure_get_long, + "pure_get_long", "long", 1, "expr*"); declare_extern((void*)pure_catch, "pure_catch", "expr*", 2, "expr*", "expr*"); @@ -2224,8 +2228,8 @@ } // External C function visible in the Pure program. No varargs are allowed // here for now. Also, we have to translate some of the parameter types - // (expr** becomes void*, int32_t gets promoted in64_t if the default int - // type of the target platform has 64 bit). + // (expr** becomes void*, int32_t gets promoted to int64_t if the default + // int type of the target platform has 64 bit). assert(!varargs); if (type == ExprPtrPtrTy) type = VoidPtrTy; @@ -2388,17 +2392,33 @@ Value *iv = b.CreateLoad(b.CreateGEP(pv, idx, idx+2), "intval"); unboxed[i] = iv; } else if (argt[i] == Type::Int64Ty) { + BasicBlock *intbb = new BasicBlock("int"); + BasicBlock *mpzbb = new BasicBlock("mpz"); BasicBlock *okbb = new BasicBlock("ok"); Value *idx[2] = { Zero, Zero }; Value *tagv = b.CreateLoad(b.CreateGEP(x, idx, idx+2), "tag"); - b.CreateCondBr - (b.CreateICmpEQ(tagv, SInt(EXPR::INT), "cmp"), okbb, failedbb); - f->getBasicBlockList().push_back(okbb); - b.SetInsertPoint(okbb); + SwitchInst *sw = b.CreateSwitch(tagv, failedbb, 2); + /* We allow either ints or bigints to be passed for a long value. */ + sw->addCase(SInt(EXPR::INT), intbb); + sw->addCase(SInt(EXPR::BIGINT), mpzbb); + f->getBasicBlockList().push_back(intbb); + b.SetInsertPoint(intbb); Value *pv = b.CreateBitCast(x, IntExprPtrTy, "intexpr"); idx[1] = ValFldIndex; Value *iv = b.CreateLoad(b.CreateGEP(pv, idx, idx+2), "intval"); - unboxed[i] = b.CreateSExt(iv, Type::Int64Ty); + Value *intv = b.CreateSExt(iv, Type::Int64Ty); + b.CreateBr(okbb); + f->getBasicBlockList().push_back(mpzbb); + b.SetInsertPoint(mpzbb); + // Handle the case of a bigint (mpz_t -> long). + Value *mpzv = b.CreateCall(module->getFunction("pure_get_long"), x); + b.CreateBr(okbb); + f->getBasicBlockList().push_back(okbb); + b.SetInsertPoint(okbb); + PHINode *phi = b.CreatePHI(Type::Int64Ty); + phi->addIncoming(intv, intbb); + phi->addIncoming(mpzv, mpzbb); + unboxed[i] = phi; } else if (argt[i] == Type::DoubleTy) { BasicBlock *okbb = new BasicBlock("ok"); Value *idx[2] = { Zero, Zero }; @@ -2478,8 +2498,7 @@ // An external builtin already has this parameter declared as char*. // We allow void* to be passed anyway, so just cast it to char* to // make the LLVM typechecker happy. - unboxed[i] = b.CreateBitCast - (unboxed[i], CharPtrTy); + unboxed[i] = b.CreateBitCast(unboxed[i], CharPtrTy); } else assert(0 && "invalid C type"); } @@ -2504,8 +2523,7 @@ else if (type == Type::Int32Ty) u = b.CreateCall(module->getFunction("pure_int"), u); else if (type == Type::Int64Ty) - u = b.CreateCall(module->getFunction("pure_int"), - b.CreateTrunc(u, Type::Int32Ty)); + u = b.CreateCall(module->getFunction("pure_long"), u); else if (type == Type::DoubleTy) u = b.CreateCall(module->getFunction("pure_double"), u); else if (type == CharPtrTy) Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-05-25 09:14:26 UTC (rev 133) +++ pure/trunk/runtime.cc 2008-05-25 15:56:23 UTC (rev 134) @@ -340,6 +340,22 @@ return x; } +extern "C" +pure_expr *pure_long(int64_t l) +{ + int sgn = (l>0)?1:(l<0)?-1:0; + uint64_t v = (uint64_t)(l>=0?l:-l); + if (sizeof(mp_limb_t) == 8) { + // 8 byte limbs, value fits in a single limb. + limb_t u[1] = { v }; + return pure_bigint(sgn, u); + } else { + // 4 byte limbs, put least significant word in the first limb. + limb_t u[2] = { (uint32_t)v, (uint32_t)(v>>32) }; + return pure_bigint(sgn+sgn, u); + } +} + static void make_bigint(mpz_t z, int32_t size, limb_t *limbs) { // FIXME: For efficiency, we poke directly into the mpz struct here, this @@ -466,6 +482,7 @@ return s; } +extern "C" void pure_free_cstrings() { for (list<char*>::iterator t = temps.begin(); t != temps.end(); t++) @@ -473,6 +490,18 @@ temps.clear(); } +extern "C" +int64_t pure_get_long(pure_expr *x) +{ + uint64_t v = + (sizeof(mp_limb_t) == 8) ? (uint64_t)mpz_getlimbn(x->data.z, 0) : + (mpz_getlimbn(x->data.z, 0) + + (((uint64_t)mpz_getlimbn(x->data.z, 1))<<32)); + cerr << "v = " << v << endl; + return (mpz_sgn(x->data.z) < 0) ? -(int64_t)v : (int64_t)v; +} + +extern "C" void *pure_get_bigint(pure_expr *x) { assert(x && x->tag == EXPR::BIGINT); Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-05-25 09:14:26 UTC (rev 133) +++ pure/trunk/runtime.h 2008-05-25 15:56:23 UTC (rev 134) @@ -63,6 +63,7 @@ void *f, void *e, uint32_t m, /* m x pure_expr* */ ...); pure_expr *pure_const(int32_t tag); pure_expr *pure_int(int32_t i); +pure_expr *pure_long(int64_t l); pure_expr *pure_bigint(int32_t size, limb_t *limbs); pure_expr *pure_mpz(mpz_t z); pure_expr *pure_double(double d); @@ -95,11 +96,11 @@ char *pure_get_cstring(pure_expr *x); void pure_free_cstrings(); -/* Get a pointer to the mpz_t value of a bigint expression which can be passed - to the GMP routines. This is used to unbox bigint arguments and map them to - void* in the C interface. */ +/* Convert a bigint expression to a pointer (mpz_t) or a long (64 bit) + integer. This is used to marshall bigint arguments in the C interface. */ void *pure_get_bigint(pure_expr *x); +int64_t pure_get_long(pure_expr *x); /* Execute a closure. If the given expression x (or x y in the case of pure_apply) is a parameterless closure (or a saturated application of a This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-05-25 21:14:04
|
Revision: 136 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=136&view=rev Author: agraef Date: 2008-05-25 14:14:08 -0700 (Sun, 25 May 2008) Log Message: ----------- Rewrite prelude operations to make them tail-recursive. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/lib/prelude.pure pure/trunk/test/prelude.log Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-25 16:01:10 UTC (rev 135) +++ pure/trunk/ChangeLog 2008-05-25 21:14:08 UTC (rev 136) @@ -1,5 +1,8 @@ 2008-05-25 Albert Graef <Dr....@t-...> + * lib/prelude.pure: Rewrite prelude operations to make them + tail-recursive. + * interpreter.cc, runtime.cc: Add marshalling between long (64 bit) ints and Pure bigints in the C interface. This means that both Pure ints and bigints can now be passed for 'long' arguments @@ -9,8 +12,6 @@ as results can now be called from Pure without loosing bits due to truncation. - * lib/prelude.pure: Make 'all' and 'any' tail-recursive. - * interpreter.cc: Make toplevel if-then-else properly tail-recursive. Thus, e.g., the following function will now run in constant stack space: count x = if x<=0 then x else count (x-1); Modified: pure/trunk/lib/prelude.pure =================================================================== --- pure/trunk/lib/prelude.pure 2008-05-25 16:01:10 UTC (rev 135) +++ pure/trunk/lib/prelude.pure 2008-05-25 21:14:08 UTC (rev 136) @@ -77,9 +77,14 @@ /* Poor man's tuples(TM). These are constructed with the pairing operator ',', are always flat and associate to the right. The empty tuple, denoted (), is neutral with respect to ','. Operations are provided to test for equality/ - inequality and emptiness, to determine the size of a tuple, and for - zero-based indexing. */ + inequality and emptiness, to determine the size of a tuple, for zero-based + indexing, and to reverse a tuple. */ +/* Note: Some of these definitions aren't exactly pretty. They are what they + are because they are the most efficient (at least asymptotically). In + particular, we strive for tail-recursive and constant or linear-time + implementations where this is feasible. */ + x,() = x; (),y = y; (x,y),z = x,(y,z); @@ -87,64 +92,94 @@ ()==() = 1; (x,xs)==() = 0; ()==(x,xs) = 0; -(x,xs)==(y,ys) = x==y && xs==ys; +(x,xs)==(y,ys) = if x==y then xs==ys else 0; ()!=() = 0; (x,xs)!=() = 1; ()!=(x,xs) = 1; -(x,xs)!=(y,ys) = x!=y || xs!=ys; +(x,xs)!=(y,ys) = if x!=y then 1 else xs!=ys; null () = 1; null (x,xs) = 0; #() = 0; -#(x,y,xs) = 1+#(y,xs); -#(x,y) = 2 otherwise; +#(x,xs) = accum 1 xs with + accum n::int (x,xs) = accum (n+1) xs; + accum n::int x = n+1; +end; (x,xs)!0 = x; (x,y,xs)!n::int = (y,xs)!(n-1) if n>0; (x,y)!1 = y; +reverse () = (); +reverse (x,xs) = accum x xs with + accum ys (x,xs) = accum (x,ys) xs; + accum ys x = x,ys; +end; + /* Lists are the usual "conses" written using the infix ':' operator. '[]' denotes the empty list. Moreover, the parser provides the customary sugar for proper list values [x] where x is any singleton or tuple (in the latter case you'll get a list made from all the elements of x). The usual basic operations are provided to test for equality/inequality and emptiness, to - compute the size of a list, and for indexing and concatenation. We also - provide two frequently used operations to reverse a list and to concatenate - a list of lists. */ + compute the size of a list, for indexing and concatenation, and for + reversing a list. */ +/* Note: Some list operations throw a 'bad_list_value xs' exception if their + argument is not a "proper" list (i.e., ending in []). In this case xs + denotes the offending tail of the list. */ + []==[] = 1; (x:xs)==[] = 0; []==(x:xs) = 0; -(x:xs)==(y:ys) = x==y && xs==ys; +(x:xs)==(y:ys) = if x==y then xs==ys else 1; []!=[] = 0; (x:xs)!=[] = 1; []!=(x:xs) = 1; -(x:xs)!=(y:ys) = x!=y || xs!=ys; +(x:xs)!=(y:ys) = if x!=y then 1 else xs!=ys; null [] = 1; null (x:xs) = 0; #[] = 0; -#(x:xs) = 1+#xs; +#(x:xs) = accum 1 xs with + accum n::int (x:xs) = accum (n+1) xs; + accum n::int [] = n; + accum _ xs = throw (bad_list_value xs); +end; (x:xs)!0 = x; (x:xs)!n::int = xs!(n-1) if n>0; []+ys = ys; -(x:xs)+ys = x:xs+ys; +(x:xs)+ys = x : accum ys (reverse xs) with + accum ys (x:xs) = accum (x:ys) xs; + accum ys [] = ys; +end; +reverse [] = []; +reverse (x:xs) = accum [x] xs with + accum ys (x:xs) = accum (x:ys) xs; + accum ys [] = ys; + accum _ xs = throw (bad_list_value xs); +end; + /* Convert between lists and tuples. */ list () = []; -list (x,y,xs) = x:list (y,xs); -list (x,y) = [x,y]; +list (x,xs) = accum [x] xs with + accum ys (x,xs) = accum (x:ys) xs; + accum ys x = reverse (x:ys); +end; tuple [] = (); -tuple [x] = x; -tuple (x:y:xs) = x,tuple (y:xs); +tuple (x:xs) = accum x xs with + accum ys (x:xs) = accum (x,ys) xs; + accum ys [] = if tuplep ys then reverse ys else ys; + accum _ xs = throw (bad_list_value xs); +end; /* Slicing. xs!ns returns the list of xs!n for all members n of the index list ns which are in the range 0..#xs-1. This works on any data structure with @@ -152,12 +187,11 @@ structures defined above. */ xs![] = []; -xs!(n::int:ns) = slice xs (n:ns) with - slice xs [] = []; - slice xs (n::int:ns) - = xs!n:slice xs ns if n>=0 && n<m; - = xs!ns otherwise; - end when m::int = #xs end; +xs!(n:ns) = accum [] xs (reverse (n:ns)) (#xs) with + accum ys xs [] m = ys; + accum ys xs (n::int:ns) m = accum (xs!n:ys) xs ns m if n>=0 && n<m; + = accum ys xs ns m otherwise; +end; /* Arithmetic sequences. */ @@ -245,41 +279,46 @@ = x:takewhile p xs if p x; = [] otherwise; -/* Concatenate a list of lists in both linear time and constant space. */ +/* Concatenate a list of lists. */ cat [] = []; cat (xs:xss) = accum (reverse xs) xss with accum xs [] = reverse xs; accum xs ([]:yss) = accum xs yss; accum xs ((y:ys):yss) = accum (y:xs) (ys:yss); - accum xs yss = reverse xs+cat yss otherwise; -end if listp xs; + accum _ (ys:_) = throw (bad_list_value ys); + accum _ yss = throw (bad_list_value yss); +end; /* Combine cat and map. This is used by list comprehensions. */ catmap f xs = cat (map f xs); -/* Reverse a list (must be a proper list). */ - -reverse xs = foldl (flip (:)) [] xs if listp xs; - /* Some useful list generators. */ -repeat n x = [] if n<=0; - = x:repeat (n-1) x otherwise; +repeat n::int x = accum [] n x with + accum xs n::int x = xs if n<=0; + = accum (x:xs) (n-1) x; +end; -cycle n [] = []; -cycle n (x:xs) = [] if n<=0; - = mkcycle n xs with - mkcycle n xs = take n xs if n<=m; - = xs+mkcycle (n-m) xs otherwise; - end when xs = x:xs; m = #xs end; +cycle n::int [] = []; +cycle n::int (x:xs) + = [] if n<=0; + = accum [] (#xs) n xs with + accum ys m::int n::int xs + = cat ys+take n xs if n<=m; + = accum (xs:ys) m (n-m) xs otherwise; + end when xs = x:xs end; -while p f a = a:while p f (f a) if p a; - = [] otherwise; +while p f a = accum [] p f a with + accum as p f a = accum (a:as) p f (f a) if p a; + = reverse as otherwise; + end; -until p f a = [] if p a; - = a:until p f (f a) otherwise; +until p f a = accum [] p f a with + accum as p f a = reverse as if p a; + = accum (a:as) p f (f a) otherwise; + end; /* zip, unzip and friends. */ Modified: pure/trunk/test/prelude.log =================================================================== --- pure/trunk/test/prelude.log 2008-05-25 16:01:10 UTC (rev 135) +++ pure/trunk/test/prelude.log 2008-05-25 21:14:08 UTC (rev 136) @@ -334,66 +334,267 @@ ()==() = 1; (x/*0:0101*/,xs/*0:011*/)==() = 0; ()==(x/*0:101*/,xs/*0:11*/) = 0; -(x/*0:0101*/,xs/*0:011*/)==(y/*0:101*/,ys/*0:11*/) = x/*0:0101*/==y/*0:101*/&&xs/*0:011*/==ys/*0:11*/; +(x/*0:0101*/,xs/*0:011*/)==(y/*0:101*/,ys/*0:11*/) = if x/*0:0101*/==y/*0:101*/ then xs/*0:011*/==ys/*0:11*/ else 0; ()!=() = 0; (x/*0:0101*/,xs/*0:011*/)!=() = 1; ()!=(x/*0:101*/,xs/*0:11*/) = 1; -(x/*0:0101*/,xs/*0:011*/)!=(y/*0:101*/,ys/*0:11*/) = x/*0:0101*/!=y/*0:101*/||xs/*0:011*/!=ys/*0:11*/; +(x/*0:0101*/,xs/*0:011*/)!=(y/*0:101*/,ys/*0:11*/) = if x/*0:0101*/!=y/*0:101*/ then 1 else xs/*0:011*/!=ys/*0:11*/; null () = 1; null (x/*0:101*/,xs/*0:11*/) = 0; #() = 0; -#(x/*0:101*/,y/*0:1101*/,xs/*0:111*/) = 1+#(y/*0:1101*/,xs/*0:111*/); -#(x/*0:101*/,y/*0:11*/) = 2; +#(x/*0:101*/,xs/*0:11*/) = accum/*0*/ 1 xs/*0:11*/ with accum n/*0:01*/::int (x/*0:101*/,xs/*0:11*/) = accum/*1*/ (n/*0:01*/+1) xs/*0:11*/; accum n/*0:01*/::int x/*0:1*/ = n/*0:01*/+1 { + rule #0: accum n::int (x,xs) = accum (n+1) xs + rule #1: accum n::int x = n+1 + state 0: #0 #1 + <var>::int state 1 + state 1: #0 #1 + <var> state 2 + <app> state 3 + state 2: #1 + state 3: #0 #1 + <var> state 4 + <app> state 6 + state 4: #1 + <var> state 5 + state 5: #1 + state 6: #0 #1 + <var> state 7 + , state 10 + state 7: #1 + <var> state 8 + state 8: #1 + <var> state 9 + state 9: #1 + state 10: #0 #1 + <var> state 11 + state 11: #0 #1 + <var> state 12 + state 12: #0 #1 +} end; (x/*0:0101*/,xs/*0:011*/)!0 = x/*0:0101*/; (x/*0:0101*/,y/*0:01101*/,xs/*0:0111*/)!n/*0:1*/::int = (y/*0:01101*/,xs/*0:0111*/)!(n/*0:1*/-1) if n/*0:1*/>0; (x/*0:0101*/,y/*0:011*/)!1 = y/*0:011*/; +reverse () = (); +reverse (x/*0:101*/,xs/*0:11*/) = accum/*0*/ x/*0:101*/ xs/*0:11*/ with accum ys/*0:01*/ (x/*0:101*/,xs/*0:11*/) = accum/*1*/ (x/*0:101*/,ys/*0:01*/) xs/*0:11*/; accum ys/*0:01*/ x/*0:1*/ = x/*0:1*/,ys/*0:01*/ { + rule #0: accum ys (x,xs) = accum (x,ys) xs + rule #1: accum ys x = x,ys + state 0: #0 #1 + <var> state 1 + state 1: #0 #1 + <var> state 2 + <app> state 3 + state 2: #1 + state 3: #0 #1 + <var> state 4 + <app> state 6 + state 4: #1 + <var> state 5 + state 5: #1 + state 6: #0 #1 + <var> state 7 + , state 10 + state 7: #1 + <var> state 8 + state 8: #1 + <var> state 9 + state 9: #1 + state 10: #0 #1 + <var> state 11 + state 11: #0 #1 + <var> state 12 + state 12: #0 #1 +} end; []==[] = 1; x/*0:0101*/:xs/*0:011*/==[] = 0; []==x/*0:101*/:xs/*0:11*/ = 0; -x/*0:0101*/:xs/*0:011*/==y/*0:101*/:ys/*0:11*/ = x/*0:0101*/==y/*0:101*/&&xs/*0:011*/==ys/*0:11*/; +x/*0:0101*/:xs/*0:011*/==y/*0:101*/:ys/*0:11*/ = if x/*0:0101*/==y/*0:101*/ then xs/*0:011*/==ys/*0:11*/ else 1; []!=[] = 0; x/*0:0101*/:xs/*0:011*/!=[] = 1; []!=x/*0:101*/:xs/*0:11*/ = 1; -x/*0:0101*/:xs/*0:011*/!=y/*0:101*/:ys/*0:11*/ = x/*0:0101*/!=y/*0:101*/||xs/*0:011*/!=ys/*0:11*/; +x/*0:0101*/:xs/*0:011*/!=y/*0:101*/:ys/*0:11*/ = if x/*0:0101*/!=y/*0:101*/ then 1 else xs/*0:011*/!=ys/*0:11*/; null [] = 1; null (x/*0:101*/:xs/*0:11*/) = 0; #[] = 0; -#(x/*0:101*/:xs/*0:11*/) = 1+#xs/*0:11*/; +#(x/*0:101*/:xs/*0:11*/) = accum/*0*/ 1 xs/*0:11*/ with accum n/*0:01*/::int (x/*0:101*/:xs/*0:11*/) = accum/*1*/ (n/*0:01*/+1) xs/*0:11*/; accum n/*0:01*/::int [] = n/*0:01*/; accum _/*0:01*/ xs/*0:1*/ = throw (bad_list_value xs/*0:1*/) { + rule #0: accum n::int (x:xs) = accum (n+1) xs + rule #1: accum n::int [] = n + rule #2: accum _ xs = throw (bad_list_value xs) + state 0: #0 #1 #2 + <var> state 1 + <var>::int state 3 + state 1: #2 + <var> state 2 + state 2: #2 + state 3: #0 #1 #2 + <var> state 4 + <app> state 5 + [] state 15 + state 4: #2 + state 5: #0 #2 + <var> state 6 + <app> state 8 + state 6: #2 + <var> state 7 + state 7: #2 + state 8: #0 #2 + <var> state 9 + : state 12 + state 9: #2 + <var> state 10 + state 10: #2 + <var> state 11 + state 11: #2 + state 12: #0 #2 + <var> state 13 + state 13: #0 #2 + <var> state 14 + state 14: #0 #2 + state 15: #1 #2 +} end; (x/*0:0101*/:xs/*0:011*/)!0 = x/*0:0101*/; (x/*0:0101*/:xs/*0:011*/)!n/*0:1*/::int = xs/*0:011*/!(n/*0:1*/-1) if n/*0:1*/>0; []+ys/*0:1*/ = ys/*0:1*/; -(x/*0:0101*/:xs/*0:011*/)+ys/*0:1*/ = x/*0:0101*/:xs/*0:011*/+ys/*0:1*/; +(x/*0:0101*/:xs/*0:011*/)+ys/*0:1*/ = x/*0:0101*/:accum/*0*/ ys/*0:1*/ (reverse xs/*0:011*/) with accum ys/*0:01*/ (x/*0:101*/:xs/*0:11*/) = accum/*1*/ (x/*0:101*/:ys/*0:01*/) xs/*0:11*/; accum ys/*0:01*/ [] = ys/*0:01*/ { + rule #0: accum ys (x:xs) = accum (x:ys) xs + rule #1: accum ys [] = ys + state 0: #0 #1 + <var> state 1 + state 1: #0 #1 + <app> state 2 + [] state 7 + state 2: #0 + <app> state 3 + state 3: #0 + : state 4 + state 4: #0 + <var> state 5 + state 5: #0 + <var> state 6 + state 6: #0 + state 7: #1 +} end; +reverse [] = []; +reverse (x/*0:101*/:xs/*0:11*/) = accum/*0*/ [x/*0:101*/] xs/*0:11*/ with accum ys/*0:01*/ (x/*0:101*/:xs/*0:11*/) = accum/*1*/ (x/*0:101*/:ys/*0:01*/) xs/*0:11*/; accum ys/*0:01*/ [] = ys/*0:01*/; accum _/*0:01*/ xs/*0:1*/ = throw (bad_list_value xs/*0:1*/) { + rule #0: accum ys (x:xs) = accum (x:ys) xs + rule #1: accum ys [] = ys + rule #2: accum _ xs = throw (bad_list_value xs) + state 0: #0 #1 #2 + <var> state 1 + state 1: #0 #1 #2 + <var> state 2 + <app> state 3 + [] state 13 + state 2: #2 + state 3: #0 #2 + <var> state 4 + <app> state 6 + state 4: #2 + <var> state 5 + state 5: #2 + state 6: #0 #2 + <var> state 7 + : state 10 + state 7: #2 + <var> state 8 + state 8: #2 + <var> state 9 + state 9: #2 + state 10: #0 #2 + <var> state 11 + state 11: #0 #2 + <var> state 12 + state 12: #0 #2 + state 13: #1 #2 +} end; list () = []; -list (x/*0:101*/,y/*0:1101*/,xs/*0:111*/) = x/*0:101*/:list (y/*0:1101*/,xs/*0:111*/); -list (x/*0:101*/,y/*0:11*/) = [x/*0:101*/,y/*0:11*/]; +list (x/*0:101*/,xs/*0:11*/) = accum/*0*/ [x/*0:101*/] xs/*0:11*/ with accum ys/*0:01*/ (x/*0:101*/,xs/*0:11*/) = accum/*1*/ (x/*0:101*/:ys/*0:01*/) xs/*0:11*/; accum ys/*0:01*/ x/*0:1*/ = reverse (x/*0:1*/:ys/*0:01*/) { + rule #0: accum ys (x,xs) = accum (x:ys) xs + rule #1: accum ys x = reverse (x:ys) + state 0: #0 #1 + <var> state 1 + state 1: #0 #1 + <var> state 2 + <app> state 3 + state 2: #1 + state 3: #0 #1 + <var> state 4 + <app> state 6 + state 4: #1 + <var> state 5 + state 5: #1 + state 6: #0 #1 + <var> state 7 + , state 10 + state 7: #1 + <var> state 8 + state 8: #1 + <var> state 9 + state 9: #1 + state 10: #0 #1 + <var> state 11 + state 11: #0 #1 + <var> state 12 + state 12: #0 #1 +} end; tuple [] = (); -tuple [x/*0:101*/] = x/*0:101*/; -tuple (x/*0:101*/:y/*0:1101*/:xs/*0:111*/) = x/*0:101*/,tuple (y/*0:1101*/:xs/*0:111*/); +tuple (x/*0:101*/:xs/*0:11*/) = accum/*0*/ x/*0:101*/ xs/*0:11*/ with accum ys/*0:01*/ (x/*0:101*/:xs/*0:11*/) = accum/*1*/ (x/*0:101*/,ys/*0:01*/) xs/*0:11*/; accum ys/*0:01*/ [] = if tuplep ys/*0:01*/ then reverse ys/*0:01*/ else ys/*0:01*/; accum _/*0:01*/ xs/*0:1*/ = throw (bad_list_value xs/*0:1*/) { + rule #0: accum ys (x:xs) = accum (x,ys) xs + rule #1: accum ys [] = if tuplep ys then reverse ys else ys + rule #2: accum _ xs = throw (bad_list_value xs) + state 0: #0 #1 #2 + <var> state 1 + state 1: #0 #1 #2 + <var> state 2 + <app> state 3 + [] state 13 + state 2: #2 + state 3: #0 #2 + <var> state 4 + <app> state 6 + state 4: #2 + <var> state 5 + state 5: #2 + state 6: #0 #2 + <var> state 7 + : state 10 + state 7: #2 + <var> state 8 + state 8: #2 + <var> state 9 + state 9: #2 + state 10: #0 #2 + <var> state 11 + state 11: #0 #2 + <var> state 12 + state 12: #0 #2 + state 13: #1 #2 +} end; xs/*0:01*/![] = []; -xs/*0:01*/!(n/*0:101*/::int:ns/*0:11*/) = slice/*0*/ xs/*1:01*/ (n/*1:101*/:ns/*1:11*/) with slice xs/*0:01*/ [] = []; slice xs/*0:01*/ (n/*0:101*/::int:ns/*0:11*/) = xs/*0:01*/!n/*0:101*/:slice/*1*/ xs/*0:01*/ ns/*0:11*/ if n/*0:101*/>=0&&n/*0:101*/<m/*1:*/; slice xs/*0:01*/ (n/*0:101*/::int:ns/*0:11*/) = xs/*0:01*/!ns/*0:11*/ { - rule #0: slice xs [] = [] - rule #1: slice xs (n::int:ns) = xs!n:slice xs ns if n>=0&&n<m - rule #2: slice xs (n::int:ns) = xs!ns +xs/*0:01*/!(n/*0:101*/:ns/*0:11*/) = accum/*0*/ [] xs/*0:01*/ (reverse (n/*0:101*/:ns/*0:11*/)) (#xs/*0:01*/) with accum ys/*0:0001*/ xs/*0:001*/ [] m/*0:1*/ = ys/*0:0001*/; accum ys/*0:0001*/ xs/*0:001*/ (n/*0:0101*/::int:ns/*0:011*/) m/*0:1*/ = accum/*1*/ (xs/*0:001*/!n/*0:0101*/:ys/*0:0001*/) xs/*0:001*/ ns/*0:011*/ m/*0:1*/ if n/*0:0101*/>=0&&n/*0:0101*/<m/*0:1*/; accum ys/*0:0001*/ xs/*0:001*/ (n/*0:0101*/::int:ns/*0:011*/) m/*0:1*/ = accum/*1*/ ys/*0:0001*/ xs/*0:001*/ ns/*0:011*/ m/*0:1*/ { + rule #0: accum ys xs [] m = ys + rule #1: accum ys xs (n::int:ns) m = accum (xs!n:ys) xs ns m if n>=0&&n<m + rule #2: accum ys xs (n::int:ns) m = accum ys xs ns m state 0: #0 #1 #2 <var> state 1 state 1: #0 #1 #2 - [] state 2 - <app> state 3 - state 2: #0 - state 3: #1 #2 - <app> state 4 - state 4: #1 #2 - : state 5 + <var> state 2 + state 2: #0 #1 #2 + [] state 3 + <app> state 5 + state 3: #0 + <var> state 4 + state 4: #0 state 5: #1 #2 - <var>::int state 6 + <app> state 6 state 6: #1 #2 - <var> state 7 + : state 7 state 7: #1 #2 -} end when m/*0:*/::int = #xs/*0:01*/ { - rule #0: m::int = #xs - state 0: #0 - <var>::int state 1 - state 1: #0 + <var>::int state 8 + state 8: #1 #2 + <var> state 9 + state 9: #1 #2 + <var> state 10 + state 10: #1 #2 } end; n1/*0:0101*/,n2/*0:011*/..m/*0:1*/ = while (\i/*0:*/ -> s/*1:*/*i/*0:*/<=s/*1:*/*m/*3:1*/ { rule #0: i = s*i<=s*m @@ -514,98 +715,128 @@ takewhile p/*0:01*/ (x/*0:101*/:xs/*0:11*/) = x/*0:101*/:takewhile p/*0:01*/ xs/*0:11*/ if p/*0:01*/ x/*0:101*/; takewhile p/*0:01*/ (x/*0:101*/:xs/*0:11*/) = []; cat [] = []; -cat (xs/*0:101*/:xss/*0:11*/) = accum/*0*/ (reverse xs/*0:101*/) xss/*0:11*/ with accum xs/*0:01*/ [] = reverse xs/*0:01*/; accum xs/*0:01*/ ([]:yss/*0:11*/) = accum/*1*/ xs/*0:01*/ yss/*0:11*/; accum xs/*0:01*/ ((y/*0:10101*/:ys/*0:1011*/):yss/*0:11*/) = accum/*1*/ (y/*0:10101*/:xs/*0:01*/) (ys/*0:1011*/:yss/*0:11*/); accum xs/*0:01*/ yss/*0:1*/ = reverse xs/*0:01*/+cat yss/*0:1*/ { +cat (xs/*0:101*/:xss/*0:11*/) = accum/*0*/ (reverse xs/*0:101*/) xss/*0:11*/ with accum xs/*0:01*/ [] = reverse xs/*0:01*/; accum xs/*0:01*/ ([]:yss/*0:11*/) = accum/*1*/ xs/*0:01*/ yss/*0:11*/; accum xs/*0:01*/ ((y/*0:10101*/:ys/*0:1011*/):yss/*0:11*/) = accum/*1*/ (y/*0:10101*/:xs/*0:01*/) (ys/*0:1011*/:yss/*0:11*/); accum _/*0:01*/ (ys/*0:101*/:_/*0:11*/) = throw (bad_list_value ys/*0:101*/); accum _/*0:01*/ yss/*0:1*/ = throw (bad_list_value yss/*0:1*/) { rule #0: accum xs [] = reverse xs rule #1: accum xs ([]:yss) = accum xs yss rule #2: accum xs ((y:ys):yss) = accum (y:xs) (ys:yss) - rule #3: accum xs yss = reverse xs+cat yss - state 0: #0 #1 #2 #3 + rule #3: accum _ (ys:_) = throw (bad_list_value ys) + rule #4: accum _ yss = throw (bad_list_value yss) + state 0: #0 #1 #2 #3 #4 <var> state 1 - state 1: #0 #1 #2 #3 + state 1: #0 #1 #2 #3 #4 <var> state 2 [] state 3 <app> state 4 - state 2: #3 - state 3: #0 #3 - state 4: #1 #2 #3 + state 2: #4 + state 3: #0 #4 + state 4: #1 #2 #3 #4 <var> state 5 <app> state 7 - state 5: #3 + state 5: #4 <var> state 6 - state 6: #3 - state 7: #1 #2 #3 + state 6: #4 + state 7: #1 #2 #3 #4 <var> state 8 : state 11 - state 8: #3 + state 8: #4 <var> state 9 - state 9: #3 + state 9: #4 <var> state 10 - state 10: #3 - state 11: #1 #2 #3 + state 10: #4 + state 11: #1 #2 #3 #4 <var> state 12 [] state 14 <app> state 16 - state 12: #3 + state 12: #3 #4 <var> state 13 - state 13: #3 - state 14: #1 #3 + state 13: #3 #4 + state 14: #1 #3 #4 <var> state 15 - state 15: #1 #3 - state 16: #2 #3 + state 15: #1 #3 #4 + state 16: #2 #3 #4 <var> state 17 <app> state 20 - state 17: #3 + state 17: #3 #4 <var> state 18 - state 18: #3 + state 18: #3 #4 <var> state 19 - state 19: #3 - state 20: #2 #3 + state 19: #3 #4 + state 20: #2 #3 #4 <var> state 21 : state 25 - state 21: #3 + state 21: #3 #4 <var> state 22 - state 22: #3 + state 22: #3 #4 <var> state 23 - state 23: #3 + state 23: #3 #4 <var> state 24 - state 24: #3 - state 25: #2 #3 + state 24: #3 #4 + state 25: #2 #3 #4 <var> state 26 - state 26: #2 #3 + state 26: #2 #3 #4 <var> state 27 - state 27: #2 #3 + state 27: #2 #3 #4 <var> state 28 - state 28: #2 #3 -} end if listp xs/*0:101*/; + state 28: #2 #3 #4 +} end; catmap f/*0:01*/ xs/*0:1*/ = cat (map f/*0:01*/ xs/*0:1*/); -reverse xs/*0:1*/ = foldl (flip (:)) [] xs/*0:1*/ if listp xs/*0:1*/; -repeat n/*0:01*/ x/*0:1*/ = [] if n/*0:01*/<=0; -repeat n/*0:01*/ x/*0:1*/ = x/*0:1*/:repeat (n/*0:01*/-1) x/*0:1*/; -cycle n/*0:01*/ [] = []; -cycle n/*0:01*/ (x/*0:101*/:xs/*0:11*/) = [] if n/*0:01*/<=0; -cycle n/*0:01*/ (x/*0:101*/:xs/*0:11*/) = mkcycle/*0*/ n/*2:01*/ xs/*1:*/ with mkcycle n/*0:01*/ xs/*0:1*/ = take n/*0:01*/ xs/*0:1*/ if n/*0:01*/<=m/*1:*/; mkcycle n/*0:01*/ xs/*0:1*/ = xs/*0:1*/+mkcycle/*1*/ (n/*0:01*/-m/*1:*/) xs/*0:1*/ { - rule #0: mkcycle n xs = take n xs if n<=m - rule #1: mkcycle n xs = xs+mkcycle (n-m) xs +repeat n/*0:01*/::int x/*0:1*/ = accum/*0*/ [] n/*0:01*/ x/*0:1*/ with accum xs/*0:001*/ n/*0:01*/::int x/*0:1*/ = xs/*0:001*/ if n/*0:01*/<=0; accum xs/*0:001*/ n/*0:01*/::int x/*0:1*/ = accum/*1*/ (x/*0:1*/:xs/*0:001*/) (n/*0:01*/-1) x/*0:1*/ { + rule #0: accum xs n::int x = xs if n<=0 + rule #1: accum xs n::int x = accum (x:xs) (n-1) x state 0: #0 #1 <var> state 1 state 1: #0 #1 - <var> state 2 + <var>::int state 2 state 2: #0 #1 -} end when xs/*0:*/ = x/*0:101*/:xs/*0:11*/; m/*0:*/ = #xs/*0:*/ { - rule #0: m = #xs - state 0: #0 + <var> state 3 + state 3: #0 #1 +} end; +cycle n/*0:01*/::int [] = []; +cycle n/*0:01*/::int (x/*0:101*/:xs/*0:11*/) = [] if n/*0:01*/<=0; +cycle n/*0:01*/::int (x/*0:101*/:xs/*0:11*/) = accum/*0*/ [] (#xs/*0:*/) n/*1:01*/ xs/*0:*/ with accum ys/*0:0001*/ m/*0:001*/::int n/*0:01*/::int xs/*0:1*/ = cat ys/*0:0001*/+take n/*0:01*/ xs/*0:1*/ if n/*0:01*/<=m/*0:001*/; accum ys/*0:0001*/ m/*0:001*/::int n/*0:01*/::int xs/*0:1*/ = accum/*1*/ (xs/*0:1*/:ys/*0:0001*/) m/*0:001*/ (n/*0:01*/-m/*0:001*/) xs/*0:1*/ { + rule #0: accum ys m::int n::int xs = cat ys+take n xs if n<=m + rule #1: accum ys m::int n::int xs = accum (xs:ys) m (n-m) xs + state 0: #0 #1 <var> state 1 - state 1: #0 -} { + state 1: #0 #1 + <var>::int state 2 + state 2: #0 #1 + <var>::int state 3 + state 3: #0 #1 + <var> state 4 + state 4: #0 #1 +} end when xs/*0:*/ = x/*0:101*/:xs/*0:11*/ { rule #0: xs = x:xs state 0: #0 <var> state 1 state 1: #0 } end; -while p/*0:001*/ f/*0:01*/ a/*0:1*/ = a/*0:1*/:while p/*0:001*/ f/*0:01*/ (f/*0:01*/ a/*0:1*/) if p/*0:001*/ a/*0:1*/; -while p/*0:001*/ f/*0:01*/ a/*0:1*/ = []; -until p/*0:001*/ f/*0:01*/ a/*0:1*/ = [] if p/*0:001*/ a/*0:1*/; -until p/*0:001*/ f/*0:01*/ a/*0:1*/ = a/*0:1*/:until p/*0:001*/ f/*0:01*/ (f/*0:01*/ a/*0:1*/); +while p/*0:001*/ f/*0:01*/ a/*0:1*/ = accum/*0*/ [] p/*0:001*/ f/*0:01*/ a/*0:1*/ with accum as/*0:0001*/ p/*0:001*/ f/*0:01*/ a/*0:1*/ = accum/*1*/ (a/*0:1*/:as/*0:0001*/) p/*0:001*/ f/*0:01*/ (f/*0:01*/ a/*0:1*/) if p/*0:001*/ a/*0:1*/; accum as/*0:0001*/ p/*0:001*/ f/*0:01*/ a/*0:1*/ = reverse as/*0:0001*/ { + rule #0: accum as p f a = accum (a:as) p f (f a) if p a + rule #1: accum as p f a = reverse as + state 0: #0 #1 + <var> state 1 + state 1: #0 #1 + <var> state 2 + state 2: #0 #1 + <var> state 3 + state 3: #0 #1 + <var> state 4 + state 4: #0 #1 +} end; +until p/*0:001*/ f/*0:01*/ a/*0:1*/ = accum/*0*/ [] p/*0:001*/ f/*0:01*/ a/*0:1*/ with accum as/*0:0001*/ p/*0:001*/ f/*0:01*/ a/*0:1*/ = reverse as/*0:0001*/ if p/*0:001*/ a/*0:1*/; accum as/*0:0001*/ p/*0:001*/ f/*0:01*/ a/*0:1*/ = accum/*1*/ (a/*0:1*/:as/*0:0001*/) p/*0:001*/ f/*0:01*/ (f/*0:01*/ a/*0:1*/) { + rule #0: accum as p f a = reverse as if p a + rule #1: accum as p f a = accum (a:as) p f (f a) + state 0: #0 #1 + <var> state 1 + state 1: #0 #1 + <var> state 2 + state 2: #0 #1 + <var> state 3 + state 3: #0 #1 + <var> state 4 + state 4: #0 #1 +} end; zip (x/*0:0101*/:xs/*0:011*/) (y/*0:101*/:ys/*0:11*/) = (x/*0:0101*/,y/*0:101*/):zip xs/*0:011*/ ys/*0:11*/; zip _/*0:01*/ _/*0:1*/ = []; zip3 (x/*0:00101*/:xs/*0:0011*/) (y/*0:0101*/:ys/*0:011*/) (z/*0:101*/:zs/*0:11*/) = (x/*0:00101*/,y/*0:0101*/,z/*0:101*/):zip3 xs/*0:0011*/ ys/*0:011*/ zs/*0:11*/; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |