Thread: [pure-lang-svn] SF.net SVN: pure-lang: [294] pure/trunk (Page 5)
Status: Beta
Brought to you by:
agraef
From: <ag...@us...> - 2008-06-24 09:54:42
|
Revision: 294 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=294&view=rev Author: agraef Date: 2008-06-24 02:54:51 -0700 (Tue, 24 Jun 2008) Log Message: ----------- Implement list/tuple convenience operations. Modified Paths: -------------- pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-06-24 08:56:30 UTC (rev 293) +++ pure/trunk/runtime.cc 2008-06-24 09:54:51 UTC (rev 294) @@ -458,13 +458,76 @@ return pure_apply2(fun, arg); } -// XXXTODO +static inline pure_expr *mk_nil() +{ + interpreter& interp = *interpreter::g_interp; + return pure_const(interp.symtab.nil_sym().f); +} -pure_expr *pure_listl(size_t size, ...); -pure_expr *pure_listv(size_t size, pure_expr **elems); -pure_expr *pure_tuplel(size_t size, ...); -pure_expr *pure_tuplev(size_t size, pure_expr **elems); +static inline pure_expr *mk_cons(pure_expr *x, pure_expr *y) +{ + interpreter& interp = *interpreter::g_interp; + pure_expr *f = pure_const(interp.symtab.cons_sym().f); + return pure_apply2(pure_apply2(f, x), y); +} +static inline pure_expr *mk_void() +{ + interpreter& interp = *interpreter::g_interp; + return pure_const(interp.symtab.void_sym().f); +} + +static inline pure_expr *mk_pair(pure_expr *x, pure_expr *y) +{ + interpreter& interp = *interpreter::g_interp; + pure_expr *f = pure_const(interp.symtab.pair_sym().f); + return pure_apply2(pure_apply2(f, x), y); +} + +extern "C" +pure_expr *pure_listl(size_t size, ...) +{ + if (size == 0) return mk_nil(); + va_list ap; + va_start(ap, size); + pure_expr **elems = (pure_expr**)alloca(size*sizeof(pure_expr*)); + for (size_t i = 0; i < size; i++) + elems[i] = va_arg(ap, pure_expr*); + return pure_listv(size, elems); +} + +extern "C" +pure_expr *pure_listv(size_t size, pure_expr **elems) +{ + pure_expr *y = mk_nil(); + for (size_t i = size; i-- > 0; ) + y = mk_cons(elems[i], y); + return y; +} + +extern "C" +pure_expr *pure_tuplel(size_t size, ...) +{ + if (size == 0) return mk_void(); + va_list ap; + va_start(ap, size); + pure_expr **elems = (pure_expr**)alloca(size*sizeof(pure_expr*)); + for (size_t i = 0; i < size; i++) + elems[i] = va_arg(ap, pure_expr*); + return pure_tuplev(size, elems); +} + +extern "C" +pure_expr *pure_tuplev(size_t size, pure_expr **elems) +{ + if (size == 0) return mk_void(); + pure_expr *y = elems[--size]; + for (size_t i = size; i-- > 0; ) + y = mk_pair(elems[i], y); + return y; +} + +extern "C" bool pure_is_symbol(const pure_expr *x, int32_t *sym) { assert(x); @@ -475,6 +538,7 @@ return false; } +extern "C" bool pure_is_int(const pure_expr *x, int32_t *i) { assert(x); @@ -485,6 +549,7 @@ return false; } +extern "C" bool pure_is_mpz(const pure_expr *x, mpz_t *z) { assert(x); @@ -495,6 +560,7 @@ return false; } +extern "C" bool pure_is_double(const pure_expr *x, double *d) { assert(x); @@ -505,6 +571,7 @@ return false; } +extern "C" bool pure_is_pointer(const pure_expr *x, void **p) { assert(x); @@ -515,6 +582,7 @@ return false; } +extern "C" bool pure_is_string(const pure_expr *x, const char **s) { assert(x); @@ -525,6 +593,7 @@ return false; } +extern "C" bool pure_is_string_dup(const pure_expr *x, char **s) { assert(x); @@ -535,6 +604,7 @@ return false; } +extern "C" bool pure_is_cstring_dup(const pure_expr *x, char **s) { assert(x); @@ -545,6 +615,7 @@ return false; } +extern "C" bool pure_is_app(const pure_expr *x, pure_expr **fun, pure_expr **arg) { assert(x); @@ -556,12 +627,96 @@ return false; } -// XXXTODO +static inline bool is_nil(pure_expr *x) +{ + interpreter& interp = *interpreter::g_interp; + return x->tag == interp.symtab.nil_sym().f; +} -bool pure_is_listv(const pure_expr *x, size_t *size, pure_expr ***elems); -bool pure_is_tuplev(const pure_expr *x, size_t *size, pure_expr ***elems); +static inline bool is_cons(pure_expr *x, pure_expr*& y, pure_expr*& z) +{ + interpreter& interp = *interpreter::g_interp; + if (x->tag == EXPR::APP && x->data.x[0]->tag == EXPR::APP && + x->data.x[0]->data.x[0]->tag == interp.symtab.cons_sym().f) { + y = x->data.x[0]->data.x[1]; + z = x->data.x[1]; + return true; + } else + return false; +} +static inline bool is_void(pure_expr *x) +{ + interpreter& interp = *interpreter::g_interp; + return x->tag == interp.symtab.void_sym().f; +} + +static inline bool is_pair(pure_expr *x, pure_expr*& y, pure_expr*& z) +{ + interpreter& interp = *interpreter::g_interp; + if (x->tag == EXPR::APP && x->data.x[0]->tag == EXPR::APP && + x->data.x[0]->data.x[0]->tag == interp.symtab.pair_sym().f) { + y = x->data.x[0]->data.x[1]; + z = x->data.x[1]; + return true; + } else + return false; +} + extern "C" +bool pure_is_listv(pure_expr *x, size_t *_size, pure_expr ***_elems) +{ + pure_expr *u = x, *y, *z; + size_t size = 0; + while (is_cons(u, y, z)) { + size++; + u = z; + } + if (!is_nil(u)) return false; + if (_size) *_size = size; + if (_elems) + if (size>0) { + pure_expr **elems = (pure_expr**)malloc(size*sizeof(pure_expr*)); + size_t i = 0; + u = x; + while (is_cons(u, y, z)) { + elems[i++] = y; + u = z; + } + *_elems = elems; + } else + *_elems = 0; + return true; +} + +extern "C" +bool pure_is_tuplev(pure_expr *x, size_t *_size, pure_expr ***_elems) +{ + /* FIXME: This implementation assumes that tuples are right-recursive. If we + change the tuple implementation in the prelude then this code has to be + adapted accordingly. */ + pure_expr *u = x, *y, *z; + size_t size = 1; + while (is_pair(u, y, z)) { + size++; + u = z; + } + if (_size) *_size = size; + if (_elems) { + pure_expr **elems = (pure_expr**)malloc(size*sizeof(pure_expr*)); + size_t i = 0; + u = x; + while (is_pair(u, y, z)) { + elems[i++] = y; + u = z; + } + elems[i++] = u; + *_elems = elems; + } + return true; +} + +extern "C" pure_expr *pure_new(pure_expr *x) { return pure_new_internal(x); @@ -1564,24 +1719,6 @@ return x; } -static inline bool is_nil(pure_expr *xs) -{ - interpreter& interp = *interpreter::g_interp; - return xs->tag == interp.symtab.nil_sym().f; -} - -static inline bool is_cons(pure_expr *xs, pure_expr*& y, pure_expr*& ys) -{ - interpreter& interp = *interpreter::g_interp; - if (xs->tag == EXPR::APP && xs->data.x[0]->tag == EXPR::APP && - xs->data.x[0]->data.x[0]->tag == interp.symtab.cons_sym().f) { - y = xs->data.x[0]->data.x[1]; - ys = xs->data.x[1]; - return true; - } else - return false; -} - extern "C" pure_expr *string_concat_list(pure_expr *xs) { Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-06-24 08:56:30 UTC (rev 293) +++ pure/trunk/runtime.h 2008-06-24 09:54:51 UTC (rev 294) @@ -171,8 +171,8 @@ pure_is_tuplev will always return true, since a singleton expression, which is not either a pair or (), is considered a tuple of size 1. */ -bool pure_is_listv(const pure_expr *x, size_t *size, pure_expr ***elems); -bool pure_is_tuplev(const pure_expr *x, size_t *size, pure_expr ***elems); +bool pure_is_listv(pure_expr *x, size_t *size, pure_expr ***elems); +bool pure_is_tuplev(pure_expr *x, size_t *size, pure_expr ***elems); /* Memory management. */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-24 10:38:20
|
Revision: 295 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=295&view=rev Author: agraef Date: 2008-06-24 03:38:29 -0700 (Tue, 24 Jun 2008) Log Message: ----------- Add convenience functions to (de)construct a function application from/to a function object and a number of argument expressions. Modified Paths: -------------- pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-06-24 09:54:51 UTC (rev 294) +++ pure/trunk/runtime.cc 2008-06-24 10:38:29 UTC (rev 295) @@ -458,6 +458,27 @@ return pure_apply2(fun, arg); } +extern "C" +pure_expr *pure_appl(pure_expr *fun, size_t argc, ...) +{ + if (argc == 0) return fun; + va_list ap; + va_start(ap, argc); + pure_expr **args = (pure_expr**)alloca(argc*sizeof(pure_expr*)); + for (size_t i = 0; i < argc; i++) + args[i] = va_arg(ap, pure_expr*); + return pure_appv(fun, argc, args); +} + +extern "C" +pure_expr *pure_appv(pure_expr *fun, size_t argc, pure_expr **args) +{ + pure_expr *y = fun; + for (size_t i = 0; i < argc; i++) + y = pure_apply2(y, args[i]); + return y; +} + static inline pure_expr *mk_nil() { interpreter& interp = *interpreter::g_interp; @@ -627,6 +648,35 @@ return false; } +extern "C" +bool pure_is_appv(pure_expr *x, pure_expr **_fun, + size_t *_argc, pure_expr ***_args) +{ + assert(x); + pure_expr *u = x, *y, *z; + size_t argc = 0; + while (pure_is_app(u, &y, &z)) { + argc++; + u = y; + } + if (_fun) *_fun = u; + if (_argc) *_argc = argc; + if (_args) + if (argc > 0) { + pure_expr **args = (pure_expr**)malloc(argc*sizeof(pure_expr*)); + assert(args); + size_t i = argc; + u = x; + while (pure_is_app(u, &y, &z)) { + args[--i] = z; + u = y; + } + *_args = args; + } else + *_args = 0; + return true; +} + static inline bool is_nil(pure_expr *x) { interpreter& interp = *interpreter::g_interp; @@ -666,6 +716,7 @@ extern "C" bool pure_is_listv(pure_expr *x, size_t *_size, pure_expr ***_elems) { + assert(x); pure_expr *u = x, *y, *z; size_t size = 0; while (is_cons(u, y, z)) { @@ -675,8 +726,9 @@ if (!is_nil(u)) return false; if (_size) *_size = size; if (_elems) - if (size>0) { + if (size > 0) { pure_expr **elems = (pure_expr**)malloc(size*sizeof(pure_expr*)); + assert(elems); size_t i = 0; u = x; while (is_cons(u, y, z)) { @@ -692,6 +744,7 @@ extern "C" bool pure_is_tuplev(pure_expr *x, size_t *_size, pure_expr ***_elems) { + assert(x); /* FIXME: This implementation assumes that tuples are right-recursive. If we change the tuple implementation in the prelude then this code has to be adapted accordingly. */ @@ -704,6 +757,7 @@ if (_size) *_size = size; if (_elems) { pure_expr **elems = (pure_expr**)malloc(size*sizeof(pure_expr*)); + assert(elems); size_t i = 0; u = x; while (is_pair(u, y, z)) { Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-06-24 09:54:51 UTC (rev 294) +++ pure/trunk/runtime.h 2008-06-24 10:38:29 UTC (rev 295) @@ -116,6 +116,14 @@ pure_expr *pure_app(pure_expr *fun, pure_expr *arg); +/* Convenience functions to construct an application of the given function to + a vector or varargs list of argument expressions. The vectors are owned by + the caller and won't be freed. References on the argument expressions are + counted automatically. */ + +pure_expr *pure_appl(pure_expr *fun, size_t argc, ...); +pure_expr *pure_appv(pure_expr *fun, size_t argc, pure_expr **args); + /* Convenience functions to construct Pure list and tuple values from a vector or a varargs list of element expressions. (Internally these are actually represented as function applications.) The vectors are owned by the caller @@ -166,10 +174,23 @@ bool pure_is_app(const pure_expr *x, pure_expr **fun, pure_expr **arg); -/* Convenience functions to deconstruct lists and tuples. Returned element - vectors are malloc'd and must be freed by the caller. Note that +/* Convenience function to decompose a function application into a function + and a vector of argument expressions. The returned element vectors are + malloc'ed and must be freed by the caller (unless the number of arguments + is zero in which case the returned vector will be NULL). Note that this + function always yields true, since a singleton expression which is not an + application is considered to be a function applied to zero arguments. In + such a case you can check the returned function object with pure_is_symbol + to see whether it actually is a symbol or closure. */ + +bool pure_is_appv(pure_expr *x, pure_expr **fun, + size_t *argc, pure_expr ***args); + +/* Convenience functions to deconstruct lists and tuples. The returned element + vectors are malloc'ed and must be freed by the caller (unless the number of + elements is zero in which case the returned vector will be NULL). Note that pure_is_tuplev will always return true, since a singleton expression, which - is not either a pair or (), is considered a tuple of size 1. */ + is not either a pair or (), is considered to be a tuple of size 1. */ bool pure_is_listv(pure_expr *x, size_t *size, pure_expr ***elems); bool pure_is_tuplev(pure_expr *x, size_t *size, pure_expr ***elems); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-24 12:41:28
|
Revision: 296 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=296&view=rev Author: agraef Date: 2008-06-24 05:41:37 -0700 (Tue, 24 Jun 2008) Log Message: ----------- Finish off public runtime API with some operations to create standalone interpreters. Modified Paths: -------------- pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-06-24 10:38:29 UTC (rev 295) +++ pure/trunk/runtime.cc 2008-06-24 12:41:37 UTC (rev 296) @@ -801,6 +801,144 @@ pure_unref_internal(x); } +#ifndef HOST +#define HOST "unknown" +#endif +#ifndef PACKAGE_VERSION +#define PACKAGE_VERSION "0.0" +#endif +#ifndef PURELIB +#define PURELIB "/usr/local/lib/pure-" PACKAGE_VERSION +#endif + +#include <llvm/Target/TargetOptions.h> + +extern "C" +pure_interp *pure_create_interp(int argc, const char *argv[]) +{ + // This is pretty much the same as pure.cc:main(), except that some options + // are ignored and there's no user interaction. + char base; + interpreter *_interp = new interpreter, &interp = *_interp; + int count = 0; + bool want_prelude = true, have_prelude = false; + // This is used in advisory stack checks. + if (!interpreter::baseptr) interpreter::baseptr = &base; + // get some settings from the environment + const char *env; + if ((env = getenv("HOME"))) + interp.histfile = string(env)+"/.pure_history"; + if ((env = getenv("PURE_PS"))) + interp.ps = string(env); + if ((env = getenv("PURE_STACK"))) { + char *end; + size_t n = strtoul(env, &end, 0); + if (!*end) interpreter::stackmax = n*1024; + } + if ((env = getenv("PURELIB"))) + interp.lib = string(env)+"/"; + else + interp.lib = string(PURELIB)+"/"; + string prelude = interp.lib+string("prelude.pure"); +#if USE_FASTCC + // This global option is needed to get tail call optimization (you'll also + // need to have USE_FASTCC in interpreter.hh enabled). + llvm::PerformTailCallOpt = true; +#endif + // scan the command line options + list<string> myargs; + for (const char **args = ++argv; *args; ++args) + if (*args == string("-h")) + /* ignored */; + else if (*args == string("-i")) + /* ignored */; + else if (*args == string("-n")) + want_prelude = false; + else if (*args == string("-q")) + /* ignored */; + else if (string(*args).substr(0,2) == "-v") { + string s = string(*args).substr(2); + if (s.empty()) continue; + char *end; + strtoul(s.c_str(), &end, 0); + if (*end) { + cerr << "pure_create_interp: invalid option " << *args << endl; + delete _interp; + return 0; + } + } else if (*args == string("-x")) { + while (*++args) myargs.push_back(*args); + break; + } else if (*args == string("--")) { + while (*++args) myargs.push_back(*args); + break; + } else if (**args == '-') { + cerr << "pure_create_interp: invalid option " << *args << endl; + delete _interp; + return 0; + } + interp.init_sys_vars(PACKAGE_VERSION, HOST, myargs); + if (want_prelude) { + // load the prelude if we can find it + FILE *fp = fopen("prelude.pure", "r"); + if (fp) + prelude = "prelude.pure"; + else + // try again in the PURELIB directory + fp = fopen(prelude.c_str(), "r"); + if (fp) { + fclose(fp); + have_prelude = true; + interp.run(prelude); + interp.compile(); + } + } + // load scripts specified on the command line + for (; *argv; ++argv) + if (string(*argv).substr(0,2) == "-v") { + uint8_t level = 1; + string s = string(*argv).substr(2); + if (!s.empty()) level = (uint8_t)strtoul(s.c_str(), 0, 0); + interp.verbose = level; + } else if (*argv == string("-x")) { + if (*++argv) { + count++; interp.modname = *argv; + interp.run(*argv); + } else { + cerr << "pure_create_interp: missing script name\n"; + delete _interp; + return 0; + } + break; + } else if (*argv == string("--")) + break; + else if (**argv == '-') + ; + else if (**argv) { + if (count++ == 0) interp.modname = *argv; + interp.run(*argv); + } + interp.symtab.init_builtins(); + return (pure_interp*)_interp; +} + +extern "C" +void pure_delete_interp(pure_interp *interp) +{ + assert(interp); + interpreter *_interp = (interpreter*)interp; + if (interpreter::g_interp == _interp) + interpreter::g_interp = 0; + delete _interp; +} + +extern "C" +void pure_switch_interp(pure_interp *interp) +{ + assert(interp); + interpreter::g_interp = (interpreter*)interp; +} + /* END OF PUBLIC API. *******************************************************/ extern "C" Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-06-24 10:38:29 UTC (rev 295) +++ pure/trunk/runtime.h 2008-06-24 12:41:37 UTC (rev 296) @@ -221,6 +221,41 @@ void pure_ref(pure_expr *x); void pure_unref(pure_expr *x); +/* The following routines provide standalone C/C++ applications with fully + initialized interpreter instances which can be used together with the + operations listed above. This is only needed for modules which are not to + be loaded by the command line version of the interpreter. + + The argc, argv parameters passed to pure_create_interp specify the command + line arguments of the interpreter instance. This includes any scripts that + are to be loaded on startup as well as any other options understood by the + command line version of the interpreter (options like -i and -q won't have + any effect, though, and the interpreter will always be in non-interactive + mode). The argv vector must be NULL-terminated, and argv[0] should be set + to the name of the hosting application (usually the main program of the + application). + + An application may use multiple interpreter instances, but only a single + instance can be active at any one time. By default, the first created + instance will be active, but you can switch between different instances + with the pure_switch_interp function. The pure_delete_interp routine + destroys an interpreter instance; if the destroyed instance is currently + active, the active instance will be undefined afterwards, so you'll have to + either create or switch to another instance before calling any other + operations. + + Note that when using different interpreter instances in concert, it is + *not* possible to pass pure_expr* values created with one interpreter + instance to another. Instead, you can use the str and eval functions from + the library API (see below) to first unparse the expression in the source + interpreter and then reparse it in the target interpreter. */ + +typedef struct pure_interp; // Pure interpreter handles (opaque). + +pure_interp *pure_create_interp(int argc, const char *argv[]); +void pure_delete_interp(pure_interp *interp); +void pure_switch_interp(pure_interp *interp); + /* END OF PUBLIC API. *******************************************************/ /* Stuff below this line is for internal use by the Pure interpreter. Don't This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-24 14:36:04
|
Revision: 298 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=298&view=rev Author: agraef Date: 2008-06-24 07:36:02 -0700 (Tue, 24 Jun 2008) Log Message: ----------- Fix some C compilation quirks and add some error reporting to the eval function. Modified Paths: -------------- pure/trunk/interpreter.cc pure/trunk/interpreter.hh pure/trunk/lib/strings.pure pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-06-24 12:48:18 UTC (rev 297) +++ pure/trunk/interpreter.cc 2008-06-24 14:36:02 UTC (rev 298) @@ -333,30 +333,46 @@ interpreter::error(const yy::location& l, const string& m) { nerrs++; - cout.flush(); - if (!source_s) cerr << l << ": " << m << endl; + if (source_s) { + ostringstream msg; + msg << l << ": " << m << endl; + errmsg += msg.str(); + } else { + cout.flush(); + cerr << l << ": " << m << endl; + } } void interpreter::error(const string& m) { nerrs++; - cout.flush(); - if (!source_s) cerr << m << endl; + if (source_s) { + ostringstream msg; + msg << m << endl; + errmsg += msg.str(); + } else { + cout.flush(); + cerr << m << endl; + } } void interpreter::warning(const yy::location& l, const string& m) { - cout.flush(); - if (!source_s) cerr << l << ": " << m << endl; + if (!source_s) { + cout.flush(); + cerr << l << ": " << m << endl; + } } void interpreter::warning(const string& m) { - cout.flush(); - if (!source_s) cerr << m << endl; + if (!source_s) { + cout.flush(); + cerr << m << endl; + } } // Run the interpreter on a source file, collection of source files, or on @@ -392,6 +408,7 @@ // initialize nerrs = 0; source = s; declare_op = false; + errmsg.clear(); if (check && !interactive) temp = 0; bool ok = lex_begin(); if (ok) { @@ -443,6 +460,7 @@ nerrs = 0; source = ""; declare_op = false; source_s = s.c_str(); + errmsg.clear(); bool ok = lex_begin(); if (ok) { yy::parser parser(*this); Modified: pure/trunk/interpreter.hh =================================================================== --- pure/trunk/interpreter.hh 2008-06-24 12:48:18 UTC (rev 297) +++ pure/trunk/interpreter.hh 2008-06-24 14:36:02 UTC (rev 298) @@ -262,6 +262,7 @@ // Interpreter state. For internal use only. int nerrs; // current error count + string errmsg; // last reported error (runstr) string source; // the source being parsed const char *source_s; // source pointer if input comes from a string set<string> sources; // the list of all scripts which have been loaded @@ -293,7 +294,9 @@ pure_expr *run(const list<string>& sources, bool check = true); /* This works like run() above, but takes the source directly from a - string. */ + string. No error messages will be printed, instead any errors reported + during the most recent invokation of this method are available in + errmsg. */ pure_expr *runstr(const string& source); /* Evaluate a (compile time) expression and return the (runtime expression) Modified: pure/trunk/lib/strings.pure =================================================================== --- pure/trunk/lib/strings.pure 2008-06-24 12:48:18 UTC (rev 297) +++ pure/trunk/lib/strings.pure 2008-06-24 14:36:02 UTC (rev 298) @@ -23,10 +23,14 @@ eval function does the opposite, by parsing and returning the value of an expression specified as a string in Pure syntax. (In fact, eval goes well beyond this, as it can parse and execute arbitrary Pure code. In that case - it will return the last computed expression, if any.) */ + it will return the last computed expression, if any.) Errors are reported + with the lasterr routine. This string value will be nonempty iff an error + was encountered during the most recent invokation of eval(). In that case + each reported error message is terminated with a newline character. */ extern void* str(expr*) = pure_str; extern expr* eval(char*); // IMPURE! +extern char* lasterr(); str x = cstring (pure_str x); Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-06-24 12:48:18 UTC (rev 297) +++ pure/trunk/runtime.cc 2008-06-24 14:36:02 UTC (rev 298) @@ -814,7 +814,7 @@ #include <llvm/Target/TargetOptions.h> extern "C" -pure_interp *pure_create_interp(int argc, const char *argv[]) +pure_interp *pure_create_interp(int argc, char *argv[]) { // This is pretty much the same as pure.cc:main(), except that some options // are ignored and there's no user interaction. @@ -847,7 +847,7 @@ #endif // scan the command line options list<string> myargs; - for (const char **args = ++argv; *args; ++args) + for (char **args = ++argv; *args; ++args) if (*args == string("-h")) /* ignored */; else if (*args == string("-i")) @@ -1984,12 +1984,20 @@ { assert(s); interpreter& interp = *interpreter::g_interp; + interp.errmsg.clear(); pure_expr *res = interp.runstr(string(s)+";"); interp.result = 0; if (res) pure_unref_internal(res); return res; } +extern "C" +const char *lasterr() +{ + interpreter& interp = *interpreter::g_interp; + return interp.errmsg.c_str(); +} + static uint32_t mpz_hash(const mpz_t z) { uint32_t h = 0; Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-06-24 12:48:18 UTC (rev 297) +++ pure/trunk/runtime.h 2008-06-24 14:36:02 UTC (rev 298) @@ -250,9 +250,9 @@ the library API (see below) to first unparse the expression in the source interpreter and then reparse it in the target interpreter. */ -typedef struct pure_interp; // Pure interpreter handles (opaque). +typedef struct _pure_interp pure_interp; // Pure interpreter handles (opaque). -pure_interp *pure_create_interp(int argc, const char *argv[]); +pure_interp *pure_create_interp(int argc, char *argv[]); void pure_delete_interp(pure_interp *interp); void pure_switch_interp(pure_interp *interp); @@ -444,12 +444,19 @@ /* Convert a Pure expression to a string and vice versa. Note that eval() will actually parse and execute any Pure source, so it can be used, e.g., to add new rules to the executing program at runtime. The result of eval() is the - last computed expression (NULL if none). The result of str() is a malloc'ed - string in the system encoding which must be freed by the caller. */ + last computed expression, NULL if none; in the latter case you can inspect + the result of lasterr() below to determine whether there were any errors. + The result of str() is a malloc'ed string in the system encoding which must + be freed by the caller. */ char *str(const pure_expr *x); pure_expr *eval(const char *s); +/* After an invokation of eval(), this returns error messages from the + interpreter (an empty string if none). */ + +const char *lasterr(); + /* Compute a 32 bit hash code of a Pure expression. This makes it possible to use arbitary Pure values as keys in a hash table. */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-24 15:36:00
|
Revision: 302 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=302&view=rev Author: agraef Date: 2008-06-24 08:33:43 -0700 (Tue, 24 Jun 2008) Log Message: ----------- Bump version number. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/configure pure/trunk/configure.ac Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-06-24 15:21:36 UTC (rev 301) +++ pure/trunk/ChangeLog 2008-06-24 15:33:43 UTC (rev 302) @@ -1,5 +1,7 @@ 2008-06-24 Albert Graef <Dr....@t-...> + * configure.ac: Bump version number. + * pure.cc, lexer.ll: Bugfix: include external symbols in command completion. Modified: pure/trunk/configure =================================================================== --- pure/trunk/configure 2008-06-24 15:21:36 UTC (rev 301) +++ pure/trunk/configure 2008-06-24 15:33:43 UTC (rev 302) @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61 for pure 0.4. +# Generated by GNU Autoconf 2.61 for pure 0.5. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. @@ -572,8 +572,8 @@ # Identity of this package. PACKAGE_NAME='pure' PACKAGE_TARNAME='pure' -PACKAGE_VERSION='0.4' -PACKAGE_STRING='pure 0.4' +PACKAGE_VERSION='0.5' +PACKAGE_STRING='pure 0.5' PACKAGE_BUGREPORT='' # Factoring default headers for most tests. @@ -1198,7 +1198,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures pure 0.4 to adapt to many kinds of systems. +\`configure' configures pure 0.5 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1263,7 +1263,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pure 0.4:";; + short | recursive ) echo "Configuration of pure 0.5:";; esac cat <<\_ACEOF @@ -1356,7 +1356,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pure configure 0.4 +pure configure 0.5 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1370,7 +1370,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by pure $as_me 0.4, which was +It was created by pure $as_me 0.5, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -5764,7 +5764,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by pure $as_me 0.4, which was +This file was extended by pure $as_me 0.5, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5813,7 +5813,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -pure config.status 0.4 +pure config.status 0.5 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Modified: pure/trunk/configure.ac =================================================================== --- pure/trunk/configure.ac 2008-06-24 15:21:36 UTC (rev 301) +++ pure/trunk/configure.ac 2008-06-24 15:33:43 UTC (rev 302) @@ -2,7 +2,7 @@ dnl To regenerate the configury after changes: dnl autoconf -I config && autoheader -I config -AC_INIT(pure, 0.4) +AC_INIT(pure, 0.5) AC_CONFIG_AUX_DIR(config) dnl AC_CONFIG_MACRO_DIR(config) AC_CONFIG_HEADERS(config.h) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-24 15:51:47
|
Revision: 304 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=304&view=rev Author: agraef Date: 2008-06-24 08:51:55 -0700 (Tue, 24 Jun 2008) Log Message: ----------- Add C->Pure example. Modified Paths: -------------- pure/trunk/ChangeLog Added Paths: ----------- pure/trunk/examples/poor.c Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-06-24 15:38:12 UTC (rev 303) +++ pure/trunk/ChangeLog 2008-06-24 15:51:55 UTC (rev 304) @@ -5,6 +5,8 @@ * pure.cc, lexer.ll: Bugfix: include external symbols in command completion. + * examples/poor.c: Add an example for the new public runtime API. + * interpreter.cc/h, runtime.cc/h, lib/strings.pure: Add error reporting to the eval() routine. Added: pure/trunk/examples/poor.c =================================================================== --- pure/trunk/examples/poor.c (rev 0) +++ pure/trunk/examples/poor.c 2008-06-24 15:51:55 UTC (rev 304) @@ -0,0 +1,35 @@ + +/* Poor man's Pure interpreter. */ + +/* This is an example for the C/C++->Pure interface. It implements a silly + little command loop which reads Pure code, evaluates it, and prints the + results. Compile this with 'gcc -o poor poor.c -lpure', and run as + './poor args...'. You can use the same command line options as with the + real Pure interpreter, including any Pure scripts to be loaded at startup. + + Please note that the interface to the interpreter, as provided by the + public runtime API, is rather minimalistic right now. In particular, the + interpreter will always run in non-interactive mode (thus none of the + interactive commands will work) and eval() will only return the last + computed expression. */ + +#include <stdio.h> +#include <pure/runtime.h> + +int main(int argc, char *argv[]) +{ + pure_interp *interp = pure_create_interp(argc, argv); + char buf[10000]; + fputs("? ", stdout); fflush(stdout); + while (fgets(buf, sizeof(buf), stdin)) { + pure_expr *x = eval(buf); + if (x) { + printf("%s\n", str(x)); + pure_freenew(x); + } else if (lasterr()) + fputs(lasterr(), stderr); + fputs("? ", stdout); fflush(stdout); + } + puts("[quit]"); + return 0; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-24 15:58:29
|
Revision: 301 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=301&view=rev Author: agraef Date: 2008-06-24 08:21:36 -0700 (Tue, 24 Jun 2008) Log Message: ----------- Bugfix: include external symbols in command completion. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/lexer.ll pure/trunk/pure.cc Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-06-24 14:53:08 UTC (rev 300) +++ pure/trunk/ChangeLog 2008-06-24 15:21:36 UTC (rev 301) @@ -1,5 +1,8 @@ 2008-06-24 Albert Graef <Dr....@t-...> + * pure.cc, lexer.ll: Bugfix: include external symbols in command + completion. + * interpreter.cc/h, runtime.cc/h, lib/strings.pure: Add error reporting to the eval() routine. Modified: pure/trunk/lexer.ll =================================================================== --- pure/trunk/lexer.ll 2008-06-24 14:53:08 UTC (rev 300) +++ pure/trunk/lexer.ll 2008-06-24 15:21:36 UTC (rev 301) @@ -141,14 +141,18 @@ { static int list_index, len; static env::iterator it, end; + static extmap::iterator xit, xend; const char *name; + assert(interpreter::g_interp); + interpreter& interp = *interpreter::g_interp; /* New match. */ if (!state) { list_index = 0; - assert(interpreter::g_interp); - it = interpreter::g_interp->globenv.begin(); - end = interpreter::g_interp->globenv.end(); + it = interp.globenv.begin(); + end = interp.globenv.end(); + xit = interp.externals.begin(); + xend = interp.externals.end(); len = strlen(text); } @@ -164,12 +168,21 @@ symbol list. */ while (it != end) { assert(it->first > 0); - symbol& sym = interpreter::g_interp->symtab.sym(it->first); + symbol& sym = interp.symtab.sym(it->first); it++; if (strncmp(sym.s.c_str(), text, len) == 0) return strdup(sym.s.c_str()); } + /* Also process the declared externals which don't have any rules yet. */ + while (xit != xend) { + assert(xit->first > 0); + symbol& sym = interp.symtab.sym(xit->first); + xit++; + if (strncmp(sym.s.c_str(), text, len) == 0) + return strdup(sym.s.c_str()); + } + /* If no names matched, then return NULL. */ return 0; } Modified: pure/trunk/pure.cc =================================================================== --- pure/trunk/pure.cc 2008-06-24 14:53:08 UTC (rev 300) +++ pure/trunk/pure.cc 2008-06-24 15:21:36 UTC (rev 301) @@ -54,19 +54,25 @@ /* Generator functions for command completion. */ +typedef map<int32_t,ExternInfo> extmap; + static char * command_generator(const char *text, int state) { static int list_index, len; static env::iterator it, end; + static extmap::iterator xit, xend; const char *name; + assert(interpreter::g_interp); + interpreter& interp = *interpreter::g_interp; /* New match. */ if (!state) { list_index = 0; - assert(interpreter::g_interp); - it = interpreter::g_interp->globenv.begin(); - end = interpreter::g_interp->globenv.end(); + it = interp.globenv.begin(); + end = interp.globenv.end(); + xit = interp.externals.begin(); + xend = interp.externals.end(); len = strlen(text); } @@ -82,12 +88,21 @@ symbol list. */ while (it != end) { assert(it->first > 0); - symbol& sym = interpreter::g_interp->symtab.sym(it->first); + symbol& sym = interp.symtab.sym(it->first); it++; if (strncmp(sym.s.c_str(), text, len) == 0) return strdup(sym.s.c_str()); } + /* Also process the declared externals which don't have any rules yet. */ + while (xit != xend) { + assert(xit->first > 0); + symbol& sym = interp.symtab.sym(xit->first); + xit++; + if (strncmp(sym.s.c_str(), text, len) == 0) + return strdup(sym.s.c_str()); + } + /* If no names matched, then return NULL. */ return 0; } @@ -97,12 +112,16 @@ { static int len; static env::iterator it, end; + static extmap::iterator xit, xend; + assert(interpreter::g_interp); + interpreter& interp = *interpreter::g_interp; /* New match. */ if (!state) { - assert(interpreter::g_interp); - it = interpreter::g_interp->globenv.begin(); - end = interpreter::g_interp->globenv.end(); + it = interp.globenv.begin(); + end = interp.globenv.end(); + xit = interp.externals.begin(); + xend = interp.externals.end(); len = strlen(text); } @@ -110,12 +129,21 @@ symbol list. */ while (it != end) { assert(it->first > 0); - symbol& sym = interpreter::g_interp->symtab.sym(it->first); + symbol& sym = interp.symtab.sym(it->first); it++; if (strncmp(sym.s.c_str(), text, len) == 0) return strdup(sym.s.c_str()); } + /* Also process the declared externals which don't have any rules yet. */ + while (xit != xend) { + assert(xit->first > 0); + symbol& sym = interp.symtab.sym(xit->first); + xit++; + if (strncmp(sym.s.c_str(), text, len) == 0) + return strdup(sym.s.c_str()); + } + /* If no names matched, then return NULL. */ return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-24 23:46:14
|
Revision: 309 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=309&view=rev Author: agraef Date: 2008-06-24 16:46:23 -0700 (Tue, 24 Jun 2008) Log Message: ----------- Add sort.c example. Modified Paths: -------------- pure/trunk/ChangeLog Added Paths: ----------- pure/trunk/examples/sort.c Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-06-24 22:45:02 UTC (rev 308) +++ pure/trunk/ChangeLog 2008-06-24 23:46:23 UTC (rev 309) @@ -1,3 +1,10 @@ +2008-06-25 Albert Graef <Dr....@t-...> + + * examples/sort.c: Add another example for the runtime API. + This one shows how to implement a C function in a module to be + loaded by the Pure interpreter, which in turn calls other C and + Pure functions. + 2008-06-24 Albert Graef <Dr....@t-...> * configure.ac: Bump version number. @@ -6,6 +13,8 @@ completion. * examples/poor.c: Add an example for the new public runtime API. + Shows how to interface to the Pure interpreter in a standalone C + application. * interpreter.cc/h, runtime.cc/h, lib/strings.pure: Add error reporting to the eval() routine. Added: pure/trunk/examples/sort.c =================================================================== --- pure/trunk/examples/sort.c (rev 0) +++ pure/trunk/examples/sort.c 2008-06-24 23:46:23 UTC (rev 309) @@ -0,0 +1,110 @@ + +/* Sort a Pure list using the C qsort() function. 2008-06-25 AG */ + +/* Another example using the runtime API. It implements an external function + 'sort' which can be loaded inside the Pure interpreter. The function, to be + invoked as 'sort p xs', calls the qsort() routine from the C library to + sort a Pure list xs using a given Pure predicate p, which compares two + elements x and y and returns a truth value indicating whether x is less + than y. The example illustrates how we can program a C function to be + called from Pure which in turn calls other Pure functions, and takes + generic pure_expr* values as arguments and returns them as results. */ + +/* To compile (Linux): 'gcc -shared -o sort.so sort.c -lpure'. This will + create a dynamic library ready to be loaded by the Pure interpreter. + (Replace .so with .dylib or .dll on OSX and Windows, respectively. On OSX, + you also have to replace -shared with -dynamiclib. On Windows you might + wish to add the '-Wl,--enable-auto-import' linker option.) + + I suggest that you also set up your LD_LIBRARY_PATH environment variable + (DYLD_LIBRARY_PATH on OSX) so that the dynamic loader finds sort.so without + further ado. Something like 'export LD_LIBRARY_PATH=.' should do the trick. + Windows doesn't need this since it always searches the current directory + for dlls. + + Now start the interpreter and enter the following to "dlopen" sort.so and + declare the sort function: + + > using "lib:sort"; + > extern expr* sort(expr* p, expr *xs); + + The sort function is now ready to be called as 'sort p xs', e.g.: + + > sort (<) (1..10); + [1,2,3,4,5,6,7,8,9,10] + > sort (>) (1..10); + [10,9,8,7,6,5,4,3,2,1] + + Have some fun with random lists, comparing our sort function with the one + from hello.pure. (The rand function is also declared in hello.pure; it is + just the rand() function from the C library.) + + > run hello.pure + Hello, world! + > let xs = [rand; i = 1..100000]; + > stats + > #sort (<) xs; + 100000 + 1.05s + > #qsort (<) xs; + 100000 + 14.05s + + The above results are for my Athlon 2500+. YMMV, but most likely you'll get + similar results indicating that the C implementation is much faster. That's + because the quicksort algorithm in hello.pure juggles around with lists, + whereas the C quicksort routine uses vectors and sorts the elements + in-place. */ + +#include <stdlib.h> +#include <pure/runtime.h> + +/* Set up a C callback which in turn invokes a Pure predicate to perform the + comparison of list elements. */ + +static pure_expr* cmp_p; +static int cmp(const void *xp, const void *yp) +{ + pure_expr *x = *(pure_expr**)xp, *y = *(pure_expr**)yp; + /* We use pure_appl to invoke the Pure predicate stored in cmp_p on the list + elements x and y passed by the qsort() routine. */ + pure_expr *p = pure_appl(cmp_p, 2, x, y); + int res = pure_is_int(p, &res) && res; /* x<y? */ + pure_freenew(p); /* collect temporary */ + if (res) + res = -1; + else { + /* Invoke cmp_p another time to perform the reverse comparison. */ + p = pure_appl(cmp_p, 2, y, x); + res = pure_is_int(p, &res) && res; /* y<x? */ + pure_freenew(p); /* collect temporary */ + /* Note that if both tests failed then the elements are either equal or + incomparable, in which case res==0. */ + } + return res; +} + +pure_expr *sort(pure_expr *p, pure_expr *xs) +{ + size_t size; + pure_expr **elems; + /* Deconstruct the list argument which is passed as a pure_expr* value. + This yields a vector of pure_expr* elements which can be passed to the + qsort() routine. */ + if (pure_is_listv(xs, &size, &elems)) { + pure_expr *ys; + /* Invoke qsort() to sort the elems vector. */ + cmp_p = p; + qsort(elems, size, sizeof(pure_expr*), cmp); + /* Construct a new list value from the sorted vector, to be returned as + the function result. */ + ys = pure_listv(size, elems); + /* The elems vector returned by pure_is_listv is malloc'ed, free it now so + that we don't leak memory. */ + free(elems); + return ys; + } else + /* The xs argument wasn't a proper list value, return a NULL pointer to + indicate failure. This will make the 'sort p xs' call a normal form. */ + return 0; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-25 23:00:44
|
Revision: 311 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=311&view=rev Author: agraef Date: 2008-06-25 16:00:24 -0700 (Wed, 25 Jun 2008) Log Message: ----------- Implement constant definitions. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/etc/pure-mode.el.in pure/trunk/etc/pure.lang pure/trunk/etc/pure.vim pure/trunk/etc/pure.xml pure/trunk/expr.cc pure/trunk/expr.hh pure/trunk/interpreter.cc pure/trunk/interpreter.hh pure/trunk/lexer.ll pure/trunk/parser.yy pure/trunk/printer.cc pure/trunk/pure.cc pure/trunk/test/test004.log Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-06-25 07:39:52 UTC (rev 310) +++ pure/trunk/ChangeLog 2008-06-25 23:00:24 UTC (rev 311) @@ -1,3 +1,13 @@ +2008-06-26 Albert Graef <Dr....@t-...> + + * interpreter.cc et al: Implement constant definitions, as + discussed on the mailing list. These work like variable + definitions (using the new 'def' keyword in lieu of 'let'), but + constants cannot be redefined (unless you first clear an existing + definition), and constant values are directly substituted into the + right-hand sides of equations rather than being evaluated at + runtime. + 2008-06-25 Albert Graef <Dr....@t-...> * examples/sort.c: Add another example for the runtime API. Modified: pure/trunk/etc/pure-mode.el.in =================================================================== --- pure/trunk/etc/pure-mode.el.in 2008-06-25 07:39:52 UTC (rev 310) +++ pure/trunk/etc/pure-mode.el.in 2008-06-25 23:00:24 UTC (rev 311) @@ -164,8 +164,8 @@ (list "\\<\\(catch\\|throw\\)\\>" 0 'font-lock-builtin-face) (list (concat "\\<\\(" - "case\\|e\\(lse\\|nd\\|xtern\\)\\|i\\(f\\|nfix[lr]?\\)\\|let\\|" - "nullary\\|o\\(f\\|therwise\\)\\|p\\(refix\\|ostfix\\)\\|" + "case\\|def\\|e\\(lse\\|nd\\|xtern\\)\\|i\\(f\\|nfix[lr]?\\)\\|" + "let\\|nullary\\|o\\(f\\|therwise\\)\\|p\\(refix\\|ostfix\\)\\|" "then\\|using\\|w\\(hen\\|ith\\)" "\\)\\>") 0 'font-lock-keyword-face)) @@ -178,8 +178,8 @@ (list "\\<\\(catch\\|throw\\)\\>" 0 'font-lock-builtin-face) (list (concat "\\<\\(" - "case\\|e\\(lse\\|nd\\|xtern\\)\\|i\\(f\\|nfix[lr]?\\)\\|let\\|" - "nullary\\|o\\(f\\|therwise\\)\\|p\\(refix\\|ostfix\\)\\|" + "case\\|def\\|e\\(lse\\|nd\\|xtern\\)\\|i\\(f\\|nfix[lr]?\\)\\|" + "let\\|nullary\\|o\\(f\\|therwise\\)\\|p\\(refix\\|ostfix\\)\\|" "then\\|using\\|w\\(hen\\|ith\\)" "\\)\\>") 0 'font-lock-keyword-face)) Modified: pure/trunk/etc/pure.lang =================================================================== --- pure/trunk/etc/pure.lang 2008-06-25 07:39:52 UTC (rev 310) +++ pure/trunk/etc/pure.lang 2008-06-25 23:00:24 UTC (rev 311) @@ -4,8 +4,8 @@ $DESCRIPTION=Pure # Pure keywords. -$KW_LIST(kwa)=infix infixl infixr prefix postfix nullary case else end extern -if let of otherwise then using when with +$KW_LIST(kwa)=infix infixl infixr prefix postfix nullary case def else end +extern if let of otherwise then using when with # These aren't really keywords but we want them to stick out anyway. $KW_LIST(kwb)=catch throw Modified: pure/trunk/etc/pure.vim =================================================================== --- pure/trunk/etc/pure.vim 2008-06-25 07:39:52 UTC (rev 310) +++ pure/trunk/etc/pure.vim 2008-06-25 23:00:24 UTC (rev 311) @@ -33,7 +33,7 @@ " keywords syn keyword pureKeyword infix infixl infixr prefix postfix nullary -syn keyword pureKeyword case else end extern if let of otherwise then +syn keyword pureKeyword case def else end extern if let of otherwise then syn keyword pureKeyword using when with syn keyword pureSpecial catch throw syn keyword pureType bigint bool char short int long double Modified: pure/trunk/etc/pure.xml =================================================================== --- pure/trunk/etc/pure.xml 2008-06-25 07:39:52 UTC (rev 310) +++ pure/trunk/etc/pure.xml 2008-06-25 23:00:24 UTC (rev 311) @@ -4,6 +4,7 @@ <highlighting> <list name="keywords"> <item> case </item> + <item> def </item> <item> else </item> <item> end </item> <item> extern </item> Modified: pure/trunk/expr.cc =================================================================== --- pure/trunk/expr.cc 2008-06-25 07:39:52 UTC (rev 310) +++ pure/trunk/expr.cc 2008-06-25 23:00:24 UTC (rev 311) @@ -234,6 +234,10 @@ ttag = e.ttag; p = new path(*e.p); break; + case cvar: + cval = new expr; + *cval = *e.cval; + break; case fvar: val = e.val; break; @@ -256,6 +260,9 @@ case lvar: delete p; break; + case cvar: + delete cval; + break; case fvar: break; case fun: @@ -272,6 +279,10 @@ ttag = e.ttag; p = new path(*e.p); break; + case cvar: + cval = new expr; + *cval = *e.cval; + break; case fvar: val = e.val; break; @@ -294,6 +305,9 @@ case lvar: delete p; break; + case cvar: + delete cval; + break; case fvar: break; case fun: Modified: pure/trunk/expr.hh =================================================================== --- pure/trunk/expr.hh 2008-06-25 07:39:52 UTC (rev 310) +++ pure/trunk/expr.hh 2008-06-25 23:00:24 UTC (rev 311) @@ -485,7 +485,7 @@ /* Environment entries. */ struct env_info { - enum { none, lvar, fvar, fun } t; + enum { none, lvar, cvar, fvar, fun } t; uint8_t temp; union { // local variable binding (lvar): @@ -493,6 +493,8 @@ int8_t ttag; path *p; }; + // constant definition (cvar): + expr *cval; // free variable definition (fvar): void *val; // pointer to memory location holding a runtime expression // function definition (fun): @@ -505,6 +507,8 @@ env_info() : t(none) { } env_info(int8_t _ttag, path _p, uint8_t _temp = 0) : t(lvar), temp(_temp), ttag(_ttag), p(new path(_p)) { } + env_info(expr x, uint8_t _temp = 0) + : t(cvar), temp(_temp), cval(new expr) { *cval = x; } env_info(void *v, uint8_t _temp = 0) : t(fvar), temp(_temp), val(v) { } env_info(uint32_t c, rulel r, uint8_t _temp = 0) Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-06-25 07:39:52 UTC (rev 310) +++ pure/trunk/interpreter.cc 2008-06-25 23:00:24 UTC (rev 311) @@ -537,8 +537,11 @@ int32_t f = it->first; const symbol& sym = symtab.sym(f); env::const_iterator jt = globenv.find(f); - if (jt != globenv.end() && jt->second.t == env_info::fun) { + if (jt != globenv.end() && jt->second.t == env_info::cvar) { restore_globals(g); + throw err("symbol '"+sym.s+"' is already defined as a constant"); + } else if (jt != globenv.end() && jt->second.t == env_info::fun) { + restore_globals(g); throw err("symbol '"+sym.s+"' is already defined as a function"); } else if (externals.find(f) != externals.end()) { restore_globals(g); @@ -559,6 +562,139 @@ return res; } +// Define global constants (macro definitions). + +pure_expr *interpreter::const_defn(expr pat, expr x) +{ + globals g; + save_globals(g); + pure_expr *e, *res = const_defn(pat, x, e); + if (!res && e) pure_free(e); + restore_globals(g); + return res; +} + +static expr pure_expr_to_expr(pure_expr *x) +{ + // FIXME: We might want to do stack checks here. + switch (x->tag) { + case EXPR::APP: + return expr(pure_expr_to_expr(x->data.x[0]), + pure_expr_to_expr(x->data.x[1])); + case EXPR::INT: + return expr(EXPR::INT, x->data.i); + case EXPR::BIGINT: { + // The expr constructor globbers its mpz_t argument, so take a copy. + mpz_t z; + mpz_init_set(z, x->data.z); + return expr(EXPR::BIGINT, z); + } + case EXPR::DBL: + return expr(EXPR::DBL, x->data.d); + case EXPR::STR: + return expr(EXPR::STR, x->data.s); + case EXPR::PTR: + if (x->data.p != 0) + // Only null pointer constants permitted right now. + throw err("pointer must be null in constant definition"); + return expr(EXPR::PTR, x->data.p); + default: + assert(x->tag > 0); + if (x->data.clos && x->data.clos->local) + // There's no way we can capture a local function in a compile time + // expression right now, so we have to forbid this, too. + throw err("anonymous closure not permitted in constant definition"); + return expr(x->tag); + } +} + +static expr subterm(expr x, const path& p) +{ + for (size_t i = 0, n = p.len(); i < n; i++) { + assert(x.tag() == EXPR::APP); + x = p[i]?x.xval2():x.xval1(); + } + return x; +} + +pure_expr *interpreter::const_defn(expr pat, expr x, pure_expr*& e) +{ + globals g; + save_globals(g); + compile(); + env vars; + expr lhs = bind(vars, pat), rhs = x; + build_env(vars, lhs); + for (env::const_iterator it = vars.begin(); it != vars.end(); ++it) { + int32_t f = it->first; + const symbol& sym = symtab.sym(f); + env::const_iterator jt = globenv.find(f); + if (jt != globenv.end() && jt->second.t == env_info::cvar) { + restore_globals(g); + throw err("symbol '"+sym.s+"' is already defined as a constant"); + } else if (jt != globenv.end() && jt->second.t == env_info::fvar) { + restore_globals(g); + throw err("symbol '"+sym.s+"' is already defined as a variable"); + } else if (jt != globenv.end() && jt->second.t == env_info::fun) { + restore_globals(g); + throw err("symbol '"+sym.s+"' is already defined as a function"); + } else if (externals.find(f) != externals.end()) { + restore_globals(g); + throw err("symbol '"+sym.s+ + "' is already declared as an extern function"); + } + } + compile(rhs); + pure_expr *res = doeval(rhs, e); + if (!res) return 0; + // convert the result back to a compile time expression + expr u = pure_expr_to_expr(res); + // match against the left-hand side + matcher m(rule(lhs, rhs)); + if (m.match(u)) { + // bind variables accordingly + for (env::const_iterator it = vars.begin(); it != vars.end(); ++it) { + assert(it->second.t == env_info::lvar && it->second.p); + int32_t f = it->first; + expr v = subterm(u, *it->second.p); + globenv[f] = env_info(v, temp); + } + } else { + pure_freenew(res); + res = 0; + } + restore_globals(g); + return res; +} + +void interpreter::const_defn(int32_t tag, pure_expr *x) +{ + assert(tag > 0 && x); + globals g; + save_globals(g); + symbol& sym = symtab.sym(tag); + env::const_iterator jt = globenv.find(tag); + if (jt != globenv.end() && jt->second.t == env_info::cvar) { + restore_globals(g); + throw err("symbol '"+sym.s+"' is already defined as a constant"); + } else if (jt != globenv.end() && jt->second.t == env_info::fvar) { + restore_globals(g); + throw err("symbol '"+sym.s+"' is already defined as a variable"); + } else if (jt != globenv.end() && jt->second.t == env_info::fun) { + restore_globals(g); + throw err("symbol '"+sym.s+"' is already defined as a function"); + } else if (externals.find(tag) != externals.end()) { + restore_globals(g); + throw err("symbol '"+sym.s+ + "' is already declared as an extern function"); + } + // convert the value to a compile time expression + expr u = pure_expr_to_expr(x); + // bind the variable + globenv[tag] = env_info(u, temp); + restore_globals(g); +} + // Process pending fundefs. void interpreter::mark_dirty(int32_t f) @@ -844,6 +980,29 @@ cout << ((double)clocks)/(double)CLOCKS_PER_SEC << "s\n"; } +void interpreter::define_const(rule *r) +{ + last.clear(); + pure_expr *e, *res = const_defn(r->lhs, r->rhs, e); + if ((verbose&verbosity::defs) != 0) + cout << "def " << r->lhs << " = " << r->rhs << ";\n"; + if (!res) { + ostringstream msg; + if (e) { + msg << "unhandled exception '" << e << "' while evaluating '" + << "def " << r->lhs << " = " << r->rhs << "'"; + pure_free(e); + } else + msg << "failed match while evaluating '" + << "def " << r->lhs << " = " << r->rhs << "'"; + throw err(msg.str()); + } + delete r; + pure_freenew(res); + if (interactive && stats) + cout << ((double)clocks)/(double)CLOCKS_PER_SEC << "s\n"; +} + void interpreter::clearsym(int32_t f) { // Check whether this symbol was already compiled; in that case @@ -962,7 +1121,9 @@ env::iterator it = e.find(f); const symbol& sym = symtab.sym(f); if (it != e.end()) { - if (it->second.t == env_info::fvar) + if (it->second.t == env_info::cvar) + throw err("symbol '"+sym.s+"' is already defined as a constant"); + else if (it->second.t == env_info::fvar) throw err("symbol '"+sym.s+"' is already defined as a variable"); else if (it->second.argc != argc) { ostringstream msg; @@ -1288,7 +1449,12 @@ // not a bound variable if (x.ttag() != 0) throw err("error in expression (misplaced type tag)"); - return x; + it = globenv.find(sym.f); + if (it != globenv.end() && it->second.t == env_info::cvar) + // substitute constant value + return *it->second.cval; + else + return x; } const env_info& info = it->second; return expr(EXPR::VAR, sym.f, idx, info.ttag, *info.p); @@ -1677,8 +1843,11 @@ save_globals(g); symbol& sym = symtab.sym(tag); env::const_iterator jt = globenv.find(tag); - if (jt != globenv.end() && jt->second.t == env_info::fun) { + if (jt != globenv.end() && jt->second.t == env_info::cvar) { restore_globals(g); + throw err("symbol '"+sym.s+"' is already defined as a constant"); + } else if (jt != globenv.end() && jt->second.t == env_info::fun) { + restore_globals(g); throw err("symbol '"+sym.s+"' is already defined as a function"); } else if (externals.find(tag) != externals.end()) { restore_globals(g); @@ -3427,7 +3596,9 @@ case EXPR::STR: return sbox(x.sval()); case EXPR::PTR: - assert(0 && "not implemented"); + // FIXME: Only null pointers are supported right now. + assert(x.pval() == 0); + return pbox(x.pval()); // application: case EXPR::APP: if (x.ttag() != 0) { @@ -3764,6 +3935,11 @@ return call("pure_string_dup", s); } +Value *interpreter::pbox(void *p) +{ + return call("pure_pointer", p); +} + // Variable access. static uint32_t argno(uint32_t n, path &p) @@ -3987,6 +4163,12 @@ return call(name, p); } +Value *interpreter::call(string name, void *p) +{ + assert(p==0); + return call(name, ConstantPointerNull::get(VoidPtrTy)); +} + Value *interpreter::call(string name, Value *x, const char *s) { Env& e = act_env(); Modified: pure/trunk/interpreter.hh =================================================================== --- pure/trunk/interpreter.hh 2008-06-25 07:39:52 UTC (rev 310) +++ pure/trunk/interpreter.hh 2008-06-25 23:00:24 UTC (rev 311) @@ -310,24 +310,39 @@ /* Evaluate an expression and define global variables. This works like eval() above, but also binds the variables in pat to the corresponding values. Also, these routines throw a C++ exception of the err type if any - of the variable symbols to be defined is already bound to a function. - Otherwise the result is the evaluated expression to be matched. Returns a - null pointer if an exception occurred during the evaluation or if the - pattern failed to match. Both the result and the exception value (if any) - are to be freed by the caller. */ + of the variable symbols to be defined is already bound to a different + kind of symbol. Otherwise the result is the evaluated expression to be + matched. Returns a null pointer if an exception occurred during the + evaluation or if the pattern failed to match. Both the result and the + exception value (if any) are to be freed by the caller. */ pure_expr *defn(expr pat, expr x); pure_expr *defn(expr pat, expr x, pure_expr*& e); /* Bind a global variable to a given value. This binds the given variable symbol directly to the given value, without matching and evaluating - anything. It is still checked whether the variable symbol is already - bound to a function, in which case an err exception is thrown. */ + anything. It is still checked that the variable symbol is not already + bound to a different kind of symbol, otherwise an err exception is + thrown. */ void defn(int32_t tag, pure_expr *x); void defn(const char *varname, pure_expr *x) { defn(symtab.sym(varname).f, x); } + /* Constant definitions. These work like the variable definition methods + above, but define constant symbols which are directly substituted into + the right-hand sides of equations rather than being evaluated at + runtime. The right-hand side expression is evaluated and matched against + the left-hand side pattern as usual. Unlike variables, existing constant + symbols cannot be redefined, so they have to be cleared before you can + give them new values. */ + + pure_expr *const_defn(expr pat, expr x); + pure_expr *const_defn(expr pat, expr x, pure_expr*& e); + void const_defn(int32_t tag, pure_expr *x); + void const_defn(const char *varname, pure_expr *x) + { const_defn(symtab.sym(varname).f, x); } + /* Process pending compilations of function definitions. This is also done - automatically when eval() or defn() is invoked. */ + automatically when eval() or defn()/const_defn() is invoked. */ void compile(); /* Errors and warnings. These are for various types of messages from the @@ -352,6 +367,7 @@ void compile(expr x); void declare(prec_t prec, fix_t fix, list<string> *ids); void define(rule *r); + void define_const(rule *r); void exec(expr *x); void clear(int32_t f = 0); void clearsym(int32_t f); @@ -466,6 +482,7 @@ llvm::Value *call(string name, const mpz_t& z); llvm::Value *call(string name, double d); llvm::Value *call(string name, const char *s); + llvm::Value *call(string name, void *p); llvm::Value *call(string name, llvm::Value *x, const mpz_t& z); llvm::Value *call(string name, llvm::Value *x, const char *s); void make_bigint(const mpz_t& z, llvm::Value*& sz, llvm::Value*& ptr); Modified: pure/trunk/lexer.ll =================================================================== --- pure/trunk/lexer.ll 2008-06-25 07:39:52 UTC (rev 310) +++ pure/trunk/lexer.ll 2008-06-25 23:00:24 UTC (rev 311) @@ -131,9 +131,9 @@ now. */ static const char *commands[] = { - "cd", "clear", "extern", "help", "infix", "infixl", "infixr", "let", "list", - "ls", "nullary", "override", "postfix", "prefix", "pwd", "quit", "run", - "save", "stats", "underride", "using", 0 + "cd", "clear", "def", "extern", "help", "infix", "infixl", "infixr", "let", + "list", "ls", "nullary", "override", "postfix", "prefix", "pwd", "quit", + "run", "save", "stats", "underride", "using", 0 }; static char * @@ -399,7 +399,7 @@ int32_t f = it->first; const env_info& e = it->second; const symbol& sym = interp.symtab.sym(f); - if (!((e.t == env_info::fvar)?vflag:fflag)) continue; + if (!((e.t == env_info::fun)?fflag:vflag)) continue; bool matches = e.temp >= tflag; if (!matches && !sflag && args.l.empty() && e.t == env_info::fun && fflag) { @@ -486,6 +486,17 @@ } else sout << "let " << sym.s << " = " << *(pure_expr**)jt->second.val << ";\n"; + } else if (jt->second.t == env_info::cvar) { + nvars++; + if (sflag) { + sout << sym.s << string(maxsize-sym.s.size(), ' ') + << " cst"; + if (lflag) sout << " " << sym.s << " = " + << *jt->second.cval << ";"; + sout << endl; + } else + sout << "def " << sym.s << " = " << *jt->second.cval + << ";\n"; } else { if (xt != interp.externals.end()) { const ExternInfo& info = xt->second; @@ -743,6 +754,7 @@ prefix yylval->fix = prefix; return token::FIX; postfix yylval->fix = postfix; return token::FIX; nullary return token::NULLARY; +def return token::DEF; let return token::LET; case return token::CASE; of return token::OF; Modified: pure/trunk/parser.yy =================================================================== --- pure/trunk/parser.yy 2008-06-25 07:39:52 UTC (rev 310) +++ pure/trunk/parser.yy 2008-06-25 23:00:24 UTC (rev 311) @@ -98,6 +98,7 @@ %token NULLARY "nullary" %token <fix> FIX "fixity" +%token DEF "def" %token LET "let" %token CASE "case" %token OF "of" @@ -274,6 +275,8 @@ { action(interp.exec($1), delete $1); } | LET simple_rule { action(interp.define($2), delete $2); } +| DEF simple_rule +{ action(interp.define_const($2), delete $2); } | rule { rulel *rl = 0; action(interp.add_rules(interp.globenv, Modified: pure/trunk/printer.cc =================================================================== --- pure/trunk/printer.cc 2008-06-25 07:39:52 UTC (rev 310) +++ pure/trunk/printer.cc 2008-06-25 23:00:24 UTC (rev 311) @@ -421,6 +421,9 @@ } break; } + case env_info::cvar: + os << "def " << sym.s << " = " << *info.cval; + break; case env_info::fvar: os << "let " << sym.s << " = " << *(pure_expr**)info.val; break; @@ -628,8 +631,6 @@ assert(x); //os << "{" << x->refc << "}"; switch (x->tag) { - case 0: - return os << "<<anonymous closure " << (void*)x << ">>"; case EXPR::INT: return os << x->data.i; case EXPR::BIGINT: { @@ -744,8 +745,11 @@ return os << pure_paren(95, u) << " " << pure_paren(100, v); } default: { - assert(x->tag > 0); + if (x->tag == 0) + return os << "<<closure " << (void*)x << ">>"; const symbol& sym = interpreter::g_interp->symtab.sym(x->tag); + if (x->data.clos && x->data.clos->local) + return os << "<<closure " << sym.s << ">>"; if (sym.prec < 10) return os << '(' << sym.s << ')'; else Modified: pure/trunk/pure.cc =================================================================== --- pure/trunk/pure.cc 2008-06-25 07:39:52 UTC (rev 310) +++ pure/trunk/pure.cc 2008-06-25 23:00:24 UTC (rev 311) @@ -47,9 +47,9 @@ #define LICENSE "This program is free software distributed under the GNU Public License\n(GPL V3 or later). Please see the COPYING file for details.\n" static const char *commands[] = { - "cd", "clear", "extern", "help", "infix", "infixl", "infixr", "let", "list", - "ls", "nullary", "override", "postfix", "prefix", "pwd", "quit", "run", - "save", "stats", "underride", "using", 0 + "cd", "clear", "def", "extern", "help", "infix", "infixl", "infixr", "let", + "list", "ls", "nullary", "override", "postfix", "prefix", "pwd", "quit", + "run", "save", "stats", "underride", "using", 0 }; /* Generator functions for command completion. */ Modified: pure/trunk/test/test004.log =================================================================== --- pure/trunk/test/test004.log 2008-06-25 07:39:52 UTC (rev 310) +++ pure/trunk/test/test004.log 2008-06-25 23:00:24 UTC (rev 311) @@ -35,15 +35,15 @@ foo 99; 99 foo2 99; -bar 100 +<<closure bar>> 100 foo2 98; -bar 98 +<<closure bar>> 98 foo3 99; -bar +<<closure bar>> foo3 99 98; -bar 98 +<<closure bar>> 98 foo3 99 99; -bar 100 +<<closure bar>> 100 loop = loop; count n/*0:1*/ = ct/*0*/ n/*0:1*/ with ct n/*0:1*/::int = n/*0:1*/ if n/*0:1*/<=0; ct n/*0:1*/::int = ct/*1*/ (n/*0:1*/-1) { rule #0: ct n::int = n if n<=0 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-26 08:56:58
|
Revision: 314 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=314&view=rev Author: agraef Date: 2008-06-26 01:57:06 -0700 (Thu, 26 Jun 2008) Log Message: ----------- Fix up list command to properly deal with the new constant symbol category. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/lexer.ll Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-06-26 08:14:31 UTC (rev 313) +++ pure/trunk/ChangeLog 2008-06-26 08:57:06 UTC (rev 314) @@ -1,5 +1,9 @@ 2008-06-26 Albert Graef <Dr....@t-...> + * lexer.ll: Fix up list command to properly deal with the new + constant symbol category. -c now lists constant symbols, the + previous -c option (print matching automata) was renamed to -a. + * interpreter.cc et al: Implement constant definitions, as discussed on the mailing list. These work like variable definitions (using the new 'def' keyword in lieu of 'let'), but Modified: pure/trunk/lexer.ll =================================================================== --- pure/trunk/lexer.ll 2008-06-26 08:14:31 UTC (rev 313) +++ pure/trunk/lexer.ll 2008-06-26 08:57:06 UTC (rev 314) @@ -331,8 +331,9 @@ if (!interp.interactive) REJECT; uint8_t s_verbose = interpreter::g_verbose; uint8_t tflag = 0; - bool cflag = false, dflag = false, eflag = false, gflag = false; - bool fflag = false, vflag = false, lflag = false, sflag = false; + bool aflag = false, dflag = false, eflag = false; + bool cflag = false, fflag = false, vflag = false; + bool gflag = false, lflag = false, sflag = false; const char *s = yytext+4; if (*s && !isspace(*s)) REJECT; yylloc->step(); @@ -345,6 +346,7 @@ if (s[0] != '-' || !s[1] || !strchr("cdefghlstv", s[1])) break; while (*++s) { switch (*s) { + case 'a': aflag = true; break; case 'c': cflag = true; break; case 'd': dflag = true; break; case 'e': eflag = true; break; @@ -363,13 +365,13 @@ case 'h': cout << "list command help: list [options ...] [symbol ...]\n\ Options may be combined, e.g., list -tvl is the same as list -t -v -l.\n\ --c Annotate printed definitions with compiled code snippets. Useful\n\ - for debugging purposes.\n\ +-a Disassembles pattern matching automata. Useful for debugging purposes.\n\ +-c Print information about constant symbols.\n\ -d Disassembles LLVM IR, showing the generated LLVM assembler code of a\n\ - function.\n\ + function. Useful for debugging purposes.\n\ -e Annotate printed definitions with lexical environment information\n\ (de Bruijn indices, subterm paths). Useful for debugging purposes.\n\ --f Print information about function symbols only.\n\ +-f Print information about function symbols.\n\ -g Indicates that the following symbols are actually shell glob patterns\n\ and that all matching symbols should be listed.\n\ -h Print this list.\n\ @@ -379,7 +381,7 @@ -t[level] List only symbols and definitions at the given temporary level\n\ (the current level by default) or above. Level 1 denotes all temporary\n\ definitions, level 0 *all* definitions (the default if -t is omitted).\n\ --v Print information about variable symbols only.\n"; +-v Print information about variable symbols.\n"; goto out; default: cerr << "list: invalid option character '" << *s << "'\n"; @@ -389,19 +391,22 @@ } args.l.erase(args.l.begin(), arg); if (eflag) interpreter::g_verbose |= verbosity::envs; - if (cflag) interpreter::g_verbose |= verbosity::code; + if (aflag) interpreter::g_verbose |= verbosity::code; if (dflag) interpreter::g_verbose |= verbosity::dump; - if (!fflag && !vflag) fflag = vflag = true; + if (!cflag && !fflag && !vflag) cflag = fflag = vflag = true; if (lflag) sflag = true; { - size_t maxsize = 0, nfuns = 0, nvars = 0, nrules = 0; + size_t maxsize = 0, nfuns = 0, nvars = 0, ncsts = 0, nrules = 0; list<env_sym> l; set<int32_t> syms; for (env::const_iterator it = interp.globenv.begin(); it != interp.globenv.end(); ++it) { int32_t f = it->first; const env_info& e = it->second; const symbol& sym = interp.symtab.sym(f); - if (!((e.t == env_info::fun)?fflag:vflag)) continue; + if (!((e.t == env_info::fun)?fflag: + (e.t == env_info::cvar)?cflag: + (e.t == env_info::fvar)?vflag:0)) + continue; bool matches = e.temp >= tflag; if (!matches && !sflag && args.l.empty() && e.t == env_info::fun && fflag) { @@ -456,7 +461,7 @@ } } l.sort(env_compare); - if (!l.empty() && (cflag||dflag)) interp.compile(); + if (!l.empty() && (aflag||dflag)) interp.compile(); // we first dump the entire listing into a string and then output that // string through more ostringstream sout; @@ -489,7 +494,7 @@ sout << "let " << sym.s << " = " << *(pure_expr**)jt->second.val << ";\n"; } else if (jt->second.t == env_info::cvar) { - nvars++; + ncsts++; if (sflag) { sout << sym.s << string(maxsize-sym.s.size(), ' ') << " cst"; @@ -517,7 +522,7 @@ sout << sym.s << string(maxsize-sym.s.size(), ' ') << " fun"; if (lflag) { sout << " " << rules << ";"; - if (cflag && m) sout << endl << *m; + if (aflag && m) sout << endl << *m; if (dflag && fenv != interp.globalfuns.end() && fenv->second.f) interp.print_defs(sout, fenv->second); } else { @@ -534,7 +539,7 @@ } } if (n > 0) { - if (cflag && m) sout << *m << endl; + if (aflag && m) sout << *m << endl; if (dflag && fenv != interp.globalfuns.end() && fenv->second.f) interp.print_defs(sout, fenv->second); nrules += n; @@ -544,12 +549,22 @@ } } if (sflag) { - if (fflag && vflag) + if (fflag && vflag && cflag) + sout << ncsts << " constants, " << nvars << " variables, " + << nfuns << " functions, " << nrules << " rules\n"; + else if (fflag && cflag) + sout << ncsts << " constants, " << nfuns << " functions, " + << nrules << " rules\n"; + else if (fflag && vflag) sout << nvars << " variables, " << nfuns << " functions, " << nrules << " rules\n"; + else if (cflag && vflag) + sout << ncsts << " constants, " << nvars << " variables\n"; + else if (cflag) + sout << ncsts << " constants\n"; else if (vflag) sout << nvars << " variables\n"; - else + else if (fflag) sout << nfuns << " functions, " << nrules << " rules\n"; } FILE *fp; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-27 00:11:49
|
Revision: 317 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=317&view=rev Author: agraef Date: 2008-06-26 17:11:58 -0700 (Thu, 26 Jun 2008) Log Message: ----------- Fix up completion support, second attempt. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc pure/trunk/lexer.ll pure/trunk/pure.cc pure/trunk/symtable.hh Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-06-26 23:12:44 UTC (rev 316) +++ pure/trunk/ChangeLog 2008-06-27 00:11:58 UTC (rev 317) @@ -1,3 +1,9 @@ +2008-06-27 Albert Graef <Dr....@t-...> + + * pure.cc, interpreter.cc, lexer.ll: Fix up completion support, + second attempt (constructor symbols without any rules were + still missing). + 2008-06-26 Albert Graef <Dr....@t-...> * lexer.ll: Fix up list command to properly deal with the new Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-06-26 23:12:44 UTC (rev 316) +++ pure/trunk/interpreter.cc 2008-06-27 00:11:58 UTC (rev 317) @@ -926,8 +926,21 @@ delete ids; throw err("conflicting fixity declaration for symbol '"+id+"'"); } - } else - symtab.sym(*it, prec, fix); + } else { + int32_t tag = symtab.sym(*it, prec, fix).f; + /* KLUDGE: Already create a globalvars entry here, so that the symbol is + properly recognized by the completion routines. */ + pure_expr *cv = pure_const(tag); + assert(JIT); + GlobalVar& v = globalvars[tag]; + if (!v.v) { + v.v = new llvm::GlobalVariable + (ExprPtrTy, false, llvm::GlobalVariable::InternalLinkage, 0, + mkvarlabel(tag), module); + JIT->addGlobalMapping(v.v, &v.x); + } + if (v.x) pure_free(v.x); v.x = pure_new(cv); + } } delete ids; } Modified: pure/trunk/lexer.ll =================================================================== --- pure/trunk/lexer.ll 2008-06-26 23:12:44 UTC (rev 316) +++ pure/trunk/lexer.ll 2008-06-27 00:11:58 UTC (rev 317) @@ -136,12 +136,13 @@ "run", "save", "stats", "underride", "using", 0 }; +typedef map<string, symbol> symbol_map; + static char * command_generator(const char *text, int state) { static int list_index, len; - static env::iterator it, end; - static extmap::iterator xit, xend; + static symbol_map::iterator it, end; const char *name; assert(interpreter::g_interp); interpreter& interp = *interpreter::g_interp; @@ -149,10 +150,11 @@ /* New match. */ if (!state) { list_index = 0; - it = interp.globenv.begin(); - end = interp.globenv.end(); - xit = interp.externals.begin(); - xend = interp.externals.end(); + /* Must do this here, so that symbols are entered into the globalvars + table. */ + interp.compile(); + it = interp.symtab.tab.begin(); + end = interp.symtab.tab.end(); len = strlen(text); } @@ -167,22 +169,19 @@ /* Return the next name which partially matches from the symbol list. */ while (it != end) { - assert(it->first > 0); - symbol& sym = interp.symtab.sym(it->first); + int32_t f = it->second.f; + /* Skip non-toplevel symbols. */ + if (interp.globalvars.find(f) == interp.globalvars.end() && + interp.externals.find(f) == interp.externals.end()) { + it++; + continue; + } + const string& s = it->first; it++; - if (strncmp(sym.s.c_str(), text, len) == 0) - return strdup(sym.s.c_str()); + if (strncmp(s.c_str(), text, len) == 0) + return strdup(s.c_str()); } - /* Also process the declared externals which don't have any rules yet. */ - while (xit != xend) { - assert(xit->first > 0); - symbol& sym = interp.symtab.sym(xit->first); - xit++; - if (strncmp(sym.s.c_str(), text, len) == 0) - return strdup(sym.s.c_str()); - } - /* If no names matched, then return NULL. */ return 0; } Modified: pure/trunk/pure.cc =================================================================== --- pure/trunk/pure.cc 2008-06-26 23:12:44 UTC (rev 316) +++ pure/trunk/pure.cc 2008-06-27 00:11:58 UTC (rev 317) @@ -54,14 +54,13 @@ /* Generator functions for command completion. */ -typedef map<int32_t,ExternInfo> extmap; +typedef map<string, symbol> symbol_map; static char * command_generator(const char *text, int state) { static int list_index, len; - static env::iterator it, end; - static extmap::iterator xit, xend; + static symbol_map::iterator it, end; const char *name; assert(interpreter::g_interp); interpreter& interp = *interpreter::g_interp; @@ -69,10 +68,11 @@ /* New match. */ if (!state) { list_index = 0; - it = interp.globenv.begin(); - end = interp.globenv.end(); - xit = interp.externals.begin(); - xend = interp.externals.end(); + /* Must do this here, so that symbols are entered into the globalvars + table. */ + interp.compile(); + it = interp.symtab.tab.begin(); + end = interp.symtab.tab.end(); len = strlen(text); } @@ -87,22 +87,19 @@ /* Return the next name which partially matches from the symbol list. */ while (it != end) { - assert(it->first > 0); - symbol& sym = interp.symtab.sym(it->first); + int32_t f = it->second.f; + /* Skip non-toplevel symbols. */ + if (interp.globalvars.find(f) == interp.globalvars.end() && + interp.externals.find(f) == interp.externals.end()) { + it++; + continue; + } + const string& s = it->first; it++; - if (strncmp(sym.s.c_str(), text, len) == 0) - return strdup(sym.s.c_str()); + if (strncmp(s.c_str(), text, len) == 0) + return strdup(s.c_str()); } - /* Also process the declared externals which don't have any rules yet. */ - while (xit != xend) { - assert(xit->first > 0); - symbol& sym = interp.symtab.sym(xit->first); - xit++; - if (strncmp(sym.s.c_str(), text, len) == 0) - return strdup(sym.s.c_str()); - } - /* If no names matched, then return NULL. */ return 0; } @@ -111,39 +108,36 @@ symbol_generator(const char *text, int state) { static int len; - static env::iterator it, end; - static extmap::iterator xit, xend; + static symbol_map::iterator it, end; assert(interpreter::g_interp); interpreter& interp = *interpreter::g_interp; /* New match. */ if (!state) { - it = interp.globenv.begin(); - end = interp.globenv.end(); - xit = interp.externals.begin(); - xend = interp.externals.end(); + /* Must do this here, so that symbols are entered into the globalvars + table. */ + interp.compile(); + it = interp.symtab.tab.begin(); + end = interp.symtab.tab.end(); len = strlen(text); } /* Return the next name which partially matches from the symbol list. */ while (it != end) { - assert(it->first > 0); - symbol& sym = interp.symtab.sym(it->first); + int32_t f = it->second.f; + /* Skip non-toplevel symbols. */ + if (interp.globalvars.find(f) == interp.globalvars.end() && + interp.externals.find(f) == interp.externals.end()) { + it++; + continue; + } + const string& s = it->first; it++; - if (strncmp(sym.s.c_str(), text, len) == 0) - return strdup(sym.s.c_str()); + if (strncmp(s.c_str(), text, len) == 0) + return strdup(s.c_str()); } - /* Also process the declared externals which don't have any rules yet. */ - while (xit != xend) { - assert(xit->first > 0); - symbol& sym = interp.symtab.sym(xit->first); - xit++; - if (strncmp(sym.s.c_str(), text, len) == 0) - return strdup(sym.s.c_str()); - } - /* If no names matched, then return NULL. */ return 0; } Modified: pure/trunk/symtable.hh =================================================================== --- pure/trunk/symtable.hh 2008-06-26 23:12:44 UTC (rev 316) +++ pure/trunk/symtable.hh 2008-06-27 00:11:58 UTC (rev 317) @@ -32,9 +32,9 @@ class symtable { int32_t fno; +public: map<string, symbol> tab; vector<symbol*> rtab; -public: symtable(); // add default declarations for the builtin constants and operators (to be // invoked *after* possibly reading the prelude) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-27 00:27:46
|
Revision: 319 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=319&view=rev Author: agraef Date: 2008-06-26 17:27:54 -0700 (Thu, 26 Jun 2008) Log Message: ----------- Bugfix in new completion functions. Modified Paths: -------------- pure/trunk/lexer.ll pure/trunk/pure.cc Modified: pure/trunk/lexer.ll =================================================================== --- pure/trunk/lexer.ll 2008-06-27 00:24:41 UTC (rev 318) +++ pure/trunk/lexer.ll 2008-06-27 00:27:54 UTC (rev 319) @@ -171,7 +171,8 @@ while (it != end) { int32_t f = it->second.f; /* Skip non-toplevel symbols. */ - if (interp.globalvars.find(f) == interp.globalvars.end() && + if (interp.globenv.find(f) == interp.globenv.end() && + interp.globalvars.find(f) == interp.globalvars.end() && interp.externals.find(f) == interp.externals.end()) { it++; continue; Modified: pure/trunk/pure.cc =================================================================== --- pure/trunk/pure.cc 2008-06-27 00:24:41 UTC (rev 318) +++ pure/trunk/pure.cc 2008-06-27 00:27:54 UTC (rev 319) @@ -89,7 +89,8 @@ while (it != end) { int32_t f = it->second.f; /* Skip non-toplevel symbols. */ - if (interp.globalvars.find(f) == interp.globalvars.end() && + if (interp.globenv.find(f) == interp.globenv.end() && + interp.globalvars.find(f) == interp.globalvars.end() && interp.externals.find(f) == interp.externals.end()) { it++; continue; @@ -127,7 +128,8 @@ while (it != end) { int32_t f = it->second.f; /* Skip non-toplevel symbols. */ - if (interp.globalvars.find(f) == interp.globalvars.end() && + if (interp.globenv.find(f) == interp.globenv.end() && + interp.globalvars.find(f) == interp.globalvars.end() && interp.externals.find(f) == interp.externals.end()) { it++; continue; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-27 10:28:16
|
Revision: 321 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=321&view=rev Author: agraef Date: 2008-06-27 03:28:24 -0700 (Fri, 27 Jun 2008) Log Message: ----------- Add some more stuff to the public runtime API. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-06-27 09:24:38 UTC (rev 320) +++ pure/trunk/ChangeLog 2008-06-27 10:28:24 UTC (rev 321) @@ -1,5 +1,8 @@ 2008-06-27 Albert Graef <Dr....@t-...> + * runtime.cc/h: Added pure_current_interp(), variable and constant + definitions, management of temporary definition levels. + * pure.cc, interpreter.cc, lexer.ll: Fix up completion support, second attempt (constructor symbols without any rules were still missing). Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-06-27 09:24:38 UTC (rev 320) +++ pure/trunk/runtime.cc 2008-06-27 10:28:24 UTC (rev 321) @@ -801,6 +801,63 @@ pure_unref_internal(x); } +extern "C" +bool pure_let(int32_t sym, pure_expr *x) +{ + if (sym <= 0 || !x) return false; + try { + interpreter& interp = *interpreter::g_interp; + interp.defn(sym, x); + return true; + } catch (err &e) { + return false; + } +} + +extern "C" +bool pure_def(int32_t sym, pure_expr *x) +{ + if (sym <= 0 || !x) return false; + try { + interpreter& interp = *interpreter::g_interp; + interp.const_defn(sym, x); + return true; + } catch (err &e) { + return false; + } +} + +extern "C" +bool pure_clear(int32_t sym) +{ + if (sym > 0) { + interpreter& interp = *interpreter::g_interp; + interp.clear(); + return true; + } else + return false; +} + +extern "C" +uint8_t pure_save() +{ + interpreter& interp = *interpreter::g_interp; + if (interp.temp < 0xff) + return ++interp.temp; + else + return 0; +} + +extern "C" +uint8_t pure_restore() +{ + interpreter& interp = *interpreter::g_interp; + uint8_t level = interp.temp; + interp.clear(); + if (level > 0 && interp.temp > level-1) --interp.temp; + return interp.temp; +} + #ifndef HOST #define HOST "unknown" #endif @@ -939,6 +996,12 @@ interpreter::g_interp = (interpreter*)interp; } +extern "C" +pure_interp *pure_current_interp() +{ + return (pure_interp*)interpreter::g_interp; +} + /* END OF PUBLIC API. *******************************************************/ extern "C" Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-06-27 09:24:38 UTC (rev 320) +++ pure/trunk/runtime.h 2008-06-27 10:28:24 UTC (rev 321) @@ -141,18 +141,14 @@ corresponding values. Parameter pointers may be NULL in which case they are not set. - Notes: + NOTES: pure_is_mpz takes a pointer to an uninitialized mpz_t and + initializes it with a copy of the Pure bigint. pure_is_symbol will return + true not only for (constant and unbound variable) symbols, but also for + arbitrary closures including local and anonymous functions. In the case of + an anonymous closure, the returned symbol will be 0. You can check whether + an expression actually represents a named or anonymous closure using the + funp and lambdap predicates from the library API (see below). */ - - pure_is_mpz takes a pointer to an uninitialized mpz_t and initializes it - with a copy of the Pure bigint. - - - pure_is_symbol will return true not only for (constant and unbound - variable) symbols, but also for arbitrary closures including local and - anonymous functions. In the case of an anonymous closure, the returned - symbol will be 0. You can check whether an expression actually represents - a named or anonymous closure using the funp and lambdap predicates from - the library API (see below). */ - bool pure_is_symbol(const pure_expr *x, int32_t *sym); bool pure_is_int(const pure_expr *x, int32_t *i); bool pure_is_mpz(const pure_expr *x, mpz_t *z); @@ -221,20 +217,54 @@ void pure_ref(pure_expr *x); void pure_unref(pure_expr *x); +/* Variable and constant definitions. These allow you to directly bind + variable and constant symbols to pure_expr* values, as the 'let' and 'def' + constructs do in the Pure language. The functions return true if + successful, false otherwise. */ + +bool pure_let(int32_t sym, pure_expr *x); +bool pure_def(int32_t sym, pure_expr *x); + +/* Purge the definition of a global (constant, variable or function) symbol. */ + +bool pure_clear(int32_t sym); + +/* Manage temporary definition levels (see the Pure manual for details). + pure_save starts a new level, pure_restore returns to the previous level, + removing all definitions of the current level. In either case the new level + is returned. A zero return value of pure_save indicates an error condition, + most likely because the maximum number of levels was exceeded. + + Note that the command line version of the interpreter starts at temporary + level 1, while the standalone interpreters created with the public API (see + below) start at level 0. Hence in the latter case you first need to invoke + pure_save before you can define temporaries. */ + +uint8_t pure_save(); +uint8_t pure_restore(); + /* The following routines provide standalone C/C++ applications with fully initialized interpreter instances which can be used together with the operations listed above. This is only needed for modules which are not to - be loaded by the command line version of the interpreter. + be loaded by the command line version of the interpreter. */ - The argc, argv parameters passed to pure_create_interp specify the command - line arguments of the interpreter instance. This includes any scripts that - are to be loaded on startup as well as any other options understood by the - command line version of the interpreter (options like -i and -q won't have - any effect, though, and the interpreter will always be in non-interactive - mode). The argv vector must be NULL-terminated, and argv[0] should be set - to the name of the hosting application (usually the main program of the - application). +/* The pure_interp type serves as a C proxy for Pure interpreters. Pointers + to these are used as C handles for the real Pure interpreter objects (which + are actually implemented by a C++ class). If your application needs more + elaborate control over interpreters as provided by this API, pure_interp* + can be cast to interpreter* (cf. interpreter.hh in the Pure sources). */ +typedef struct _pure_interp pure_interp; + +/* Manage interpreter instances. The argc, argv parameters passed to + pure_create_interp specify the command line arguments of the interpreter + instance. This includes any scripts that are to be loaded on startup as + well as any other options understood by the command line version of the + interpreter. (Options like -i and -q won't have any effect, though, and the + interpreter will always be in non-interactive mode.) The argv vector must + be NULL-terminated, and argv[0] should be set to the name of the hosting + application (usually the main program of the application). + An application may use multiple interpreter instances, but only a single instance can be active at any one time. By default, the first created instance will be active, but you can switch between different instances @@ -242,7 +272,10 @@ destroys an interpreter instance; if the destroyed instance is currently active, the active instance will be undefined afterwards, so you'll have to either create or switch to another instance before calling any other - operations. + operations. The pure_current_interp returns the currently active + instance. If the application is hosted by the command line interpreter, + this will return a handle to the command line interpreter if it is invoked + before switching to any other interpreter instance. Note that when using different interpreter instances in concert, it is *not* possible to pass pure_expr* values created with one interpreter @@ -250,11 +283,10 @@ the library API (see below) to first unparse the expression in the source interpreter and then reparse it in the target interpreter. */ -typedef struct _pure_interp pure_interp; // Pure interpreter handles (opaque). - pure_interp *pure_create_interp(int argc, char *argv[]); void pure_delete_interp(pure_interp *interp); void pure_switch_interp(pure_interp *interp); +pure_interp *pure_current_interp(); /* END OF PUBLIC API. *******************************************************/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-27 19:20:04
|
Revision: 323 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=323&view=rev Author: agraef Date: 2008-06-27 12:20:13 -0700 (Fri, 27 Jun 2008) Log Message: ----------- Rename the slicing operator to 'svn diff'. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/lib/prelude.pure pure/trunk/test/prelude.log Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-06-27 18:44:55 UTC (rev 322) +++ pure/trunk/ChangeLog 2008-06-27 19:20:13 UTC (rev 323) @@ -1,5 +1,9 @@ 2008-06-27 Albert Graef <Dr....@t-...> + * lib/prelude.pure: Using xs!ns for slicing conflicts with more + general indexing of containers with arbitrary keys. Use !! for + slicing instead. Reported by Jiri Spitz. + * runtime.cc/h: Added pure_current_interp(), variable and constant definitions, management of temporary definition levels. Modified: pure/trunk/lib/prelude.pure =================================================================== --- pure/trunk/lib/prelude.pure 2008-06-27 18:44:55 UTC (rev 322) +++ pure/trunk/lib/prelude.pure 2008-06-27 19:20:13 UTC (rev 323) @@ -59,7 +59,7 @@ prefix 7 ~ ; // bitwise not infixr 8 ^ ; // exponentiation prefix 8 # ; // size operator -infixl 9 ! ; // indexing +infixl 9 ! !! ; // indexing, slicing infixr 9 . ; // function composition /* Pull in the primitives (arithmetic etc.) and the standard string functions. @@ -185,19 +185,19 @@ accum ys xs = ys,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 - zero-based indices and thus, in particular, on the list and tuple +/* 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 zero-based indices and thus, in particular, on the list and tuple structures defined above. */ -xs![] = []; -xs!(n:ns) = accum [] (n:ns) with +xs!![] = []; +xs!!(n:ns) = accum [] (n:ns) with accum ys [] = reverse ys; accum ys (n::int:ns) = accum (xs!n:ys) ns if n>=0 && n<m; = accum ys ns otherwise; accum ys (n:ns) = accum (xs!n:ys) ns if n>=0 && n<m; = accum ys ns otherwise; - accum ys ns = reverse ys+xs!ns; + accum ys ns = reverse ys+xs!!ns; end when m::int = #xs end; /* Arithmetic sequences. */ Modified: pure/trunk/test/prelude.log =================================================================== --- pure/trunk/test/prelude.log 2008-06-27 18:44:55 UTC (rev 322) +++ pure/trunk/test/prelude.log 2008-06-27 19:20:13 UTC (rev 323) @@ -591,14 +591,14 @@ state 12: #0 #2 state 13: #1 #2 } end; -xs/*0:01*/![] = []; -xs/*0:01*/!(n/*0:101*/:ns/*0:11*/) = accum/*0*/ [] (n/*1:101*/:ns/*1:11*/) with accum ys/*0:01*/ [] = reverse ys/*0:01*/; accum ys/*0:01*/ (n/*0:101*/::int:ns/*0:11*/) = accum/*1*/ (xs/*2:01*/!n/*0:101*/:ys/*0:01*/) ns/*0:11*/ if n/*0:101*/>=0&&n/*0:101*/<m/*1:*/; accum ys/*0:01*/ (n/*0:101*/::int:ns/*0:11*/) = accum/*1*/ ys/*0:01*/ ns/*0:11*/; accum ys/*0:01*/ (n/*0:101*/:ns/*0:11*/) = accum/*1*/ (xs/*2:01*/!n/*0:101*/:ys/*0:01*/) ns/*0:11*/ if n/*0:101*/>=0&&n/*0:101*/<m/*1:*/; accum ys/*0:01*/ (n/*0:101*/:ns/*0:11*/) = accum/*1*/ ys/*0:01*/ ns/*0:11*/; accum ys/*0:01*/ ns/*0:1*/ = reverse ys/*0:01*/+xs/*2:01*/!ns/*0:1*/ { +xs/*0:01*/!![] = []; +xs/*0:01*/!!(n/*0:101*/:ns/*0:11*/) = accum/*0*/ [] (n/*1:101*/:ns/*1:11*/) with accum ys/*0:01*/ [] = reverse ys/*0:01*/; accum ys/*0:01*/ (n/*0:101*/::int:ns/*0:11*/) = accum/*1*/ (xs/*2:01*/!n/*0:101*/:ys/*0:01*/) ns/*0:11*/ if n/*0:101*/>=0&&n/*0:101*/<m/*1:*/; accum ys/*0:01*/ (n/*0:101*/::int:ns/*0:11*/) = accum/*1*/ ys/*0:01*/ ns/*0:11*/; accum ys/*0:01*/ (n/*0:101*/:ns/*0:11*/) = accum/*1*/ (xs/*2:01*/!n/*0:101*/:ys/*0:01*/) ns/*0:11*/ if n/*0:101*/>=0&&n/*0:101*/<m/*1:*/; accum ys/*0:01*/ (n/*0:101*/:ns/*0:11*/) = accum/*1*/ ys/*0:01*/ ns/*0:11*/; accum ys/*0:01*/ ns/*0:1*/ = reverse ys/*0:01*/+xs/*2:01*/!!ns/*0:1*/ { rule #0: accum ys [] = reverse ys rule #1: accum ys (n::int:ns) = accum (xs!n:ys) ns if n>=0&&n<m rule #2: accum ys (n::int:ns) = accum ys ns rule #3: accum ys (n:ns) = accum (xs!n:ys) ns if n>=0&&n<m rule #4: accum ys (n:ns) = accum ys ns - rule #5: accum ys ns = reverse ys+xs!ns + rule #5: accum ys ns = reverse ys+xs!!ns state 0: #0 #1 #2 #3 #4 #5 <var> state 1 state 1: #0 #1 #2 #3 #4 #5 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-27 20:05:22
|
Revision: 324 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=324&view=rev Author: agraef Date: 2008-06-27 13:05:31 -0700 (Fri, 27 Jun 2008) Log Message: ----------- Bugfixes in slicing operation. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/lib/prelude.pure pure/trunk/test/prelude.log Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-06-27 19:20:13 UTC (rev 323) +++ pure/trunk/ChangeLog 2008-06-27 20:05:31 UTC (rev 324) @@ -2,7 +2,9 @@ * lib/prelude.pure: Using xs!ns for slicing conflicts with more general indexing of containers with arbitrary keys. Use !! for - slicing instead. Reported by Jiri Spitz. + slicing instead, as suggested by Jiri Spitz. Also make slicing + fail if indices aren't machine ints, and throw a bad_list_value + exception if computing the size of the container fails. * runtime.cc/h: Added pure_current_interp(), variable and constant definitions, management of temporary definition levels. Modified: pure/trunk/lib/prelude.pure =================================================================== --- pure/trunk/lib/prelude.pure 2008-06-27 19:20:13 UTC (rev 323) +++ pure/trunk/lib/prelude.pure 2008-06-27 20:05:31 UTC (rev 324) @@ -187,18 +187,22 @@ /* 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 zero-based indices and thus, in particular, on the list and tuple - structures defined above. */ + with zero-based indices and a contiguous index range. This includes, in + particular, the list and tuple structures defined above. Note that this + definition requires that the indices be machine ints, otherwise the + operation will fail. Also, you'll get a 'bad_list_value' exception if we + can't determine the size of xs using the # operator. */ xs!![] = []; -xs!!(n:ns) = accum [] (n:ns) with +xs!!(n::int:ns) = accum [] (n:ns) with accum ys [] = reverse ys; accum ys (n::int:ns) = accum (xs!n:ys) ns if n>=0 && n<m; = accum ys ns otherwise; - accum ys (n:ns) = accum (xs!n:ys) ns if n>=0 && n<m; - = accum ys ns otherwise; + accum ys (n:ns) = reverse ys+xs!!(n:ns); accum ys ns = reverse ys+xs!!ns; -end when m::int = #xs end; +end when + m::int = case #xs of m::int = m; _ = throw (bad_list_value xs) end; +end; /* Arithmetic sequences. */ Modified: pure/trunk/test/prelude.log =================================================================== --- pure/trunk/test/prelude.log 2008-06-27 19:20:13 UTC (rev 323) +++ pure/trunk/test/prelude.log 2008-06-27 20:05:31 UTC (rev 324) @@ -592,46 +592,53 @@ state 13: #1 #2 } end; xs/*0:01*/!![] = []; -xs/*0:01*/!!(n/*0:101*/:ns/*0:11*/) = accum/*0*/ [] (n/*1:101*/:ns/*1:11*/) with accum ys/*0:01*/ [] = reverse ys/*0:01*/; accum ys/*0:01*/ (n/*0:101*/::int:ns/*0:11*/) = accum/*1*/ (xs/*2:01*/!n/*0:101*/:ys/*0:01*/) ns/*0:11*/ if n/*0:101*/>=0&&n/*0:101*/<m/*1:*/; accum ys/*0:01*/ (n/*0:101*/::int:ns/*0:11*/) = accum/*1*/ ys/*0:01*/ ns/*0:11*/; accum ys/*0:01*/ (n/*0:101*/:ns/*0:11*/) = accum/*1*/ (xs/*2:01*/!n/*0:101*/:ys/*0:01*/) ns/*0:11*/ if n/*0:101*/>=0&&n/*0:101*/<m/*1:*/; accum ys/*0:01*/ (n/*0:101*/:ns/*0:11*/) = accum/*1*/ ys/*0:01*/ ns/*0:11*/; accum ys/*0:01*/ ns/*0:1*/ = reverse ys/*0:01*/+xs/*2:01*/!!ns/*0:1*/ { +xs/*0:01*/!!(n/*0:101*/::int:ns/*0:11*/) = accum/*0*/ [] (n/*1:101*/:ns/*1:11*/) with accum ys/*0:01*/ [] = reverse ys/*0:01*/; accum ys/*0:01*/ (n/*0:101*/::int:ns/*0:11*/) = accum/*1*/ (xs/*2:01*/!n/*0:101*/:ys/*0:01*/) ns/*0:11*/ if n/*0:101*/>=0&&n/*0:101*/<m/*1:*/; accum ys/*0:01*/ (n/*0:101*/::int:ns/*0:11*/) = accum/*1*/ ys/*0:01*/ ns/*0:11*/; accum ys/*0:01*/ (n/*0:101*/:ns/*0:11*/) = reverse ys/*0:01*/+xs/*2:01*/!!(n/*0:101*/:ns/*0:11*/); accum ys/*0:01*/ ns/*0:1*/ = reverse ys/*0:01*/+xs/*2:01*/!!ns/*0:1*/ { rule #0: accum ys [] = reverse ys rule #1: accum ys (n::int:ns) = accum (xs!n:ys) ns if n>=0&&n<m rule #2: accum ys (n::int:ns) = accum ys ns - rule #3: accum ys (n:ns) = accum (xs!n:ys) ns if n>=0&&n<m - rule #4: accum ys (n:ns) = accum ys ns - rule #5: accum ys ns = reverse ys+xs!!ns - state 0: #0 #1 #2 #3 #4 #5 + rule #3: accum ys (n:ns) = reverse ys+xs!!(n:ns) + rule #4: accum ys ns = reverse ys+xs!!ns + state 0: #0 #1 #2 #3 #4 <var> state 1 - state 1: #0 #1 #2 #3 #4 #5 + state 1: #0 #1 #2 #3 #4 <var> state 2 [] state 3 <app> state 4 - state 2: #5 - state 3: #0 #5 - state 4: #1 #2 #3 #4 #5 + state 2: #4 + state 3: #0 #4 + state 4: #1 #2 #3 #4 <var> state 5 <app> state 7 - state 5: #5 + state 5: #4 <var> state 6 - state 6: #5 - state 7: #1 #2 #3 #4 #5 + state 6: #4 + state 7: #1 #2 #3 #4 <var> state 8 : state 11 - state 8: #5 + state 8: #4 <var> state 9 - state 9: #5 + state 9: #4 <var> state 10 - state 10: #5 - state 11: #1 #2 #3 #4 #5 + state 10: #4 + state 11: #1 #2 #3 #4 <var> state 12 <var>::int state 14 - state 12: #3 #4 #5 + state 12: #3 #4 <var> state 13 - state 13: #3 #4 #5 - state 14: #1 #2 #3 #4 #5 + state 13: #3 #4 + state 14: #1 #2 #3 #4 <var> state 15 - state 15: #1 #2 #3 #4 #5 -} end when m/*0:*/::int = #xs/*0:01*/ { - rule #0: m::int = #xs + state 15: #1 #2 #3 #4 +} end when m/*0:*/::int = case #xs/*0:01*/ of m/*0:*/::int = m/*0:*/; _/*0:*/ = throw (bad_list_value xs/*1:01*/) { + rule #0: m::int = m + rule #1: _ = throw (bad_list_value xs) + state 0: #0 #1 + <var> state 1 + <var>::int state 2 + state 1: #1 + state 2: #0 #1 +} end { + rule #0: m::int = case #xs of m::int = m; _ = throw (bad_list_value xs) end state 0: #0 <var>::int 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-06-27 22:53:42
|
Revision: 325 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=325&view=rev Author: agraef Date: 2008-06-27 15:53:51 -0700 (Fri, 27 Jun 2008) Log Message: ----------- Restrict definition of the slicing operation to lists and tuples, and simplify it by using a list comprehension. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/lib/prelude.pure pure/trunk/test/prelude.log Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-06-27 20:05:31 UTC (rev 324) +++ pure/trunk/ChangeLog 2008-06-27 22:53:51 UTC (rev 325) @@ -1,11 +1,13 @@ -2008-06-27 Albert Graef <Dr....@t-...> +2008-06-28 Albert Graef <Dr....@t-...> * lib/prelude.pure: Using xs!ns for slicing conflicts with more general indexing of containers with arbitrary keys. Use !! for - slicing instead, as suggested by Jiri Spitz. Also make slicing - fail if indices aren't machine ints, and throw a bad_list_value - exception if computing the size of the container fails. + slicing instead. Restrict the definition to lists and tuples, and + simplify it by using a list comprehension. Suggested by Jiri + Spitz. +2008-06-27 Albert Graef <Dr....@t-...> + * runtime.cc/h: Added pure_current_interp(), variable and constant definitions, management of temporary definition levels. Modified: pure/trunk/lib/prelude.pure =================================================================== --- pure/trunk/lib/prelude.pure 2008-06-27 20:05:31 UTC (rev 324) +++ pure/trunk/lib/prelude.pure 2008-06-27 22:53:51 UTC (rev 325) @@ -186,23 +186,11 @@ 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 zero-based indices and a contiguous index range. This includes, in - particular, the list and tuple structures defined above. Note that this - definition requires that the indices be machine ints, otherwise the - operation will fail. Also, you'll get a 'bad_list_value' exception if we - can't determine the size of xs using the # operator. */ + list ns which are in the range 0..#xs-1. xs must be a (proper) list or + tuple, and the indices must be machine ints. */ -xs!![] = []; -xs!!(n::int:ns) = accum [] (n:ns) with - accum ys [] = reverse ys; - accum ys (n::int:ns) = accum (xs!n:ys) ns if n>=0 && n<m; - = accum ys ns otherwise; - accum ys (n:ns) = reverse ys+xs!!(n:ns); - accum ys ns = reverse ys+xs!!ns; -end when - m::int = case #xs of m::int = m; _ = throw (bad_list_value xs) end; -end; +xs!!ns = [xs!n; n=ns; n>=0 && n<m] when m::int = #xs end + if listp xs || tuplep xs; /* Arithmetic sequences. */ Modified: pure/trunk/test/prelude.log =================================================================== --- pure/trunk/test/prelude.log 2008-06-27 20:05:31 UTC (rev 324) +++ pure/trunk/test/prelude.log 2008-06-27 22:53:51 UTC (rev 325) @@ -591,58 +591,17 @@ state 12: #0 #2 state 13: #1 #2 } end; -xs/*0:01*/!![] = []; -xs/*0:01*/!!(n/*0:101*/::int:ns/*0:11*/) = accum/*0*/ [] (n/*1:101*/:ns/*1:11*/) with accum ys/*0:01*/ [] = reverse ys/*0:01*/; accum ys/*0:01*/ (n/*0:101*/::int:ns/*0:11*/) = accum/*1*/ (xs/*2:01*/!n/*0:101*/:ys/*0:01*/) ns/*0:11*/ if n/*0:101*/>=0&&n/*0:101*/<m/*1:*/; accum ys/*0:01*/ (n/*0:101*/::int:ns/*0:11*/) = accum/*1*/ ys/*0:01*/ ns/*0:11*/; accum ys/*0:01*/ (n/*0:101*/:ns/*0:11*/) = reverse ys/*0:01*/+xs/*2:01*/!!(n/*0:101*/:ns/*0:11*/); accum ys/*0:01*/ ns/*0:1*/ = reverse ys/*0:01*/+xs/*2:01*/!!ns/*0:1*/ { - rule #0: accum ys [] = reverse ys - rule #1: accum ys (n::int:ns) = accum (xs!n:ys) ns if n>=0&&n<m - rule #2: accum ys (n::int:ns) = accum ys ns - rule #3: accum ys (n:ns) = reverse ys+xs!!(n:ns) - rule #4: accum ys ns = reverse ys+xs!!ns - state 0: #0 #1 #2 #3 #4 +xs/*0:01*/!!ns/*0:1*/ = catmap (\n/*0:*/ -> if n/*0:*/>=0&&n/*0:*/<m/*1:*/ then [xs/*2:01*/!n/*0:*/] else [] { + rule #0: n = if n>=0&&n<m then [xs!n] else [] + state 0: #0 <var> state 1 - state 1: #0 #1 #2 #3 #4 - <var> state 2 - [] state 3 - <app> state 4 - state 2: #4 - state 3: #0 #4 - state 4: #1 #2 #3 #4 - <var> state 5 - <app> state 7 - state 5: #4 - <var> state 6 - state 6: #4 - state 7: #1 #2 #3 #4 - <var> state 8 - : state 11 - state 8: #4 - <var> state 9 - state 9: #4 - <var> state 10 - state 10: #4 - state 11: #1 #2 #3 #4 - <var> state 12 - <var>::int state 14 - state 12: #3 #4 - <var> state 13 - state 13: #3 #4 - state 14: #1 #2 #3 #4 - <var> state 15 - state 15: #1 #2 #3 #4 -} end when m/*0:*/::int = case #xs/*0:01*/ of m/*0:*/::int = m/*0:*/; _/*0:*/ = throw (bad_list_value xs/*1:01*/) { - rule #0: m::int = m - rule #1: _ = throw (bad_list_value xs) - state 0: #0 #1 - <var> state 1 - <var>::int state 2 - state 1: #1 - state 2: #0 #1 -} end { - rule #0: m::int = case #xs of m::int = m; _ = throw (bad_list_value xs) end + state 1: #0 +}) ns/*1:1*/ when m/*0:*/::int = #xs/*0:01*/ { + rule #0: m::int = #xs state 0: #0 <var>::int state 1 state 1: #0 -} end; +} end if listp xs/*0:01*/||tuplep xs/*0:01*/; 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 state 0: #0 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-28 17:01:05
|
Revision: 327 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=327&view=rev Author: agraef Date: 2008-06-28 10:01:14 -0700 (Sat, 28 Jun 2008) Log Message: ----------- Bugfixes: Perform substitutions on the rhs of variable and constant definitions. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc pure/trunk/interpreter.hh Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-06-28 12:20:43 UTC (rev 326) +++ pure/trunk/ChangeLog 2008-06-28 17:01:14 UTC (rev 327) @@ -1,5 +1,8 @@ 2008-06-28 Albert Graef <Dr....@t-...> + * interpreter.cc: Promote type tags and substitute constants on + the rhs of variable and constant definitions. + * lib/prelude.pure: Using xs!ns for slicing conflicts with more general indexing of containers with arbitrary keys. Use !! for slicing instead. Restrict the definition to lists and tuples, and Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-06-28 12:20:43 UTC (rev 326) +++ pure/trunk/interpreter.cc 2008-06-28 17:01:14 UTC (rev 327) @@ -490,7 +490,7 @@ // Evaluate an expression. -pure_expr *interpreter::eval(expr x) +pure_expr *interpreter::eval(expr& x) { globals g; save_globals(g); @@ -500,14 +500,15 @@ return res; } -pure_expr *interpreter::eval(expr x, pure_expr*& e) +pure_expr *interpreter::eval(expr& x, pure_expr*& e) { globals g; save_globals(g); compile(); - // promote type tags: + // promote type tags and substitute constants: env vars; expr u = subst(vars, x); compile(u); + x = u; pure_expr *res = doeval(u, e); restore_globals(g); return res; @@ -515,7 +516,7 @@ // Define global variables. -pure_expr *interpreter::defn(expr pat, expr x) +pure_expr *interpreter::defn(expr pat, expr& x) { globals g; save_globals(g); @@ -525,13 +526,15 @@ return res; } -pure_expr *interpreter::defn(expr pat, expr x, pure_expr*& e) +pure_expr *interpreter::defn(expr pat, expr& x, pure_expr*& e) { globals g; save_globals(g); compile(); env vars; - expr lhs = bind(vars, pat), rhs = x; + // promote type tags and substitute constants: + expr rhs = subst(vars, x); + expr lhs = bind(vars, pat); build_env(vars, lhs); for (env::const_iterator it = vars.begin(); it != vars.end(); ++it) { int32_t f = it->first; @@ -550,6 +553,7 @@ } } compile(rhs); + x = rhs; pure_expr *res = dodefn(vars, lhs, rhs, e); if (!res) return 0; for (env::const_iterator it = vars.begin(); it != vars.end(); ++it) { @@ -564,7 +568,7 @@ // Define global constants (macro definitions). -pure_expr *interpreter::const_defn(expr pat, expr x) +pure_expr *interpreter::const_defn(expr pat, expr& x) { globals g; save_globals(g); @@ -617,13 +621,15 @@ return x; } -pure_expr *interpreter::const_defn(expr pat, expr x, pure_expr*& e) +pure_expr *interpreter::const_defn(expr pat, expr& x, pure_expr*& e) { globals g; save_globals(g); compile(); env vars; - expr lhs = bind(vars, pat), rhs = x; + // promote type tags and substitute constants: + expr rhs = subst(vars, x); + expr lhs = bind(vars, pat); build_env(vars, lhs); for (env::const_iterator it = vars.begin(); it != vars.end(); ++it) { int32_t f = it->first; @@ -645,6 +651,7 @@ } } compile(rhs); + x = rhs; pure_expr *res = doeval(rhs, e); if (!res) return 0; // convert the result back to a compile time expression Modified: pure/trunk/interpreter.hh =================================================================== --- pure/trunk/interpreter.hh 2008-06-28 12:20:43 UTC (rev 326) +++ pure/trunk/interpreter.hh 2008-06-28 17:01:14 UTC (rev 327) @@ -304,8 +304,8 @@ evaluation. In such a case, the variant with the extra e parameter returns the runtime expression thrown by the exception, if any. Both the result and the exception value (if any) are to be freed by the caller. */ - pure_expr *eval(expr x); - pure_expr *eval(expr x, pure_expr*& e); + pure_expr *eval(expr& x); + pure_expr *eval(expr& x, pure_expr*& e); /* Evaluate an expression and define global variables. This works like eval() above, but also binds the variables in pat to the corresponding @@ -315,8 +315,8 @@ matched. Returns a null pointer if an exception occurred during the evaluation or if the pattern failed to match. Both the result and the exception value (if any) are to be freed by the caller. */ - pure_expr *defn(expr pat, expr x); - pure_expr *defn(expr pat, expr x, pure_expr*& e); + pure_expr *defn(expr pat, expr& x); + pure_expr *defn(expr pat, expr& x, pure_expr*& e); /* Bind a global variable to a given value. This binds the given variable symbol directly to the given value, without matching and evaluating @@ -334,8 +334,8 @@ the left-hand side pattern as usual. Unlike variables, existing constant symbols cannot be redefined, so they have to be cleared before you can give them new values. */ - pure_expr *const_defn(expr pat, expr x); - pure_expr *const_defn(expr pat, expr x, pure_expr*& e); + pure_expr *const_defn(expr pat, expr& x); + pure_expr *const_defn(expr pat, expr& x, pure_expr*& e); /* Directly bind a given constant symbol to a given value. */ void const_defn(int32_t tag, pure_expr *x); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-28 17:40:38
|
Revision: 328 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=328&view=rev Author: agraef Date: 2008-06-28 10:40:47 -0700 (Sat, 28 Jun 2008) Log Message: ----------- Refactoring. Modified Paths: -------------- pure/trunk/lib/primitives.pure pure/trunk/test/prelude.log Modified: pure/trunk/lib/primitives.pure =================================================================== --- pure/trunk/lib/primitives.pure 2008-06-28 17:01:14 UTC (rev 327) +++ pure/trunk/lib/primitives.pure 2008-06-28 17:40:47 UTC (rev 328) @@ -75,24 +75,24 @@ expr* pure_bigintval(expr*), expr* pure_pointerval(expr*); int x::int = x; -int x::bigint = pure_intval x; -int x::double = pure_intval x; +int x::bigint | +int x::double | int x::pointer = pure_intval x; -bigint x::int = pure_bigintval x; bigint x::bigint = x; -bigint x::double = pure_bigintval x; +bigint x::int | +bigint x::double | bigint x::pointer = pure_bigintval x; -double x::int = pure_dblval x; +double x::double = x; +double x::int | double x::bigint = pure_dblval x; -double x::double = x; -pointer x::int = pure_pointerval x; -pointer x::bigint = pure_pointerval x; -pointer x::double = pure_pointerval x; +pointer x::pointer = x; +pointer x::int | +pointer x::bigint | +pointer x::double | pointer x::string = pure_pointerval x; -pointer x::pointer = x; /* Basic int and double arithmetic. The Pure compiler already knows how to handle these, we just need to supply rules with the right type tags. */ @@ -272,7 +272,7 @@ extern double sqrt(double) = c_sqrt; -sqrt x::int = c_sqrt (double x) if x>=0; +sqrt x::int | sqrt x::bigint = c_sqrt (double x) if x>=0; sqrt x::double = c_sqrt x if x>=0; @@ -291,22 +291,22 @@ pow x::bigint y::int = bigint_pow x y if y>=0; // mixed double/int/bigint -pow x::double y::int = c_pow x (double y); +pow x::double y::int | pow x::double y::bigint = c_pow x (double y); -pow x::int y::double = c_pow (double x) y if x>=0 || int y==y; +pow x::int y::double | pow x::bigint y::double = c_pow (double x) y if x>=0 || int y==y; /* The ^ operator. Works like pow, but always promotes its operands to double and returns a double result. */ x::double^y::double = c_pow x y if x>=0 || int y==y; -x::int^y::int = c_pow (double x) (double y); -x::bigint^y::bigint = c_pow (double x) (double y); -x::int^y::bigint = c_pow (double x) (double y); +x::int^y::int | +x::bigint^y::bigint | +x::int^y::bigint | x::bigint^y::int = c_pow (double x) (double y); -x::double^y::int = c_pow x (double y); +x::double^y::int | x::double^y::bigint = c_pow x (double y); -x::int^y::double = c_pow (double x) y if x>=0 || int y==y; +x::int^y::double | x::bigint^y::double = c_pow (double x) y if x>=0 || int y==y; /* Pointer arithmetic. We do this using bigints, so that the code is portable Modified: pure/trunk/test/prelude.log =================================================================== --- pure/trunk/test/prelude.log 2008-06-28 17:01:14 UTC (rev 327) +++ pure/trunk/test/prelude.log 2008-06-28 17:40:47 UTC (rev 328) @@ -60,18 +60,18 @@ int x/*0:1*/::bigint = pure_intval x/*0:1*/; int x/*0:1*/::double = pure_intval x/*0:1*/; int x/*0:1*/ = pure_intval x/*0:1*/; +bigint x/*0:1*/::bigint = x/*0:1*/; bigint x/*0:1*/::int = pure_bigintval x/*0:1*/; -bigint x/*0:1*/::bigint = x/*0:1*/; bigint x/*0:1*/::double = pure_bigintval x/*0:1*/; bigint x/*0:1*/ = pure_bigintval x/*0:1*/; +double x/*0:1*/::double = x/*0:1*/; double x/*0:1*/::int = pure_dblval x/*0:1*/; double x/*0:1*/::bigint = pure_dblval x/*0:1*/; -double x/*0:1*/::double = x/*0:1*/; +pointer x/*0:1*/ = x/*0:1*/; pointer x/*0:1*/::int = pure_pointerval x/*0:1*/; pointer x/*0:1*/::bigint = pure_pointerval x/*0:1*/; pointer x/*0:1*/::double = pure_pointerval x/*0:1*/; pointer x/*0:1*/::string = pure_pointerval x/*0:1*/; -pointer x/*0:1*/ = x/*0:1*/; -x/*0:1*/::int = -x/*0:1*/; ~x/*0:1*/::int = ~x/*0:1*/; not x/*0:1*/::int = not x/*0:1*/; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-06-30 20:00:46
|
Revision: 345 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=345&view=rev Author: agraef Date: 2008-06-30 13:00:55 -0700 (Mon, 30 Jun 2008) Log Message: ----------- Fix a segfault in external wrapper routines. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-06-30 19:08:19 UTC (rev 344) +++ pure/trunk/ChangeLog 2008-06-30 20:00:55 UTC (rev 345) @@ -1,3 +1,9 @@ +2008-06-30 Albert Graef <Dr....@t-...> + + * interpreter.cc (declare_extern): Fix a segfault in external + wrapper routines, due to the shadow stack not being popped when + an external fails and thus the default rule gets used. + 2008-06-29 Albert Graef <Dr....@t-...> * etc/pure.xml: Improved syntax highlighting for Kate. Fixed up Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-06-30 19:08:19 UTC (rev 344) +++ pure/trunk/interpreter.cc 2008-06-30 20:00:55 UTC (rev 345) @@ -2903,10 +2903,19 @@ vector<Value*> myargs(2); for (size_t i = 0; i < n; ++i) { myargs[0] = b.CreateCall(module->getFunction("pure_new"), defaultv); - myargs[1] = args[i]; + myargs[1] = b.CreateCall(module->getFunction("pure_new"), args[i]); defaultv = b.CreateCall(module->getFunction("pure_apply"), myargs.begin(), myargs.end()); } + if (n > 0) { + vector<Value*> freeargs(3); + freeargs[0] = defaultv; + freeargs[1] = UInt(n); + freeargs[2] = Zero; + b.CreateCall(module->getFunction("pure_pop_args"), + freeargs.begin(), freeargs.end()); + b.CreateCall(module->getFunction("pure_unref"), defaultv); + } b.CreateRet(defaultv); verifyFunction(*f); if (FPM) FPM->run(*f); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-07-01 21:05:44
|
Revision: 356 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=356&view=rev Author: agraef Date: 2008-07-01 14:04:46 -0700 (Tue, 01 Jul 2008) Log Message: ----------- 'list' command now also prints fixity and nullary declarations of listed symbols. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/lexer.ll Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-07-01 14:50:04 UTC (rev 355) +++ pure/trunk/ChangeLog 2008-07-01 21:04:46 UTC (rev 356) @@ -1,5 +1,8 @@ 2008-07-01 Albert Graef <Dr....@t-...> + * lexer.ll: 'list' command now also prints fixity and nullary + declarations of listed symbols. + * lib/math.pure: Added various bits and pieces, most notably the complex numbers. Also moved sqrt function from primitives.pure to math.pure. Modified: pure/trunk/lexer.ll =================================================================== --- pure/trunk/lexer.ll 2008-07-01 14:50:04 UTC (rev 355) +++ pure/trunk/lexer.ll 2008-07-01 21:04:46 UTC (rev 356) @@ -505,6 +505,25 @@ sout << "def " << sym.s << " = " << *jt->second.cval << ";\n"; } else { + if (sym.fix == nullary) + sout << "nullary " << sym.s << ";\n"; + else if (sym.prec < 10) { + switch (sym.fix) { + case infix: + sout << "infix"; break; + case infixl: + sout << "infixl"; break; + case infixr: + sout << "infixr"; break; + case prefix: + sout << "prefix"; break; + case postfix: + sout << "postfix"; break; + case nullary: + assert(0 && "this can't happen"); break; + } + sout << " " << (int)sym.prec << " " << sym.s << ";\n"; + } if (xt != interp.externals.end()) { const ExternInfo& info = xt->second; sout << info << ";"; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-07-01 21:53:01
|
Revision: 357 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=357&view=rev Author: agraef Date: 2008-07-01 14:53:10 -0700 (Tue, 01 Jul 2008) Log Message: ----------- Add GMP gcd and lcm functions. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/lib/primitives.pure pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-07-01 21:04:46 UTC (rev 356) +++ pure/trunk/ChangeLog 2008-07-01 21:53:10 UTC (rev 357) @@ -1,5 +1,8 @@ 2008-07-01 Albert Graef <Dr....@t-...> + * lib/primitives.pure, runtime.cc/h: Add the GMP gcd and lcm + functions. + * lexer.ll: 'list' command now also prints fixity and nullary declarations of listed symbols. Modified: pure/trunk/lib/primitives.pure =================================================================== --- pure/trunk/lib/primitives.pure 2008-07-01 21:04:46 UTC (rev 356) +++ pure/trunk/lib/primitives.pure 2008-07-01 21:53:10 UTC (rev 357) @@ -267,6 +267,23 @@ x::double==y::bigint = x==double y; x::double!=y::bigint = x!=double y; +/* The gcd and lcm functions from the GMP library. These return a bigint if at + least one of the arguments is a bigint, a machine int otherwise. */ + +extern expr* bigint_gcd(void*, void*); +extern expr* bigint_lcm(void*, void*); + +gcd x::bigint y::bigint = bigint_gcd x y; +lcm x::bigint y::bigint = bigint_lcm x y; + +gcd x::int y::bigint = bigint_gcd (bigint x) y; +gcd x::bigint y::int = bigint_gcd x (bigint y); +gcd x::int y::int = int (bigint_gcd (bigint x) (bigint y)); + +lcm x::int y::bigint = bigint_lcm (bigint x) y; +lcm x::bigint y::int = bigint_lcm x (bigint y); +lcm x::int y::int = int (bigint_lcm (bigint x) (bigint y)); + /* The pow function. Returns a bigint for integer arguments, double if one of the arguments is double (in the latter case, x may be negative only if y is integer). */ Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-07-01 21:04:46 UTC (rev 356) +++ pure/trunk/runtime.cc 2008-07-01 21:53:10 UTC (rev 357) @@ -1894,6 +1894,24 @@ } extern "C" +pure_expr *bigint_gcd(mpz_t x, mpz_t y) +{ + pure_expr *u = pure_bigint(0, 0); + mpz_t& z = u->data.z; + mpz_gcd(z, x, y); + return u; +} + +extern "C" +pure_expr *bigint_lcm(mpz_t x, mpz_t y) +{ + pure_expr *u = pure_bigint(0, 0); + mpz_t& z = u->data.z; + mpz_lcm(z, x, y); + return u; +} + +extern "C" int32_t bigint_cmp(mpz_t x, mpz_t y) { return mpz_cmp(x, y); Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-07-01 21:04:46 UTC (rev 356) +++ pure/trunk/runtime.h 2008-07-01 21:53:10 UTC (rev 357) @@ -443,6 +443,9 @@ pure_expr *bigint_and(mpz_t x, mpz_t y); pure_expr *bigint_or(mpz_t x, mpz_t y); +pure_expr *bigint_gcd(mpz_t x, mpz_t y); +pure_expr *bigint_lcm(mpz_t x, mpz_t y); + int32_t bigint_cmp(mpz_t x, mpz_t y); /* String operations. In difference to the string operations from the C This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-07-02 01:05:02
|
Revision: 360 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=360&view=rev Author: agraef Date: 2008-07-01 18:05:10 -0700 (Tue, 01 Jul 2008) Log Message: ----------- Add rational numbers. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/lib/math.pure Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-07-01 22:01:15 UTC (rev 359) +++ pure/trunk/ChangeLog 2008-07-02 01:05:10 UTC (rev 360) @@ -1,3 +1,7 @@ +2008-07-02 Albert Graef <Dr....@t-...> + + * lib/math.pure: Added rational numbers. + 2008-07-01 Albert Graef <Dr....@t-...> * lib/primitives.pure, runtime.cc/h: Add the GMP gcd and lcm Modified: pure/trunk/lib/math.pure =================================================================== --- pure/trunk/lib/math.pure 2008-07-01 22:01:15 UTC (rev 359) +++ pure/trunk/lib/math.pure 2008-07-02 01:05:10 UTC (rev 360) @@ -1,5 +1,5 @@ -/* Pure math routines. Also defines the complex numbers. */ +/* Pure math routines. Also defines complex and rational numbers. */ /* Copyright (c) 2008 by Albert Graef <Dr....@t-...>. @@ -370,13 +370,189 @@ z1@(r1<:t1)!=x2 = z1 != (x2<:0); x1!=z2@(r2<:t2) = (x1<:0) != z2; +/* Rational numbers. These are constructed with the exact division operator + '%' which has the same precedence and fixity as the other division + operators declared in the prelude. */ + +infixl 7 % ; + +/* The '%' operator returns a rational or complex rational for any combination + of integer, rational and complex integer/rational arguments, provided that + the denominator is nonzero (otherwise it returns a floating point nan or + infinity, depending on the numerator). Machine int operands are always + promoted to bigints. For other numeric operands '%' works just like + '/'. Rational results are normalized so that the sign is always in the + numerator and numerator and denominator are relatively prime. Hence a + rational zero is always represented as 1L%0L. */ + +x::bigint % 0L = x/0; +x::bigint % y::bigint = (-x)%(-y) if y<0; + = (x div d) % (y div d) when d = gcd x y end + if gcd x y > 1; + +// int/bigint operands +x::int % y::bigint = bigint x % y; +x::bigint % y::int = x % bigint y; +x::int % y::int = bigint x % bigint y; + +// rational operands +(x1%y1)%(x2%y2) = (x1*y2)%(y1*x2); +(x1%y1)%x2 = x1%(y1*x2); +x1%(x2%y2) = (x1*y2)%x2; + +// complex operands (these must both use the same representation, otherwise +// the result won't be exact) +z1@(_+:_)%z2@(_<:_) | +z1@(_<:_)%z2@(_+:_) = z1/z2; +(x1+:y1)%(x2+:y2) = (x1*x2+y1*y2)%d +: (y1*x2-x1*y2)%d + when d = x2*x2+y2*y2 end; +(x1+:y1)%x2 = (x1*x2)%d +: (y1*x2)%d when d = x2*x2 end; +x1%(x2+:y2) = (x1*x2)%d +: (-x1*y2)%d when d = x2*x2+y2*y2 end; +(r1<:t1)%(r2<:t2) = r1%r2 <: t1-t2; +(r1<:t1)%x2 = r1%x2 <: t1; +x1%(r2<:t2) = x1%r2 <: -t2; + +// fall back to ordinary inexact division in all other cases +x::double%y | +x%y::double = x/y; + +/* Conversions. */ + +rational x@(_%_) = x; +rational x::int | +rational x::bigint = x%1; + +// TODO: Need to rationalize doubles here. Currently this is a no-op. +rational x::double = x; + +rational (x+:y) = rational x +: rational y; +rational (x<:y) = rational x <: rational y; + +int x@(_%_) = int (bigint x); +bigint x@(_%_) = trunc x; +double (x%y) = x/y; + +complex (x%y) = x%y +: 0L%1L; +rect (x%y) = x%y +: 0L%1L; +polar (x%y) = x%y <: 0L%1L; + +/* Note that these normalization rules will yield inexact results when + triggered. Thus you have to take care that your polar representations stay + normalized if you want to do computations with exact complex rationals in + polar notation. */ +r@(_%_)<:t = -r <: t+pi if r<0; +r<:t@(_%_) = r <: atan2 (sin t) (cos t) if t<-pi || t>pi; + = r <: pi if t==-pi; + +/* Numerator and denominator. */ + +num (x%y) = x; +den (x%y) = y; + +/* Absolute value and sign. */ + +abs (x%y) = abs x % y; +sgn (x%y) = sgn x; + +/* Rounding functions. These return exact results here. */ + +floor x@(_%_) = if n<=x then n else n-1 when n::bigint = trunc x end; +ceil x@(_%_) = -floor (-x); +trunc (x%y) = x div y; +frac x@(_%_) = x-trunc x; + +/* The pow function. Returns exact results for integer exponents. */ + +pow (x%y) n::int | +pow (x%y) n::bigint = pow x n % pow y n if n>0; + = pow y (-n) % pow x (-n) if n<0; + = 1L%1L otherwise; +pow (x%y) n::double = pow (x/y) n; +pow (x%y) (n%m) = pow (x/y) (n/m); + +/* Fallback rules for other functions (inexact results). */ + +sqrt (x%y) = sqrt (x/y); + +exp (x%y) = exp (x/y); +ln (x%y) = ln (x/y); +log (x%y) = log (x/y); + +sin (x%y) = sin (x/y); +cos (x%y) = cos (x/y); +tan (x%y) = tan (x/y); +asin (x%y) = asin (x/y); +acos (x%y) = acos (x/y); +atan (x%y) = atan (x/y); + +atan2 (x%y) z = atan2 (x/y) z; +atan2 x (y%z) = atan2 x (y/z); + +sinh (x%y) = sinh (x/y); +cosh (x%y) = cosh (x/y); +tanh (x%y) = tanh (x/y); +asinh (x%y) = asinh (x/y); +acosh (x%y) = acosh (x/y); +atanh (x%y) = atanh (x/y); + +/* Rational arithmetic. */ + +-(x%y) = (-x)%y; + +(x1%y1)+(x2%y2) = (x1*y2+x2*y1) % (y1*y2); +(x1%y1)-(x2%y2) = (x1*y2-x2*y1) % (y1*y2); +(x1%y1)*(x2%y2) = (x1*x2) % (y1*y2); + +(x1%y1)+x2 = (x1+x2*y1) % y1; +(x1%y1)-x2 = (x1-x2*y1) % y1; +(x1%y1)*x2 = (x1*x2) % y1; + +x1+(x2%y2) = (x1*y2+x2) % y2; +x1-(x2%y2) = (x1*y2-x2) % y2; +x1*(x2%y2) = (x1*x2) % y2; + +/* / and ^ yield inexact results. */ + +(x1%y1)/(x2%y2) = (x1*y2) / (y1*x2); +(x1%y1)^(x2%y2) = (x1/y1) ^ (x2/y2); + +(x1%y1)/x2 = x1 / (y1*x2); +(x1%y1)^x2 = (x1/y1) ^ x2; + +x1/(x2%y2) = (x1*y2) / x2; +x1^(x2%y2) = x1 ^ (x2/y2); + +/* Comparisons. */ + +x1%y1 == x2%y2 = x1*y2 == x2*y1; +x1%y1 != x2%y2 = x1*y2 != x2*y1; +x1%y1 < x2%y2 = x1*y2 < x2*y1; +x1%y1 <= x2%y2 = x1*y2 <= x2*y1; +x1%y1 > x2%y2 = x1*y2 > x2*y1; +x1%y1 >= x2%y2 = x1*y2 >= x2*y1; + +x1%y1 == x2 = x1 == x2*y1; +x1%y1 != x2 = x1 != x2*y1; +x1%y1 < x2 = x1 < x2*y1; +x1%y1 <= x2 = x1 <= x2*y1; +x1%y1 > x2 = x1 > x2*y1; +x1%y1 >= x2 = x1 >= x2*y1; + +x1 == x2%y2 = x1*y2 == x2; +x1 != x2%y2 = x1*y2 != x2; +x1 < x2%y2 = x1*y2 < x2; +x1 <= x2%y2 = x1*y2 <= x2; +x1 > x2%y2 = x1*y2 > x2; +x1 >= x2%y2 = x1*y2 >= x2; + /* Additional number predicates. */ -realp x = intp x || bigintp x || doublep x; complexp x = case x of x+:y | x<:y = realp x && realp y; _ = 0 end; +rationalp x = case x of x%y = bigintp x && bigintp y; _ = 0 end; +realp x = intp x || bigintp x || doublep x || rationalp x; nump x = realp x || complexp x; -exactp x = intp x || bigintp x || +exactp x = intp x || bigintp x || rationalp || complexp x && exactp (re x) && exactp (im x) if nump x; infp x::double = not nanp x && nanp (x-x); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-07-02 01:13:30
|
Revision: 362 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=362&view=rev Author: agraef Date: 2008-07-01 18:13:39 -0700 (Tue, 01 Jul 2008) Log Message: ----------- Fix up list equality test. Reported by Jiri Spitz. Modified Paths: -------------- pure/trunk/lib/prelude.pure pure/trunk/test/prelude.log Modified: pure/trunk/lib/prelude.pure =================================================================== --- pure/trunk/lib/prelude.pure 2008-07-02 01:06:03 UTC (rev 361) +++ pure/trunk/lib/prelude.pure 2008-07-02 01:13:39 UTC (rev 362) @@ -140,7 +140,7 @@ []==[] = 1; (x:xs)==[] = 0; []==(x:xs) = 0; -(x:xs)==(y:ys) = if x==y then xs==ys else 1; +(x:xs)==(y:ys) = if x==y then xs==ys else 0; []!=[] = 0; (x:xs)!=[] = 1; Modified: pure/trunk/test/prelude.log =================================================================== --- pure/trunk/test/prelude.log 2008-07-02 01:06:03 UTC (rev 361) +++ pure/trunk/test/prelude.log 2008-07-02 01:13:39 UTC (rev 362) @@ -440,7 +440,7 @@ []==[] = 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*/ = if x/*0:0101*/==y/*0:101*/ then xs/*0:011*/==ys/*0:11*/ else 1; +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; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-07-02 20:46:18
|
Revision: 370 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=370&view=rev Author: agraef Date: 2008-07-02 13:46:27 -0700 (Wed, 02 Jul 2008) Log Message: ----------- Add double->rational conversion. Modified Paths: -------------- pure/trunk/lib/math.pure pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/lib/math.pure =================================================================== --- pure/trunk/lib/math.pure 2008-07-02 19:26:25 UTC (rev 369) +++ pure/trunk/lib/math.pure 2008-07-02 20:46:27 UTC (rev 370) @@ -418,12 +418,16 @@ /* Conversions. */ +extern expr* pure_rational(double); + rational x@(_%_) = x; rational x::int | rational x::bigint = x%1; -// TODO: Need to rationalize doubles here. Currently this is a no-op. -rational x::double = x; +/* The conversion from double doesn't do any rounding, so it is guaranteed + that converting the resulting rational back to double reconstructs the + original value. */ +rational x::double = n%d when n,d = pure_rational x end; rational (x+:y) = rational x +: rational y; rational (x<:y) = rational x <: rational y; Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-07-02 19:26:25 UTC (rev 369) +++ pure/trunk/runtime.cc 2008-07-02 20:46:27 UTC (rev 370) @@ -1786,6 +1786,22 @@ } extern "C" +pure_expr *pure_rational(double d) +{ + pure_expr *u = pure_bigint(0, 0); + pure_expr *v = pure_bigint(0, 0); + mpz_t& x = u->data.z; + mpz_t& y = v->data.z; + mpq_t q; + mpq_init(q); + mpq_set_d(q, d); + mpq_get_num(x, q); + mpq_get_den(y, q); + mpq_clear(q); + return pure_tuplel(2, u, v); +} + +extern "C" pure_expr *bigint_neg(mpz_t x) { pure_expr *u = pure_bigint(0, 0); Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-07-02 19:26:25 UTC (rev 369) +++ pure/trunk/runtime.h 2008-07-02 20:46:27 UTC (rev 370) @@ -415,6 +415,11 @@ pure_expr *pure_bigintval(pure_expr *x); pure_expr *pure_pointerval(pure_expr *x); +/* Convert a double to a rational number, without rounding. Returns a pair n,d + of two bigint values, where n is the numerator and d the denominator. */ + +pure_expr *pure_rational(double d); + /* Construct a "byte string" from a string. The result is a raw pointer object pointing to the converted string. The original string is copied (and, in the case of pure_byte_cstring, converted to the system encoding). The This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-07-03 00:19:38
|
Revision: 374 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=374&view=rev Author: agraef Date: 2008-07-02 17:19:47 -0700 (Wed, 02 Jul 2008) Log Message: ----------- Temporarily suppress verbose output for using clause. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc pure/trunk/test/prelude.log pure/trunk/test/test011.log pure/trunk/test/test014.log Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-07-02 23:31:57 UTC (rev 373) +++ pure/trunk/ChangeLog 2008-07-03 00:19:47 UTC (rev 374) @@ -1,3 +1,9 @@ +2008-07-03 Albert Graef <Dr....@t-...> + + * interpreter.cc (run): Temporarily suppress verbose output for + using clause. This also makes the some of the test logs much + smaller. Reported by Jiri Spitz. + 2008-07-02 Albert Graef <Dr....@t-...> * lib/math.pure: Added rational numbers. Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-07-02 23:31:57 UTC (rev 373) +++ pure/trunk/interpreter.cc 2008-07-03 00:19:47 UTC (rev 374) @@ -441,8 +441,14 @@ pure_expr* interpreter::run(const list<string> &sl, bool check) { + uint8_t s_verbose = verbose; + // Temporarily suppress verbose output for using clause. + compile(); + verbose = 0; for (list<string>::const_iterator s = sl.begin(); s != sl.end(); s++) run(*s, check); + compile(); + verbose = s_verbose; return result; } Modified: pure/trunk/test/prelude.log =================================================================== --- pure/trunk/test/prelude.log 2008-07-02 23:31:57 UTC (rev 373) +++ pure/trunk/test/prelude.log 2008-07-03 00:19:47 UTC (rev 374) @@ -1,355 +1,5 @@ def false = 0; def true = 1; -throw x/*0:1*/ = pure_throw x/*0:1*/; -assert p/*0:01*/ e/*0:1*/ = if p/*0:01*/ then 1 else throw e/*0:1*/; -x/*0:01*/===y/*0:1*/ = same x/*0:01*/ y/*0:1*/; -x/*0:01*/!==y/*0:1*/ = not same x/*0:01*/ y/*0:1*/; -intp x/*0:1*/ = case x/*0:1*/ of _/*0:*/::int = 1; _/*0:*/ = 0 { - rule #0: _::int = 1 - rule #1: _ = 0 - state 0: #0 #1 - <var> state 1 - <var>::int state 2 - state 1: #1 - state 2: #0 #1 -} end; -bigintp x/*0:1*/ = case x/*0:1*/ of _/*0:*/::bigint = 1; _/*0:*/ = 0 { - rule #0: _::bigint = 1 - rule #1: _ = 0 - state 0: #0 #1 - <var> state 1 - <var>::bigint state 2 - state 1: #1 - state 2: #0 #1 -} end; -doublep x/*0:1*/ = case x/*0:1*/ of _/*0:*/::double = 1; _/*0:*/ = 0 { - rule #0: _::double = 1 - rule #1: _ = 0 - state 0: #0 #1 - <var> state 1 - <var>::double state 2 - state 1: #1 - state 2: #0 #1 -} end; -stringp x/*0:1*/ = case x/*0:1*/ of _/*0:*/::string = 1; _/*0:*/ = 0 { - rule #0: _::string = 1 - rule #1: _ = 0 - state 0: #0 #1 - <var> state 1 - <var>::string state 2 - state 1: #1 - state 2: #0 #1 -} end; -pointerp x/*0:1*/ = case x/*0:1*/ of _/*0:*/ = 1; _/*0:*/ = 0 { - rule #0: _ = 1 - rule #1: _ = 0 - state 0: #0 #1 - <var> state 1 - <var> state 2 - state 1: #1 - state 2: #0 #1 -} end; -listp [] = 1; -listp (x/*0:101*/:xs/*0:11*/) = listp xs/*0:11*/; -listp _/*0:1*/ = 0; -listnp [] = 1; -listnp (x/*0:101*/:xs/*0:11*/) = 1; -listnp _/*0:1*/ = 0; -tuplep () = 1; -tuplep (x/*0:101*/,xs/*0:11*/) = 1; -tuplep _/*0:1*/ = 0; -int x/*0:1*/::int = x/*0:1*/; -int x/*0:1*/::bigint = pure_intval x/*0:1*/; -int x/*0:1*/::double = pure_intval x/*0:1*/; -int x/*0:1*/ = pure_intval x/*0:1*/; -bigint x/*0:1*/::bigint = x/*0:1*/; -bigint x/*0:1*/::int = pure_bigintval x/*0:1*/; -bigint x/*0:1*/::double = pure_bigintval x/*0:1*/; -bigint x/*0:1*/ = pure_bigintval x/*0:1*/; -double x/*0:1*/::double = x/*0:1*/; -double x/*0:1*/::int = pure_dblval x/*0:1*/; -double x/*0:1*/::bigint = pure_dblval x/*0:1*/; -pointer x/*0:1*/ = x/*0:1*/; -pointer x/*0:1*/::int = pure_pointerval x/*0:1*/; -pointer x/*0:1*/::bigint = pure_pointerval x/*0:1*/; -pointer x/*0:1*/::double = pure_pointerval x/*0:1*/; -pointer x/*0:1*/::string = pure_pointerval x/*0:1*/; --x/*0:1*/::int = -x/*0:1*/; -~x/*0:1*/::int = ~x/*0:1*/; -not x/*0:1*/::int = not x/*0:1*/; -x/*0:01*/::int<<y/*0:1*/::int = x/*0:01*/<<y/*0:1*/; -x/*0:01*/::int>>y/*0:1*/::int = x/*0:01*/>>y/*0:1*/; -x/*0:01*/::int+y/*0:1*/::int = x/*0:01*/+y/*0:1*/; -x/*0:01*/::int-y/*0:1*/::int = x/*0:01*/-y/*0:1*/; -x/*0:01*/::int*y/*0:1*/::int = x/*0:01*/*y/*0:1*/; -x/*0:01*/::int/y/*0:1*/::int = x/*0:01*//y/*0:1*/; -x/*0:01*/::int div y/*0:1*/::int = x/*0:01*/ div y/*0:1*/; -x/*0:01*/::int mod y/*0:1*/::int = x/*0:01*/ mod y/*0:1*/; -x/*0:01*/::int or y/*0:1*/::int = x/*0:01*/ or y/*0:1*/; -x/*0:01*/::int and y/*0:1*/::int = x/*0:01*/ and y/*0:1*/; -x/*0:01*/::int<y/*0:1*/::int = x/*0:01*/<y/*0:1*/; -x/*0:01*/::int>y/*0:1*/::int = x/*0:01*/>y/*0:1*/; -x/*0:01*/::int<=y/*0:1*/::int = x/*0:01*/<=y/*0:1*/; -x/*0:01*/::int>=y/*0:1*/::int = x/*0:01*/>=y/*0:1*/; -x/*0:01*/::int==y/*0:1*/::int = x/*0:01*/==y/*0:1*/; -x/*0:01*/::int!=y/*0:1*/::int = x/*0:01*/!=y/*0:1*/; --x/*0:1*/::double = -x/*0:1*/; -x/*0:01*/::double+y/*0:1*/::double = x/*0:01*/+y/*0:1*/; -x/*0:01*/::double-y/*0:1*/::double = x/*0:01*/-y/*0:1*/; -x/*0:01*/::double*y/*0:1*/::double = x/*0:01*/*y/*0:1*/; -x/*0:01*/::double/y/*0:1*/::double = x/*0:01*//y/*0:1*/; -x/*0:01*/::double<y/*0:1*/::double = x/*0:01*/<y/*0:1*/; -x/*0:01*/::double>y/*0:1*/::double = x/*0:01*/>y/*0:1*/; -x/*0:01*/::double<=y/*0:1*/::double = x/*0:01*/<=y/*0:1*/; -x/*0:01*/::double>=y/*0:1*/::double = x/*0:01*/>=y/*0:1*/; -x/*0:01*/::double==y/*0:1*/::double = x/*0:01*/==y/*0:1*/; -x/*0:01*/::double!=y/*0:1*/::double = x/*0:01*/!=y/*0:1*/; -x/*0:01*/::int+y/*0:1*/::double = x/*0:01*/+y/*0:1*/; -x/*0:01*/::int-y/*0:1*/::double = x/*0:01*/-y/*0:1*/; -x/*0:01*/::int*y/*0:1*/::double = x/*0:01*/*y/*0:1*/; -x/*0:01*/::int/y/*0:1*/::double = x/*0:01*//y/*0:1*/; -x/*0:01*/::int<y/*0:1*/::double = x/*0:01*/<y/*0:1*/; -x/*0:01*/::int>y/*0:1*/::double = x/*0:01*/>y/*0:1*/; -x/*0:01*/::int<=y/*0:1*/::double = x/*0:01*/<=y/*0:1*/; -x/*0:01*/::int>=y/*0:1*/::double = x/*0:01*/>=y/*0:1*/; -x/*0:01*/::int==y/*0:1*/::double = x/*0:01*/==y/*0:1*/; -x/*0:01*/::int!=y/*0:1*/::double = x/*0:01*/!=y/*0:1*/; -x/*0:01*/::double+y/*0:1*/::int = x/*0:01*/+y/*0:1*/; -x/*0:01*/::double-y/*0:1*/::int = x/*0:01*/-y/*0:1*/; -x/*0:01*/::double*y/*0:1*/::int = x/*0:01*/*y/*0:1*/; -x/*0:01*/::double/y/*0:1*/::int = x/*0:01*//y/*0:1*/; -x/*0:01*/::double<y/*0:1*/::int = x/*0:01*/<y/*0:1*/; -x/*0:01*/::double>y/*0:1*/::int = x/*0:01*/>y/*0:1*/; -x/*0:01*/::double<=y/*0:1*/::int = x/*0:01*/<=y/*0:1*/; -x/*0:01*/::double>=y/*0:1*/::int = x/*0:01*/>=y/*0:1*/; -x/*0:01*/::double==y/*0:1*/::int = x/*0:01*/==y/*0:1*/; -x/*0:01*/::double!=y/*0:1*/::int = x/*0:01*/!=y/*0:1*/; -x/*0:01*/::int&&y/*0:1*/::int = x/*0:01*/&&y/*0:1*/; -x/*0:01*/::int||y/*0:1*/::int = x/*0:01*/||y/*0:1*/; --x/*0:1*/::bigint = bigint_neg x/*0:1*/; -~x/*0:1*/::bigint = bigint_not x/*0:1*/; -not x/*0:1*/::bigint = not int x/*0:1*/; -x/*0:01*/::bigint<<y/*0:1*/::int = bigint_shl x/*0:01*/ y/*0:1*/ if y/*0:1*/>=0; -x/*0:01*/::bigint<<y/*0:1*/::int = bigint_shr x/*0:01*/ (-y/*0:1*/); -x/*0:01*/::bigint>>y/*0:1*/::int = bigint_shr x/*0:01*/ y/*0:1*/ if y/*0:1*/>=0; -x/*0:01*/::bigint>>y/*0:1*/::int = bigint_shl x/*0:01*/ (-y/*0:1*/); -x/*0:01*/::bigint+y/*0:1*/::bigint = bigint_add x/*0:01*/ y/*0:1*/; -x/*0:01*/::bigint-y/*0:1*/::bigint = bigint_sub x/*0:01*/ y/*0:1*/; -x/*0:01*/::bigint*y/*0:1*/::bigint = bigint_mul x/*0:01*/ y/*0:1*/; -x/*0:01*/::bigint/y/*0:1*/::bigint = double x/*0:01*//double y/*0:1*/; -x/*0:01*/::bigint div y/*0:1*/::bigint = bigint_div x/*0:01*/ y/*0:1*/; -x/*0:01*/::bigint mod y/*0:1*/::bigint = bigint_mod x/*0:01*/ y/*0:1*/; -x/*0:01*/::bigint or y/*0:1*/::bigint = bigint_or x/*0:01*/ y/*0:1*/; -x/*0:01*/::bigint and y/*0:1*/::bigint = bigint_and x/*0:01*/ y/*0:1*/; -x/*0:01*/::bigint<y/*0:1*/::bigint = bigint_cmp x/*0:01*/ y/*0:1*/<0; -x/*0:01*/::bigint>y/*0:1*/::bigint = bigint_cmp x/*0:01*/ y/*0:1*/>0; -x/*0:01*/::bigint<=y/*0:1*/::bigint = bigint_cmp x/*0:01*/ y/*0:1*/<=0; -x/*0:01*/::bigint>=y/*0:1*/::bigint = bigint_cmp x/*0:01*/ y/*0:1*/>=0; -x/*0:01*/::bigint==y/*0:1*/::bigint = bigint_cmp x/*0:01*/ y/*0:1*/==0; -x/*0:01*/::bigint!=y/*0:1*/::bigint = bigint_cmp x/*0:01*/ y/*0:1*/!=0; -x/*0:01*/::int+y/*0:1*/::bigint = bigint x/*0:01*/+y/*0:1*/; -x/*0:01*/::int-y/*0:1*/::bigint = bigint x/*0:01*/-y/*0:1*/; -x/*0:01*/::int*y/*0:1*/::bigint = bigint x/*0:01*/*y/*0:1*/; -x/*0:01*/::int/y/*0:1*/::bigint = double x/*0:01*//y/*0:1*/; -x/*0:01*/::int div y/*0:1*/::bigint = bigint x/*0:01*/ div y/*0:1*/; -x/*0:01*/::int mod y/*0:1*/::bigint = bigint x/*0:01*/ mod y/*0:1*/; -x/*0:01*/::int or y/*0:1*/::bigint = bigint x/*0:01*/ or y/*0:1*/; -x/*0:01*/::int and y/*0:1*/::bigint = bigint x/*0:01*/ and y/*0:1*/; -x/*0:01*/::int<y/*0:1*/::bigint = bigint x/*0:01*/<y/*0:1*/; -x/*0:01*/::int>y/*0:1*/::bigint = bigint x/*0:01*/>y/*0:1*/; -x/*0:01*/::int<=y/*0:1*/::bigint = bigint x/*0:01*/<=y/*0:1*/; -x/*0:01*/::int>=y/*0:1*/::bigint = bigint x/*0:01*/>=y/*0:1*/; -x/*0:01*/::int==y/*0:1*/::bigint = bigint x/*0:01*/==y/*0:1*/; -x/*0:01*/::int!=y/*0:1*/::bigint = bigint x/*0:01*/!=y/*0:1*/; -x/*0:01*/::bigint+y/*0:1*/::int = x/*0:01*/+bigint y/*0:1*/; -x/*0:01*/::bigint-y/*0:1*/::int = x/*0:01*/-bigint y/*0:1*/; -x/*0:01*/::bigint*y/*0:1*/::int = x/*0:01*/*bigint y/*0:1*/; -x/*0:01*/::bigint/y/*0:1*/::int = x/*0:01*//double y/*0:1*/; -x/*0:01*/::bigint div y/*0:1*/::int = x/*0:01*/ div bigint y/*0:1*/; -x/*0:01*/::bigint mod y/*0:1*/::int = x/*0:01*/ mod bigint y/*0:1*/; -x/*0:01*/::bigint or y/*0:1*/::int = x/*0:01*/ or bigint y/*0:1*/; -x/*0:01*/::bigint and y/*0:1*/::int = x/*0:01*/ and bigint y/*0:1*/; -x/*0:01*/::bigint<y/*0:1*/::int = x/*0:01*/<bigint y/*0:1*/; -x/*0:01*/::bigint>y/*0:1*/::int = x/*0:01*/>bigint y/*0:1*/; -x/*0:01*/::bigint<=y/*0:1*/::int = x/*0:01*/<=bigint y/*0:1*/; -x/*0:01*/::bigint>=y/*0:1*/::int = x/*0:01*/>=bigint y/*0:1*/; -x/*0:01*/::bigint==y/*0:1*/::int = x/*0:01*/==bigint y/*0:1*/; -x/*0:01*/::bigint!=y/*0:1*/::int = x/*0:01*/!=bigint y/*0:1*/; -x/*0:01*/::bigint+y/*0:1*/::double = double x/*0:01*/+y/*0:1*/; -x/*0:01*/::bigint-y/*0:1*/::double = double x/*0:01*/-y/*0:1*/; -x/*0:01*/::bigint*y/*0:1*/::double = double x/*0:01*/*y/*0:1*/; -x/*0:01*/::bigint/y/*0:1*/::double = double x/*0:01*//y/*0:1*/; -x/*0:01*/::bigint<y/*0:1*/::double = double x/*0:01*/<y/*0:1*/; -x/*0:01*/::bigint>y/*0:1*/::double = double x/*0:01*/>y/*0:1*/; -x/*0:01*/::bigint<=y/*0:1*/::double = double x/*0:01*/<=y/*0:1*/; -x/*0:01*/::bigint>=y/*0:1*/::double = double x/*0:01*/>=y/*0:1*/; -x/*0:01*/::bigint==y/*0:1*/::double = double x/*0:01*/==y/*0:1*/; -x/*0:01*/::bigint!=y/*0:1*/::double = double x/*0:01*/!=y/*0:1*/; -x/*0:01*/::double+y/*0:1*/::bigint = x/*0:01*/+double y/*0:1*/; -x/*0:01*/::double-y/*0:1*/::bigint = x/*0:01*/-double y/*0:1*/; -x/*0:01*/::double*y/*0:1*/::bigint = x/*0:01*/*double y/*0:1*/; -x/*0:01*/::double/y/*0:1*/::bigint = x/*0:01*//double y/*0:1*/; -x/*0:01*/::double<y/*0:1*/::bigint = x/*0:01*/<double y/*0:1*/; -x/*0:01*/::double>y/*0:1*/::bigint = x/*0:01*/>double y/*0:1*/; -x/*0:01*/::double<=y/*0:1*/::bigint = x/*0:01*/<=double y/*0:1*/; -x/*0:01*/::double>=y/*0:1*/::bigint = x/*0:01*/>=double y/*0:1*/; -x/*0:01*/::double==y/*0:1*/::bigint = x/*0:01*/==double y/*0:1*/; -x/*0:01*/::double!=y/*0:1*/::bigint = x/*0:01*/!=double y/*0:1*/; -gcd x/*0:01*/::bigint y/*0:1*/::bigint = bigint_gcd x/*0:01*/ y/*0:1*/; -lcm x/*0:01*/::bigint y/*0:1*/::bigint = bigint_lcm x/*0:01*/ y/*0:1*/; -gcd x/*0:01*/::int y/*0:1*/::bigint = bigint_gcd (bigint x/*0:01*/) y/*0:1*/; -gcd x/*0:01*/::bigint y/*0:1*/::int = bigint_gcd x/*0:01*/ (bigint y/*0:1*/); -gcd x/*0:01*/::int y/*0:1*/::int = int (bigint_gcd (bigint x/*0:01*/) (bigint y/*0:1*/)); -lcm x/*0:01*/::int y/*0:1*/::bigint = bigint_lcm (bigint x/*0:01*/) y/*0:1*/; -lcm x/*0:01*/::bigint y/*0:1*/::int = bigint_lcm x/*0:01*/ (bigint y/*0:1*/); -lcm x/*0:01*/::int y/*0:1*/::int = int (bigint_lcm (bigint x/*0:01*/) (bigint y/*0:1*/)); -pow x/*0:01*/::int y/*0:1*/::int = bigint_pow (bigint x/*0:01*/) y/*0:1*/ if y/*0:1*/>=0; -pow x/*0:01*/::bigint y/*0:1*/::bigint = bigint_pow x/*0:01*/ (int y/*0:1*/) if int y/*0:1*/>=0; -pow x/*0:01*/::double y/*0:1*/::double = c_pow x/*0:01*/ y/*0:1*/ if x/*0:01*/>=0||int y/*0:1*/==y/*0:1*/; -pow x/*0:01*/::int y/*0:1*/::bigint = bigint_pow (bigint x/*0:01*/) (int y/*0:1*/) if y/*0:1*/>=0; -pow x/*0:01*/::bigint y/*0:1*/::int = bigint_pow x/*0:01*/ y/*0:1*/ if y/*0:1*/>=0; -pow x/*0:01*/::double y/*0:1*/::int = c_pow x/*0:01*/ (double y/*0:1*/); -pow x/*0:01*/::double y/*0:1*/::bigint = c_pow x/*0:01*/ (double y/*0:1*/); -pow x/*0:01*/::int y/*0:1*/::double = c_pow (double x/*0:01*/) y/*0:1*/ if x/*0:01*/>=0||int y/*0:1*/==y/*0:1*/; -pow x/*0:01*/::bigint y/*0:1*/::double = c_pow (double x/*0:01*/) y/*0:1*/ if x/*0:01*/>=0||int y/*0:1*/==y/*0:1*/; -x/*0:01*/::double^y/*0:1*/::double = c_pow x/*0:01*/ y/*0:1*/ if x/*0:01*/>=0||int y/*0:1*/==y/*0:1*/; -x/*0:01*/::int^y/*0:1*/::int = c_pow (double x/*0:01*/) (double y/*0:1*/); -x/*0:01*/::bigint^y/*0:1*/::bigint = c_pow (double x/*0:01*/) (double y/*0:1*/); -x/*0:01*/::int^y/*0:1*/::bigint = c_pow (double x/*0:01*/) (double y/*0:1*/); -x/*0:01*/::bigint^y/*0:1*/::int = c_pow (double x/*0:01*/) (double y/*0:1*/); -x/*0:01*/::double^y/*0:1*/::int = c_pow x/*0:01*/ (double y/*0:1*/); -x/*0:01*/::double^y/*0:1*/::bigint = c_pow x/*0:01*/ (double y/*0:1*/); -x/*0:01*/::int^y/*0:1*/::double = c_pow (double x/*0:01*/) y/*0:1*/ if x/*0:01*/>=0||int y/*0:1*/==y/*0:1*/; -x/*0:01*/::bigint^y/*0:1*/::double = c_pow (double x/*0:01*/) y/*0:1*/ if x/*0:01*/>=0||int y/*0:1*/==y/*0:1*/; -x/*0:01*/::int^y/*0:1*/::double = double x/*0:01*/^y/*0:1*/; -x/*0:01*/::bigint^y/*0:1*/::double = double x/*0:01*/^y/*0:1*/; -null x/*0:1*/ = bigint x/*0:1*/==0; -x/*0:01*/-y/*0:1*/ = bigint x/*0:01*/-bigint y/*0:1*/; -x/*0:01*/+y/*0:1*/::int = pointer (bigint x/*0:01*/+y/*0:1*/); -x/*0:01*/+y/*0:1*/::bigint = pointer (bigint x/*0:01*/+y/*0:1*/); -x/*0:01*/<y/*0:1*/ = bigint x/*0:01*/<bigint y/*0:1*/; -x/*0:01*/>y/*0:1*/ = bigint x/*0:01*/>bigint y/*0:1*/; -x/*0:01*/<=y/*0:1*/ = bigint x/*0:01*/<=bigint y/*0:1*/; -x/*0:01*/>=y/*0:1*/ = bigint x/*0:01*/>=bigint y/*0:1*/; -x/*0:01*/==y/*0:1*/ = bigint x/*0:01*/==bigint y/*0:1*/; -x/*0:01*/!=y/*0:1*/ = bigint x/*0:01*/!=bigint y/*0:1*/; -get_byte x/*0:1*/ = pointer_get_byte x/*0:1*/; -get_int x/*0:1*/ = pointer_get_int x/*0:1*/; -get_double x/*0:1*/ = pointer_get_double x/*0:1*/; -get_string x/*0:1*/ = pointer_get_string x/*0:1*/; -get_pointer x/*0:1*/ = pointer_get_pointer x/*0:1*/; -put_byte x/*0:01*/ y/*0:1*/::int = pointer_put_byte x/*0:01*/ y/*0:1*/; -put_int x/*0:01*/ y/*0:1*/::int = pointer_put_int x/*0:01*/ y/*0:1*/; -put_double x/*0:01*/ y/*0:1*/::double = pointer_put_double x/*0:01*/ y/*0:1*/; -put_string x/*0:01*/ y/*0:1*/::string = pointer_put_string x/*0:01*/ y/*0:1*/; -put_pointer x/*0:01*/ y/*0:1*/::string = pointer_put_pointer x/*0:01*/ y/*0:1*/; -put_pointer x/*0:01*/ y/*0:1*/ = pointer_put_pointer x/*0:01*/ y/*0:1*/; -str x/*0:1*/ = cstring (pure_str x/*0:1*/); -chr n/*0:1*/::int = string_chr n/*0:1*/ if n/*0:1*/>0; -ord s/*0:1*/::string = string_ord s/*0:1*/ if #s/*0:1*/==1; -string s/*0:1*/ = pure_string s/*0:1*/; -cstring s/*0:1*/ = pure_cstring s/*0:1*/; -string_dup s/*0:1*/ = pure_string_dup s/*0:1*/; -cstring_dup s/*0:1*/ = pure_cstring_dup s/*0:1*/; -byte_string s/*0:1*/::string = pure_byte_string s/*0:1*/; -byte_cstring s/*0:1*/::string = pure_byte_cstring s/*0:1*/; -c/*0:01*/::string+n/*0:1*/::int = chr (ord c/*0:01*/+n/*0:1*/) if #c/*0:01*/==1; -c/*0:01*/::string-n/*0:1*/::int = chr (ord c/*0:01*/-n/*0:1*/) if #c/*0:01*/==1&&ord c/*0:01*/>=n/*0:1*/; -c/*0:01*/::string-d/*0:1*/::string = ord c/*0:01*/-ord d/*0:1*/ if #c/*0:01*/==1&&#d/*0:1*/==1; -null s/*0:1*/::string = string_null s/*0:1*/; -#s/*0:1*/::string = string_size s/*0:1*/; -s/*0:01*/::string!n/*0:1*/::int = string_char_at s/*0:01*/ n/*0:1*/ if n/*0:1*/>=0&&n/*0:1*/<#s/*0:01*/; -s/*0:01*/::string+t/*0:1*/::string = string_concat s/*0:01*/ t/*0:1*/; -chars s/*0:1*/::string = string_chars s/*0:1*/; -x/*0:01*/::string<y/*0:1*/::string = strcmp x/*0:01*/ y/*0:1*/<0; -x/*0:01*/::string>y/*0:1*/::string = strcmp x/*0:01*/ y/*0:1*/>0; -x/*0:01*/::string<=y/*0:1*/::string = strcmp x/*0:01*/ y/*0:1*/<=0; -x/*0:01*/::string>=y/*0:1*/::string = strcmp x/*0:01*/ y/*0:1*/>=0; -x/*0:01*/::string==y/*0:1*/::string = strcmp x/*0:01*/ y/*0:1*/==0; -x/*0:01*/::string!=y/*0:1*/::string = strcmp x/*0:01*/ y/*0:1*/!=0; -substr s/*0:001*/::string pos/*0:01*/::int size/*0:1*/::int = string_substr s/*0:001*/ (max/*0*/ 0 pos/*0:01*/) (max/*0*/ 0 size/*0:1*/) with max x/*0:01*/ y/*0:1*/ = if x/*0:01*/>=y/*0:1*/ then x/*0:01*/ else y/*0:1*/ { - rule #0: max x y = if x>=y then x else y - state 0: #0 - <var> state 1 - state 1: #0 - <var> state 2 - state 2: #0 -} end; -index s/*0:01*/::string u/*0:1*/::string = string_index s/*0:01*/ u/*0:1*/; -strcat xs/*0:1*/ = string_concat_list xs/*0:1*/ if listp xs/*0:1*/&&all stringp xs/*0:1*/; -join delim/*0:01*/::string [] = ""; -join delim/*0:01*/::string (x/*0:101*/::string:xs/*0:11*/) = x/*0:101*/+strcat (catmap (\x/*0:*/ -> [delim/*1:01*/+x/*0:*/] { - rule #0: x = [delim+x] - state 0: #0 - <var> state 1 - state 1: #0 -}) xs/*0:11*/) if listp xs/*0:11*/&&all stringp xs/*0:11*/; -split delim/*0:01*/::string s/*0:1*/::string = if null s/*1:1*/ then [] else split1/*0*/ delim/*1:01*/ s/*1:1*/ with split1 delim/*0:01*/ s/*0:1*/ = case index s/*0:1*/ delim/*0:01*/ of n/*0:*/ = take n/*0:*/ s/*1:1*/:split1/*2*/ delim/*1:01*/ (drop (n/*0:*/+m/*2:*/) s/*1:1*/) if n/*0:*/>=0; n/*0:*/ = [s/*1:1*/] { - rule #0: n = take n s:split1 delim (drop (n+m) s) if n>=0 - rule #1: n = [s] - state 0: #0 #1 - <var> state 1 - state 1: #0 #1 -} end { - rule #0: split1 delim s = case index s delim of n = take n s:split1 delim (drop (n+m) s) if n>=0; n = [s] end - state 0: #0 - <var> state 1 - state 1: #0 - <var> state 2 - state 2: #0 -} end when m/*0:*/ = #delim/*0:01*/ { - rule #0: m = #delim - state 0: #0 - <var> state 1 - state 1: #0 -} end if not null delim/*0:01*/; -list s/*0:1*/::string = chars s/*0:1*/; -tuple s/*0:1*/::string = tuple (chars s/*0:1*/); -reverse s/*0:1*/::string = strcat (reverse (chars s/*0:1*/)); -cat (s/*0:101*/::string:xs/*0:11*/) = cat (chars s/*0:101*/:xs/*0:11*/); -cycle n/*0:01*/::int "" = ""; -cycle n/*0:01*/::int s/*0:1*/::string = "" if n/*0:01*/<=0; -cycle n/*0:01*/::int s/*0:1*/::string = accum/*0*/ [] n/*1:01*/ with accum ys/*0:01*/ n/*0:1*/ = strcat ys/*0:01*/+take n/*0:1*/ s/*2:1*/ if n/*0:1*/<=m/*1:*/; accum ys/*0:01*/ n/*0:1*/ = accum/*1*/ (s/*2:1*/:ys/*0:01*/) (n/*0:1*/-m/*1:*/) { - rule #0: accum ys n = strcat ys+take n s if n<=m - rule #1: accum ys n = accum (s:ys) (n-m) - state 0: #0 #1 - <var> state 1 - state 1: #0 #1 - <var> state 2 - state 2: #0 #1 -} end when m/*0:*/::int = #s/*0:1*/ { - rule #0: m::int = #s - state 0: #0 - <var>::int state 1 - state 1: #0 -} end; -all p/*0:01*/ s/*0:1*/::string = all p/*0:01*/ (chars s/*0:1*/); -any p/*0:01*/ s/*0:1*/::string = any p/*0:01*/ (chars s/*0:1*/); -do f/*0:01*/ s/*0:1*/::string = do f/*0:01*/ (chars s/*0:1*/); -drop n/*0:01*/ s/*0:1*/::string = substr s/*0:1*/ n/*0:01*/ (#s/*0:1*/-n/*0:01*/); -dropwhile p/*0:01*/ s/*0:1*/::string = strcat (dropwhile p/*0:01*/ (chars s/*0:1*/)); -filter p/*0:01*/ s/*0:1*/::string = strcat (filter p/*0:01*/ (chars s/*0:1*/)); -foldl f/*0:001*/ a/*0:01*/ s/*0:1*/::string = foldl f/*0:001*/ a/*0:01*/ (chars s/*0:1*/); -foldl1 f/*0:01*/ s/*0:1*/::string = foldl1 f/*0:01*/ (chars s/*0:1*/); -foldr f/*0:001*/ a/*0:01*/ s/*0:1*/::string = foldr f/*0:001*/ a/*0:01*/ (chars s/*0:1*/); -foldr1 f/*0:01*/ s/*0:1*/::string = foldr1 f/*0:01*/ (chars s/*0:1*/); -head s/*0:1*/::string = s/*0:1*/!0 if not null s/*0:1*/; -init s/*0:1*/::string = substr s/*0:1*/ 0 (#s/*0:1*/-1) if not null s/*0:1*/; -last s/*0:1*/::string = s/*0:1*/!(#s/*0:1*/-1) if not null s/*0:1*/; -map f/*0:01*/ s/*0:1*/::string = map f/*0:01*/ (chars s/*0:1*/); -scanl f/*0:001*/ a/*0:01*/ s/*0:1*/::string = scanl f/*0:001*/ a/*0:01*/ (chars s/*0:1*/); -scanl1 f/*0:01*/ s/*0:1*/::string = scanl1 f/*0:01*/ (chars s/*0:1*/); -scanr f/*0:001*/ a/*0:01*/ s/*0:1*/::string = scanr f/*0:001*/ a/*0:01*/ (chars s/*0:1*/); -scanr1 f/*0:01*/ s/*0:1*/::string = scanr1 f/*0:01*/ (chars s/*0:1*/); -take n/*0:01*/ s/*0:1*/::string = substr s/*0:1*/ 0 n/*0:01*/; -takewhile p/*0:01*/ s/*0:1*/::string = strcat (takewhile p/*0:01*/ (chars s/*0:1*/)); -tail s/*0:1*/::string = substr s/*0:1*/ 1 (#s/*0:1*/-1) if not null s/*0:1*/; -zip s/*0:01*/::string t/*0:1*/::string = zip (chars s/*0:01*/) (chars t/*0:1*/); -zip3 s/*0:001*/::string t/*0:01*/::string u/*0:1*/::string = zip3 (chars s/*0:001*/) (chars t/*0:01*/) (chars u/*0:1*/); -zipwith f/*0:001*/ s/*0:01*/::string t/*0:1*/::string = zipwith f/*0:001*/ (chars s/*0:01*/) (chars t/*0:1*/); -zipwith3 f/*0:0001*/ s/*0:001*/::string t/*0:01*/::string u/*0:1*/::string = zipwith3 f/*0:0001*/ (chars s/*0:001*/) (chars t/*0:01*/) (chars u/*0:1*/); -dowith f/*0:001*/ s/*0:01*/::string t/*0:1*/::string = dowith f/*0:001*/ (chars s/*0:01*/) (chars t/*0:1*/); -dowith3 f/*0:0001*/ s/*0:001*/::string t/*0:01*/::string u/*0:1*/::string = dowith3 f/*0:0001*/ (chars s/*0:001*/) (chars t/*0:01*/) (chars u/*0:1*/); f/*0:01*/$x/*0:1*/ = f/*0:01*/ x/*0:1*/; (f/*0:001*/.g/*0:01*/) x/*0:1*/ = f/*0:001*/ (g/*0:01*/ x/*0:1*/); void _/*0:1*/ = (); Modified: pure/trunk/test/test011.log =================================================================== --- pure/trunk/test/test011.log 2008-07-02 23:31:57 UTC (rev 373) +++ pure/trunk/test/test011.log 2008-07-03 00:19:47 UTC (rev 374) @@ -1,2107 +1,3 @@ -pure_sys_vars; -errno = pure_errno; -set_errno val/*0:1*/::int = pure_set_errno val/*0:1*/; -fgets f/*0:1*/ = read_a_line/*1*/ f/*1:1*/ buf/*0:*/ "" when buf/*0:*/ = malloc 1024 { - rule #0: buf = malloc 1024 - state 0: #0 - <var> state 1 - state 1: #0 -} end with read_a_line f/*0:001*/ buf/*0:01*/ t/*0:1*/ = check/*1*/ s/*0:*/ when s/*0:*/ = c_fgets buf/*0:01*/ 1024 f/*0:001*/ { - rule #0: s = c_fgets buf 1024 f - state 0: #0 - <var> state 1 - state 1: #0 -} end with check s/*0:1*/::string = return/*1*/ (t/*1:1*/+s/*0:1*/) if done/*1*/ s/*0:1*/; check s/*0:1*/::string = read_a_line/*2*/ f/*1:001*/ buf/*1:01*/ (t/*1:1*/+s/*0:1*/); check s/*0:1*/ = return/*1*/ s/*0:1*/ if null t/*1:1*/; check s/*0:1*/ = return/*1*/ t/*1:1*/ { - rule #0: check s::string = return (t+s) if done s - rule #1: check s::string = read_a_line f buf (t+s) - rule #2: check s = return s if null t - rule #3: check s = return t - state 0: #0 #1 #2 #3 - <var> state 1 - <var>::string state 2 - state 1: #2 #3 - state 2: #0 #1 #2 #3 -}; return x/*0:1*/ = x/*1:1*/ when _/*0:*/ = free buf/*1:01*/ { - rule #0: _ = free buf - state 0: #0 - <var> state 1 - state 1: #0 -} end { - rule #0: return x = x when _ = free buf end - state 0: #0 - <var> state 1 - state 1: #0 -}; done s/*0:1*/::string = feof f/*1:001*/||ferror f/*1:001*/||not null s/*0:1*/&&last s/*0:1*/=="\n" { - rule #0: done s::string = feof f||ferror f||not null s&&last s=="\n" - state 0: #0 - <var>::string state 1 - state 1: #0 -} end { - rule #0: read_a_line f buf t = check s when s = c_fgets buf 1024 f end with check s::string = return (t+s) if done s; check s::string = read_a_line f buf (t+s); check s = return s if null t; check s = return t; return x = x when _ = free buf end; done s::string = feof f||ferror f||not null s&&last s=="\n" end - state 0: #0 - <var> state 1 - state 1: #0 - <var> state 2 - state 2: #0 - <var> state 3 - state 3: #0 -} end; -gets = if null s/*0:*/ then s/*0:*/ else if last s/*0:*/=="\n" then init s/*0:*/ else s/*0:*/ when s/*0:*/ = fgets stdin { - rule #0: s = fgets stdin - state 0: #0 - <var> state 1 - state 1: #0 -} end; -fget f/*0:1*/ = read_a_file/*1*/ f/*1:1*/ buf/*0:*/ "" when buf/*0:*/ = malloc 65536 { - rule #0: buf = malloc 65536 - state 0: #0 - <var> state 1 - state 1: #0 -} end with read_a_file f/*0:001*/ buf/*0:01*/ t/*0:1*/ = check/*1*/ s/*0:*/ when s/*0:*/ = c_fgets buf/*0:01*/ 65536 f/*0:001*/ { - rule #0: s = c_fgets buf 65536 f - state 0: #0 - <var> state 1 - state 1: #0 -} end with check s/*0:1*/::string = return/*1*/ (t/*1:1*/+s/*0:1*/) if feof f/*1:001*/||ferror f/*1:001*/; check s/*0:1*/::string = read_a_file/*2*/ f/*1:001*/ buf/*1:01*/ (t/*1:1*/+s/*0:1*/); check s/*0:1*/ = return/*1*/ s/*0:1*/ if null t/*1:1*/; check s/*0:1*/ = return/*1*/ t/*1:1*/ { - rule #0: check s::string = return (t+s) if feof f||ferror f - rule #1: check s::string = read_a_file f buf (t+s) - rule #2: check s = return s if null t - rule #3: check s = return t - state 0: #0 #1 #2 #3 - <var> state 1 - <var>::string state 2 - state 1: #2 #3 - state 2: #0 #1 #2 #3 -}; return x/*0:1*/ = x/*1:1*/ when _/*0:*/ = free buf/*1:01*/ { - rule #0: _ = free buf - state 0: #0 - <var> state 1 - state 1: #0 -} end { - rule #0: return x = x when _ = free buf end - state 0: #0 - <var> state 1 - state 1: #0 -} end { - rule #0: read_a_file f buf t = check s when s = c_fgets buf 65536 f end with check s::string = return (t+s) if feof f||ferror f; check s::string = read_a_file f buf (t+s); check s = return s if null t; check s = return t; return x = x when _ = free buf end end - state 0: #0 - <var> state 1 - state 1: #0 - <var> state 2 - state 2: #0 - <var> state 3 - state 3: #0 -} end; -printf format/*0:01*/::string args/*0:1*/ = fprintf stdout format/*0:01*/ args/*0:1*/; -fprintf fp/*0:001*/ format/*0:01*/::string args/*0:1*/ = count/*0:01*/ when args/*0:*/ = if tuplep args/*0:1*/ then list args/*0:1*/ else [args/*0:1*/]; count/*0:01*/,_/*0:1*/ = catch error_handler/*1*/ (foldl (do_fprintf/*2*/ fp/*2:001*/) (0,args/*1:*/)$printf_split_format format/*2:01*/) { - rule #0: count,_ = catch error_handler (foldl (do_fprintf fp) (0,args)$printf_split_format format) - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - <var> state 4 - state 4: #0 - <var> state 5 - state 5: #0 -} { - rule #0: args = if tuplep args then list args else [args] - state 0: #0 - <var> state 1 - state 1: #0 -} end with error_handler (printf_error res/*0:11*/::int) = res/*0:11*/,[]; error_handler x/*0:1*/ = throw x/*0:1*/ { - rule #0: error_handler (printf_error res::int) = res,[] - rule #1: error_handler x = throw x - state 0: #0 #1 - <var> state 1 - <app> state 2 - state 1: #1 - state 2: #0 #1 - <var> state 3 - printf_error state 5 - state 3: #1 - <var> state 4 - state 4: #1 - state 5: #0 #1 - <var> state 6 - <var>::int state 7 - state 6: #1 - state 7: #0 #1 -}; do_fprintf fp/*0:001*/ (count/*0:0101*/,arg/*0:01101*/:args/*0:0111*/) (printf_format_spec t/*0:101*/ s/*0:11*/) = count/*0:*/,args/*2:0111*/ when res/*0:*/ = case t/*0:101*/,arg/*0:01101*/ of "d",x/*0:1*/::int = pure_fprintf_int fp/*1:001*/ s/*1:11*/ x/*0:1*/; "d",x/*0:1*/::bigint = pure_fprintf_int fp/*1:001*/ s/*1:11*/ (int x/*0:1*/); "g",x/*0:1*/::double = pure_fprintf_double fp/*1:001*/ s/*1:11*/ x/*0:1*/; "s",x/*0:1*/::string = pure_fprintf_string fp/*1:001*/ s/*1:11*/ x/*0:1*/; "p",x/*0:1*/::string = pure_fprintf_pointer fp/*1:001*/ s/*1:11*/ x/*0:1*/; "p",x/*0:1*/ = pure_fprintf_pointer fp/*1:001*/ s/*1:11*/ x/*0:1*/; _/*0:*/ = throw (printf_value_error s/*1:11*/ arg/*1:01101*/) { - rule #0: "d",x::int = pure_fprintf_int fp s x - rule #1: "d",x::bigint = pure_fprintf_int fp s (int x) - rule #2: "g",x::double = pure_fprintf_double fp s x - rule #3: "s",x::string = pure_fprintf_string fp s x - rule #4: "p",x::string = pure_fprintf_pointer fp s x - rule #5: "p",x = pure_fprintf_pointer fp s x - rule #6: _ = throw (printf_value_error s arg) - state 0: #0 #1 #2 #3 #4 #5 #6 - <var> state 1 - <app> state 2 - state 1: #6 - state 2: #0 #1 #2 #3 #4 #5 #6 - <var> state 3 - <app> state 5 - state 3: #6 - <var> state 4 - state 4: #6 - state 5: #0 #1 #2 #3 #4 #5 #6 - <var> state 6 - , state 9 - state 6: #6 - <var> state 7 - state 7: #6 - <var> state 8 - state 8: #6 - state 9: #0 #1 #2 #3 #4 #5 #6 - <var> state 10 - "d"::string state 12 - "g"::string state 16 - "s"::string state 19 - "p"::string state 22 - state 10: #6 - <var> state 11 - state 11: #6 - state 12: #0 #1 #6 - <var> state 13 - <var>::int state 14 - <var>::bigint state 15 - state 13: #6 - state 14: #0 #6 - state 15: #1 #6 - state 16: #2 #6 - <var> state 17 - <var>::double state 18 - state 17: #6 - state 18: #2 #6 - state 19: #3 #6 - <var> state 20 - <var>::string state 21 - state 20: #6 - state 21: #3 #6 - state 22: #4 #5 #6 - <var> state 23 - <var>::string state 24 - <var> state 25 - state 23: #6 - state 24: #4 #6 - state 25: #5 #6 -} end; count/*0:*/ = if res/*0:*/>=0 then count/*1:0101*/+res/*0:*/ else throw printf_error res/*0:*/ { - rule #0: count = if res>=0 then count+res else throw printf_error res - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: res = case t,arg of "d",x::int = pure_fprintf_int fp s x; "d",x::bigint = pure_fprintf_int fp s (int x); "g",x::double = pure_fprintf_double fp s x; "s",x::string = pure_fprintf_string fp s x; "p",x::string = pure_fprintf_pointer fp s x; "p",x = pure_fprintf_pointer fp s x; _ = throw (printf_value_error s arg) end - state 0: #0 - <var> state 1 - state 1: #0 -} end; do_fprintf fp/*0:001*/ (count/*0:0101*/,args/*0:011*/) (printf_format_str s/*0:11*/) = count/*0:*/,args/*2:011*/ when res/*0:*/ = pure_fprintf fp/*0:001*/ s/*0:11*/; count/*0:*/ = if res/*0:*/>=0 then count/*1:0101*/+res/*0:*/ else throw printf_error res/*0:*/ { - rule #0: count = if res>=0 then count+res else throw printf_error res - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: res = pure_fprintf fp s - state 0: #0 - <var> state 1 - state 1: #0 -} end; do_fprintf fp/*0:001*/ (count/*0:0101*/,_/*0:011*/) _/*0:1*/ = throw printf_arg_error { - rule #0: do_fprintf fp (count,arg:args) (printf_format_spec t s) = count,args when res = case t,arg of "d",x::int = pure_fprintf_int fp s x; "d",x::bigint = pure_fprintf_int fp s (int x); "g",x::double = pure_fprintf_double fp s x; "s",x::string = pure_fprintf_string fp s x; "p",x::string = pure_fprintf_pointer fp s x; "p",x = pure_fprintf_pointer fp s x; _ = throw (printf_value_error s arg) end; count = if res>=0 then count+res else throw printf_error res end - rule #1: do_fprintf fp (count,args) (printf_format_str s) = count,args when res = pure_fprintf fp s; count = if res>=0 then count+res else throw printf_error res end - rule #2: do_fprintf fp (count,_) _ = throw printf_arg_error - state 0: #0 #1 #2 - <var> state 1 - state 1: #0 #1 #2 - <app> state 2 - state 2: #0 #1 #2 - <app> state 3 - state 3: #0 #1 #2 - , state 4 - state 4: #0 #1 #2 - <var> state 5 - state 5: #0 #1 #2 - <var> state 6 - <app> state 13 - state 6: #1 #2 - <var> state 7 - <app> state 8 - state 7: #2 - state 8: #1 #2 - <var> state 9 - printf_format_str state 11 - state 9: #2 - <var> state 10 - state 10: #2 - state 11: #1 #2 - <var> state 12 - state 12: #1 #2 - state 13: #0 #1 #2 - <var> state 14 - <app> state 22 - state 14: #1 #2 - <var> state 15 - state 15: #1 #2 - <var> state 16 - <app> state 17 - state 16: #2 - state 17: #1 #2 - <var> state 18 - printf_format_str state 20 - state 18: #2 - <var> state 19 - state 19: #2 - state 20: #1 #2 - <var> state 21 - state 21: #1 #2 - state 22: #0 #1 #2 - <var> state 23 - : state 32 - state 23: #1 #2 - <var> state 24 - state 24: #1 #2 - <var> state 25 - state 25: #1 #2 - <var> state 26 - <app> state 27 - state 26: #2 - state 27: #1 #2 - <var> state 28 - printf_format_str state 30 - state 28: #2 - <var> state 29 - state 29: #2 - state 30: #1 #2 - <var> state 31 - state 31: #1 #2 - state 32: #0 #1 #2 - <var> state 33 - state 33: #0 #1 #2 - <var> state 34 - state 34: #0 #1 #2 - <var> state 35 - <app> state 36 - state 35: #2 - state 36: #0 #1 #2 - <var> state 37 - <app> state 39 - printf_format_str state 46 - state 37: #2 - <var> state 38 - state 38: #2 - state 39: #0 #2 - <var> state 40 - printf_format_spec state 43 - state 40: #2 - <var> state 41 - state 41: #2 - <var> state 42 - state 42: #2 - state 43: #0 #2 - <var> state 44 - state 44: #0 #2 - <var> state 45 - state 45: #0 #2 - state 46: #1 #2 - <var> state 47 - state 47: #1 #2 -} end; -printf_split_format format/*0:1*/ = regexg analyze/*0*/ "(%[-#0 ]?[0-9]*([.][0-9]*)?[diouxXeEfgGsp])|(%)|([^%]|%%)+" REG_EXTENDED format/*0:1*/ 0 with analyze info/*0:1*/ = if p/*1:01*/>=0 then printf_format_spec (format_type/*4*/ (last u/*2:1*/)) u/*2:1*/ else if q/*0:01*/>=0 then throw (printf_format_error q/*0:01*/) else printf_format_str u/*2:1*/ when _/*0:01*/,u/*0:1*/ = reg 0 info/*0:1*/; p/*0:01*/,_/*0:1*/ = reg 1 info/*1:1*/; q/*0:01*/,_/*0:1*/ = reg 3 info/*2:1*/ { - rule #0: q,_ = reg 3 info - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - <var> state 4 - state 4: #0 - <var> state 5 - state 5: #0 -} { - rule #0: p,_ = reg 1 info - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - <var> state 4 - state 4: #0 - <var> state 5 - state 5: #0 -} { - rule #0: _,u = reg 0 info - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - <var> state 4 - state 4: #0 - <var> state 5 - state 5: #0 -} end { - rule #0: analyze info = if p>=0 then printf_format_spec (format_type (last u)) u else if q>=0 then throw (printf_format_error q) else printf_format_str u when _,u = reg 0 info; p,_ = reg 1 info; q,_ = reg 3 info end - state 0: #0 - <var> state 1 - state 1: #0 -}; format_type x/*0:1*/ = if index "diouxX" x/*0:1*/>=0 then "d" else if index "eEfgG" x/*0:1*/>=0 then "g" else x/*0:1*/ { - rule #0: format_type x = if index "diouxX" x>=0 then "d" else if index "eEfgG" x>=0 then "g" else x - state 0: #0 - <var> state 1 - state 1: #0 -} end; -sprintf format/*0:01*/::string args/*0:1*/ = s/*0:01*/ when args/*0:*/ = if tuplep args/*0:1*/ then list args/*0:1*/ else [args/*0:1*/]; s/*0:01*/,_/*0:1*/ = catch error_handler/*1*/ (foldl do_sprintf/*2*/ ("",args/*1:*/)$printf_split_format format/*2:01*/) { - rule #0: s,_ = catch error_handler (foldl do_sprintf ("",args)$printf_split_format format) - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - <var> state 4 - state 4: #0 - <var> state 5 - state 5: #0 -} { - rule #0: args = if tuplep args then list args else [args] - state 0: #0 - <var> state 1 - state 1: #0 -} end with error_handler (printf_error res/*0:11*/::int) = pointer 0,[]; error_handler x/*0:1*/ = throw x/*0:1*/ { - rule #0: error_handler (printf_error res::int) = pointer 0,[] - rule #1: error_handler x = throw x - state 0: #0 #1 - <var> state 1 - <app> state 2 - state 1: #1 - state 2: #0 #1 - <var> state 3 - printf_error state 5 - state 3: #1 - <var> state 4 - state 4: #1 - state 5: #0 #1 - <var> state 6 - <var>::int state 7 - state 6: #1 - state 7: #0 #1 -}; do_sprintf (u/*0:0101*/,arg/*0:01101*/:args/*0:0111*/) (printf_format_spec t/*0:101*/ s/*0:11*/) = u/*0:*/,args/*4:0111*/ when size/*0:*/ = case t/*0:101*/,arg/*0:01101*/ of "s",x/*0:1*/::string = #s/*1:11*/+#x/*0:1*/+1000; _/*0:*/ = 64 { - rule #0: "s",x::string = #s+#x+1000 - rule #1: _ = 64 - state 0: #0 #1 - <var> state 1 - <app> state 2 - state 1: #1 - state 2: #0 #1 - <var> state 3 - <app> state 5 - state 3: #1 - <var> state 4 - state 4: #1 - state 5: #0 #1 - <var> state 6 - , state 9 - state 6: #1 - <var> state 7 - state 7: #1 - <var> state 8 - state 8: #1 - state 9: #0 #1 - <var> state 10 - "s"::string state 12 - state 10: #1 - <var> state 11 - state 11: #1 - state 12: #0 #1 - <var> state 13 - <var>::string state 14 - state 13: #1 - state 14: #0 #1 -} end; buf/*0:*/ = check_buf/*2*/ (malloc size/*0:*/); res/*0:*/ = case t/*2:101*/,arg/*2:01101*/ of "d",x/*0:1*/::int = pure_snprintf_int buf/*1:*/ size/*2:*/ s/*3:11*/ x/*0:1*/; "d",x/*0:1*/::bigint = pure_snprintf_int buf/*1:*/ size/*2:*/ s/*3:11*/ (int x/*0:1*/); "g",x/*0:1*/::double = pure_snprintf_double buf/*1:*/ size/*2:*/ s/*3:11*/ x/*0:1*/; "s",x/*0:1*/::string = pure_snprintf_string buf/*1:*/ size/*2:*/ s/*3:11*/ x/*0:1*/; "p",x/*0:1*/::string = pure_snprintf_pointer buf/*1:*/ size/*2:*/ s/*3:11*/ x/*0:1*/; "p",x/*0:1*/ = pure_snprintf_pointer buf/*1:*/ size/*2:*/ s/*3:11*/ x/*0:1*/; _/*0:*/ = throw (printf_value_error s/*4:11*/ arg/*4:01101*/) when _/*0:*/ = free buf/*1:*/ { - rule #0: _ = free buf - state 0: #0 - <var> state 1 - state 1: #0 -} end { - rule #0: "d",x::int = pure_snprintf_int buf size s x - rule #1: "d",x::bigint = pure_snprintf_int buf size s (int x) - rule #2: "g",x::double = pure_snprintf_double buf size s x - rule #3: "s",x::string = pure_snprintf_string buf size s x - rule #4: "p",x::string = pure_snprintf_pointer buf size s x - rule #5: "p",x = pure_snprintf_pointer buf size s x - rule #6: _ = throw (printf_value_error s arg) when _ = free buf end - state 0: #0 #1 #2 #3 #4 #5 #6 - <var> state 1 - <app> state 2 - state 1: #6 - state 2: #0 #1 #2 #3 #4 #5 #6 - <var> state 3 - <app> state 5 - state 3: #6 - <var> state 4 - state 4: #6 - state 5: #0 #1 #2 #3 #4 #5 #6 - <var> state 6 - , state 9 - state 6: #6 - <var> state 7 - state 7: #6 - <var> state 8 - state 8: #6 - state 9: #0 #1 #2 #3 #4 #5 #6 - <var> state 10 - "d"::string state 12 - "g"::string state 16 - "s"::string state 19 - "p"::string state 22 - state 10: #6 - <var> state 11 - state 11: #6 - state 12: #0 #1 #6 - <var> state 13 - <var>::int state 14 - <var>::bigint state 15 - state 13: #6 - state 14: #0 #6 - state 15: #1 #6 - state 16: #2 #6 - <var> state 17 - <var>::double state 18 - state 17: #6 - state 18: #2 #6 - state 19: #3 #6 - <var> state 20 - <var>::string state 21 - state 20: #6 - state 21: #3 #6 - state 22: #4 #5 #6 - <var> state 23 - <var>::string state 24 - <var> state 25 - state 23: #6 - state 24: #4 #6 - state 25: #5 #6 -} end; u/*0:*/ = if res/*0:*/>=0 then u/*3:0101*/+cstring buf/*1:*/ else throw printf_error res/*1:*/ when _/*0:*/ = free buf/*1:*/ { - rule #0: _ = free buf - state 0: #0 - <var> state 1 - state 1: #0 -} end { - rule #0: u = if res>=0 then u+cstring buf else throw printf_error res when _ = free buf end - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: res = case t,arg of "d",x::int = pure_snprintf_int buf size s x; "d",x::bigint = pure_snprintf_int buf size s (int x); "g",x::double = pure_snprintf_double buf size s x; "s",x::string = pure_snprintf_string buf size s x; "p",x::string = pure_snprintf_pointer buf size s x; "p",x = pure_snprintf_pointer buf size s x; _ = throw (printf_value_error s arg) when _ = free buf end end - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: buf = check_buf (malloc size) - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: size = case t,arg of "s",x::string = #s+#x+1000; _ = 64 end - state 0: #0 - <var> state 1 - state 1: #0 -} end; do_sprintf (u/*0:0101*/,args/*0:011*/) (printf_format_str s/*0:11*/) = u/*0:*/,args/*4:011*/ when size/*0:*/ = #s/*0:11*/+1000; buf/*0:*/ = check_buf/*2*/ (malloc size/*0:*/); res/*0:*/ = pure_snprintf buf/*0:*/ size/*1:*/ s/*2:11*/; u/*0:*/ = if res/*0:*/>=0 then u/*3:0101*/+cstring buf/*1:*/ else throw printf_error res/*1:*/ when _/*0:*/ = free buf/*1:*/ { - rule #0: _ = free buf - state 0: #0 - <var> state 1 - state 1: #0 -} end { - rule #0: u = if res>=0 then u+cstring buf else throw printf_error res when _ = free buf end - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: res = pure_snprintf buf size s - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: buf = check_buf (malloc size) - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: size = #s+1000 - state 0: #0 - <var> state 1 - state 1: #0 -} end; do_sprintf (u/*0:0101*/,_/*0:011*/) _/*0:1*/ = throw printf_arg_error { - rule #0: do_sprintf (u,arg:args) (printf_format_spec t s) = u,args when size = case t,arg of "s",x::string = #s+#x+1000; _ = 64 end; buf = check_buf (malloc size); res = case t,arg of "d",x::int = pure_snprintf_int buf size s x; "d",x::bigint = pure_snprintf_int buf size s (int x); "g",x::double = pure_snprintf_double buf size s x; "s",x::string = pure_snprintf_string buf size s x; "p",x::string = pure_snprintf_pointer buf size s x; "p",x = pure_snprintf_pointer buf size s x; _ = throw (printf_value_error s arg) when _ = free buf end end; u = if res>=0 then u+cstring buf else throw printf_error res when _ = free buf end end - rule #1: do_sprintf (u,args) (printf_format_str s) = u,args when size = #s+1000; buf = check_buf (malloc size); res = pure_snprintf buf size s; u = if res>=0 then u+cstring buf else throw printf_error res when _ = free buf end end - rule #2: do_sprintf (u,_) _ = throw printf_arg_error - state 0: #0 #1 #2 - <app> state 1 - state 1: #0 #1 #2 - <app> state 2 - state 2: #0 #1 #2 - , state 3 - state 3: #0 #1 #2 - <var> state 4 - state 4: #0 #1 #2 - <var> state 5 - <app> state 12 - state 5: #1 #2 - <var> state 6 - <app> state 7 - state 6: #2 - state 7: #1 #2 - <var> state 8 - printf_format_str state 10 - state 8: #2 - <var> state 9 - state 9: #2 - state 10: #1 #2 - <var> state 11 - state 11: #1 #2 - state 12: #0 #1 #2 - <var> state 13 - <app> state 21 - state 13: #1 #2 - <var> state 14 - state 14: #1 #2 - <var> state 15 - <app> state 16 - state 15: #2 - state 16: #1 #2 - <var> state 17 - printf_format_str state 19 - state 17: #2 - <var> state 18 - state 18: #2 - state 19: #1 #2 - <var> state 20 - state 20: #1 #2 - state 21: #0 #1 #2 - <var> state 22 - : state 31 - state 22: #1 #2 - <var> state 23 - state 23: #1 #2 - <var> state 24 - state 24: #1 #2 - <var> state 25 - <app> state 26 - state 25: #2 - state 26: #1 #2 - <var> state 27 - printf_format_str state 29 - state 27: #2 - <var> state 28 - state 28: #2 - state 29: #1 #2 - <var> state 30 - state 30: #1 #2 - state 31: #0 #1 #2 - <var> state 32 - state 32: #0 #1 #2 - <var> state 33 - state 33: #0 #1 #2 - <var> state 34 - <app> state 35 - state 34: #2 - state 35: #0 #1 #2 - <var> state 36 - <app> state 38 - printf_format_str state 45 - state 36: #2 - <var> state 37 - state 37: #2 - state 38: #0 #2 - <var> state 39 - printf_format_spec state 42 - state 39: #2 - <var> state 40 - state 40: #2 - <var> state 41 - state 41: #2 - state 42: #0 #2 - <var> state 43 - state 43: #0 #2 - <var> state 44 - state 44: #0 #2 - state 45: #1 #2 - <var> state 46 - state 46: #1 #2 -}; check_buf buf/*0:1*/ = throw printf_malloc_error if null buf/*0:1*/; check_buf buf/*0:1*/ = buf/*0:1*/ { - rule #0: check_buf buf = throw printf_malloc_error if null buf - rule #1: check_buf buf = buf - state 0: #0 #1 - <var> state 1 - state 1: #0 #1 -} end; -scanf format/*0:1*/::string = fscanf stdin format/*0:1*/; -fscanf fp/*0:01*/ format/*0:1*/::string = tuple$reverse ret/*0:1*/ when _/*0:01*/,ret/*0:1*/ = catch error_handler/*0*/ (foldl (do_fscanf/*1*/ fp/*1:01*/) (0,[])$scanf_split_format format/*1:1*/) { - rule #0: _,ret = catch error_handler (foldl (do_fscanf fp) (0,[])$scanf_split_format format) - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - <var> state 4 - state 4: #0 - <var> state 5 - state 5: #0 -} end with error_handler (scanf_error ret/*0:11*/) = throw (scanf_error (tuple$reverse ret/*0:11*/)); error_handler x/*0:1*/ = throw x/*0:1*/ { - rule #0: error_handler (scanf_error ret) = throw (scanf_error (tuple$reverse ret)) - rule #1: error_handler x = throw x - state 0: #0 #1 - <var> state 1 - <app> state 2 - state 1: #1 - state 2: #0 #1 - <var> state 3 - scanf_error state 5 - state 3: #1 - <var> state 4 - state 4: #1 - state 5: #0 #1 - <var> state 6 - state 6: #0 #1 -}; check_buf buf/*0:1*/ = throw scanf_malloc_error if null buf/*0:1*/; check_buf buf/*0:1*/ = buf/*0:1*/ { - rule #0: check_buf buf = throw scanf_malloc_error if null buf - rule #1: check_buf buf = buf - state 0: #0 #1 - <var> state 1 - state 1: #0 #1 -}; do_fscanf fp/*0:001*/ (nread/*0:0101*/,ret/*0:011*/) (scanf_format_spec t/*0:101*/ s/*0:11*/) = nread/*7:0101*/+res/*3:*/,ret/*0:*/ 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/*3:001*/ s/*2:1*/ buf/*1:*/; "d" = pure_fscanf_int fp/*3:001*/ s/*2:1*/ buf/*1:*/; "g" = pure_fscanf_double fp/*3:001*/ s/*2:1*/ buf/*1:*/; "s" = pure_fscanf_string fp/*3:001*/ s/*2:1*/ buf/*1:*/; "p" = pure_fscanf_pointer fp/*3:001*/ s/*2:1*/ buf/*1:*/; _/*0:*/ = throw (this_cant_happen ret/*3:011*/) { - rule #0: "n" = pure_fscanf_int fp s buf - rule #1: "d" = pure_fscanf_int fp s buf - rule #2: "g" = pure_fscanf_double fp s buf - rule #3: "s" = pure_fscanf_string fp s buf - rule #4: "p" = pure_fscanf_pointer fp s buf - rule #5: _ = throw (this_cant_happen ret) - state 0: #0 #1 #2 #3 #4 #5 - <var> state 1 - "n"::string state 2 - "d"::string state 3 - "g"::string state 4 - "s"::string state 5 - "p"::string state 6 - state 1: #5 - state 2: #0 #5 - state 3: #1 #5 - state 4: #2 #5 - state 5: #3 #5 - state 6: #4 #5 -} end; res/*0:*/ = if res/*0:*/>=0 then res/*0:*/ else throw (scanf_error ret/*4:011*/) when _/*0:*/ = free buf/*1:*/ { - rule #0: _ = free buf - state 0: #0 - <var> state 1 - state 1: #0 -} end; val/*0:*/ = case t/*4:101*/ of "n" = nread/*5:0101*/+get_int buf/*3:*/; "d" = get_int buf/*3:*/; "g" = get_double buf/*3:*/; "s" = cstring buf/*3:*/; "p" = get_pointer buf/*3:*/; _/*0:*/ = throw (this_cant_happen ret/*5:011*/) { - rule #0: "n" = nread+get_int buf - rule #1: "d" = get_int buf - rule #2: "g" = get_double buf - rule #3: "s" = cstring buf - rule #4: "p" = get_pointer buf - rule #5: _ = throw (this_cant_happen ret) - state 0: #0 #1 #2 #3 #4 #5 - <var> state 1 - "n"::string state 2 - "d"::string state 3 - "g"::string state 4 - "s"::string state 5 - "p"::string state 6 - state 1: #5 - state 2: #0 #5 - state 3: #1 #5 - state 4: #2 #5 - state 5: #3 #5 - state 6: #4 #5 -} end; _/*0:*/ = if t/*5:101*/=="s" then () else free buf/*3:*/; ret/*0:*/ = val/*1:*/:ret/*6:011*/ { - rule #0: ret = val:ret - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: _ = if t=="s" then () else free buf - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: 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 - state 0: #0 - <var> state 1 - state 1: #0 -} { - 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 -} { - rule #0: res = case t of "n" = pure_fscanf_int fp s buf; "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 - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: buf = check_buf (calloc size 1) - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: size,s = if t=="s" then guestimate s else 16,s - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - <var> state 4 - state 4: #0 - <var> state 5 - state 5: #0 -} end; do_fscanf fp/*0:001*/ (nread/*0:0101*/,ret/*0:011*/) (scanf_format_str s/*0:11*/) = nread/*2:0101*/+res/*1:*/,ret/*0:*/ when res/*0:*/ = pure_fscanf fp/*0:001*/ s/*0:11*/; ret/*0:*/ = if res/*0:*/>=0 then ret/*1:011*/ else throw (scanf_error ret/*1:011*/) { - rule #0: ret = if res>=0 then ret else throw (scanf_error ret) - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: res = pure_fscanf fp s - state 0: #0 - <var> state 1 - state 1: #0 -} end; do_fscanf _/*0:001*/ (_/*0:0101*/,ret/*0:011*/) _/*0:1*/ = throw (this_cant_happen ret/*0:011*/) { - rule #0: do_fscanf fp (nread,ret) (scanf_format_spec t s) = 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_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 "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 end - rule #1: do_fscanf fp (nread,ret) (scanf_format_str s) = nread+res,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 - <var> state 1 - state 1: #0 #1 #2 - <app> state 2 - state 2: #0 #1 #2 - <app> state 3 - state 3: #0 #1 #2 - , state 4 - state 4: #0 #1 #2 - <var> state 5 - state 5: #0 #1 #2 - <var> state 6 - state 6: #0 #1 #2 - <var> state 7 - <app> state 8 - state 7: #2 - state 8: #0 #1 #2 - <var> state 9 - <app> state 11 - scanf_format_str state 18 - state 9: #2 - <var> state 10 - state 10: #2 - state 11: #0 #2 - <var> state 12 - scanf_format_spec state 15 - state 12: #2 - <var> state 13 - state 13: #2 - <var> state 14 - state 14: #2 - state 15: #0 #2 - <var> state 16 - state 16: #0 #2 - <var> state 17 - state 17: #0 #2 - state 18: #1 #2 - <var> state 19 - state 19: #1 #2 -}; guestimate format/*0:1*/ = n/*0:01*/,format/*0:1*/ when 1,0,_/*0:1101*/,1,s/*0:1111*/ = regex "^%([0-9]*)" REG_EXTENDED format/*0:1*/ 0; n/*0:01*/,format/*0:1*/ = if null s/*0:1111*/ then 1025,"%1024"+tail format/*1:1*/ else eval s/*0:1111*/+1,format/*1:1*/ { - rule #0: n,format = if null s then 1025,"%1024"+tail format else eval s+1,format - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - <var> state 4 - state 4: #0 - <var> state 5 - state 5: #0 -} { - rule #0: 1,0,_,1,s = regex "^%([0-9]*)" REG_EXTENDED format 0 - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - 1::int state 4 - state 4: #0 - <app> state 5 - state 5: #0 - <app> state 6 - state 6: #0 - , state 7 - state 7: #0 - 0::int state 8 - state 8: #0 - <app> state 9 - state 9: #0 - <app> state 10 - state 10: #0 - , state 11 - state 11: #0 - <var> state 12 - state 12: #0 - <app> state 13 - state 13: #0 - <app> state 14 - state 14: #0 - , state 15 - state 15: #0 - 1::int state 16 - state 16: #0 - <var> state 17 - state 17: #0 -} end { - rule #0: 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 - state 0: #0 - <var> state 1 - state 1: #0 -} end; -scanf_split_format format/*0:1*/ = regexg analyze/*0*/ "(%[*]?[0-9]*([cdiouxXneEfgsp]|\\[\\^?\\]?[^]]+\\]))|(%)|([^%]|%%)+" REG_EXTENDED format/*0:1*/ 0 with analyze info/*0:1*/ = if p/*1:01*/>=0&&u/*2:1*/!1!="*" then scanf_format_spec t/*0:*/ (kludge/*5*/ t/*0:*/ u/*3:1*/) when t/*0:*/ = format_type/*4*/ (last u/*2:1*/) { - rule #0: t = format_type (last u) - state 0: #0 - <var> state 1 - state 1: #0 -} end else if q/*0:01*/>=0 then throw (scanf_format_error q/*0:01*/) else scanf_format_str u/*2:1*/ when _/*0:01*/,u/*0:1*/ = reg 0 info/*0:1*/; p/*0:01*/,_/*0:1*/ = reg 1 info/*1:1*/; q/*0:01*/,_/*0:1*/ = reg 3 info/*2:1*/ { - rule #0: q,_ = reg 3 info - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - <var> state 4 - state 4: #0 - <var> state 5 - state 5: #0 -} { - rule #0: p,_ = reg 1 info - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - <var> state 4 - state 4: #0 - <var> state 5 - state 5: #0 -} { - rule #0: _,u = reg 0 info - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - <var> state 4 - state 4: #0 - <var> state 5 - state 5: #0 -} end { - rule #0: analyze info = if p>=0&&u!1!="*" then scanf_format_spec t (kludge t u) when t = format_type (last u) end else if q>=0 then throw (scanf_format_error q) else scanf_format_str u when _,u = reg 0 info; p,_ = reg 1 info; q,_ = reg 3 info end - state 0: #0 - <var> state 1 - state 1: #0 -}; format_type x/*0:1*/ = if x/*0:1*/=="n" then "n" else if index "diouxX" x/*0:1*/>=0 then "d" else if index "eEfg" x/*0:1*/>=0 then "g" else if x/*0:1*/=="]"||x/*0:1*/=="c" then "s" else x/*0:1*/ { - rule #0: format_type x = if x=="n" then "n" else if index "diouxX" x>=0 then "d" else if index "eEfg" x>=0 then "g" else if x=="]"||x=="c" then "s" else x - state 0: #0 - <var> state 1 - state 1: #0 -}; kludge "g" u/*0:1*/ = init u/*0:1*/+"l"+last u/*0:1*/; kludge _/*0:01*/ u/*0:1*/ = u/*0:1*/ { - rule #0: kludge "g" u = init u+"l"+last u - rule #1: kludge _ u = u - state 0: #0 #1 - <var> state 1 - "g"::string state 3 - state 1: #1 - <var> state 2 - state 2: #1 - state 3: #0 #1 - <var> state 4 - state 4: #0 #1 -} end; -sscanf s/*0:01*/::string format/*0:1*/::string = tuple$reverse ret/*0:11*/ when _/*0:01*/,_/*0:101*/,ret/*0:11*/ = catch error_handler/*0*/ (foldl do_sscanf/*1*/ (s/*1:01*/,0,[])$scanf_split_format format/*1:1*/) { - rule #0: _,_,ret = catch error_handler (foldl do_sscanf (s,0,[])$scanf_split_format format) - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - <var> state 4 - state 4: #0 - <app> state 5 - state 5: #0 - <app> state 6 - state 6: #0 - , state 7 - state 7: #0 - <var> state 8 - state 8: #0 - <var> state 9 - state 9: #0 -} end with error_handler (scanf_error ret/*0:11*/) = throw (scanf_error (tuple$reverse ret/*0:11*/)); error_handler x/*0:1*/ = throw x/*0:1*/ { - rule #0: error_handler (scanf_error ret) = throw (scanf_error (tuple$reverse ret)) - rule #1: error_handler x = throw x - state 0: #0 #1 - <var> state 1 - <app> state 2 - state 1: #1 - state 2: #0 #1 - <var> state 3 - scanf_error state 5 - state 3: #1 - <var> state 4 - state 4: #1 - state 5: #0 #1 - <var> state 6 - state 6: #0 #1 -}; check_buf buf/*0:1*/ = throw scanf_malloc_error if null buf/*0:1*/; check_buf buf/*0:1*/ = buf/*0:1*/ { - rule #0: check_buf buf = throw scanf_malloc_error if null buf - rule #1: check_buf buf = buf - state 0: #0 #1 - <var> state 1 - state 1: #0 #1 -}; guestimate format/*0:1*/ = n/*0:01*/,format/*0:1*/ when 1,0,_/*0:1101*/,1,s/*0:1111*/ = regex "^%([0-9]*)" REG_EXTENDED format/*0:1*/ 0; n/*0:01*/,format/*0:1*/ = if null s/*0:1111*/ then 1025,"%1024"+tail format/*1:1*/ else eval s/*0:1111*/+1,format/*1:1*/ { - rule #0: n,format = if null s then 1025,"%1024"+tail format else eval s+1,format - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - <var> state 4 - state 4: #0 - <var> state 5 - state 5: #0 -} { - rule #0: 1,0,_,1,s = regex "^%([0-9]*)" REG_EXTENDED format 0 - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - 1::int state 4 - state 4: #0 - <app> state 5 - state 5: #0 - <app> state 6 - state 6: #0 - , state 7 - state 7: #0 - 0::int state 8 - state 8: #0 - <app> state 9 - state 9: #0 - <app> state 10 - state 10: #0 - , state 11 - state 11: #0 - <var> state 12 - state 12: #0 - <app> state 13 - state 13: #0 - <app> state 14 - state 14: #0 - , state 15 - state 15: #0 - 1::int state 16 - state 16: #0 - <var> state 17 - state 17: #0 -} end { - rule #0: 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 - 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_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 - rule #4: "p" = pure_sscanf_pointer u s buf - rule #5: _ = throw (this_cant_happen ret) - state 0: #0 #1 #2 #3 #4 #5 - <var> state 1 - "n"::string state 2 - "d"::string state 3 - "g"::string state 4 - "s"::string state 5 - "p"::string state 6 - state 1: #5 - state 2: #0 #5 - state 3: #1 #5 - state 4: #2 #5 - state 5: #3 #5 - state 6: #4 #5 -} end; res/*0:*/ = if res/*0:*/>=0 then res/*0:*/ else throw (scanf_error ret/*4:0111*/) when _/*0:*/ = free buf/*1:*/ { - rule #0: _ = free buf - state 0: #0 - <var> state 1 - state 1: #0 -} end; val/*0:*/ = case t/*4:101*/ of "n" = nread/*5:01101*/+get_int buf/*3:*/; "d" = get_int buf/*3:*/; "g" = get_double buf/*3:*/; "s" = cstring buf/*3:*/; "p" = get_pointer buf/*3:*/; _/*0:*/ = throw (this_cant_happen ret/*5:0111*/) { - rule #0: "n" = nread+get_int buf - rule #1: "d" = get_int buf - rule #2: "g" = get_double buf - rule #3: "s" = cstring buf - rule #4: "p" = get_pointer buf - rule #5: _ = throw (this_cant_happen ret) - state 0: #0 #1 #2 #3 #4 #5 - <var> state 1 - "n"::string state 2 - "d"::string state 3 - "g"::string state 4 - "s"::string state 5 - "p"::string state 6 - state 1: #5 - state 2: #0 #5 - state 3: #1 #5 - state 4: #2 #5 - state 5: #3 #5 - state 6: #4 #5 -} end; _/*0:*/ = if t/*5:101*/=="s" then () else free buf/*3:*/; ret/*0:*/ = val/*1:*/:ret/*6:0111*/; u/*0:*/ = drop res/*3:*/ u/*7:0101*/ { - rule #0: u = drop res u - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: ret = val:ret - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: _ = if t=="s" then () else free buf - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: 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 - state 0: #0 - <var> state 1 - state 1: #0 -} { - 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 -} { - 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 -} { - rule #0: buf = check_buf (calloc size 1) - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: size,s = if t=="s" then guestimate s else 16,s - state 0: #0 - <app> state 1 - state 1: #0 - <app> state 2 - state 2: #0 - , state 3 - state 3: #0 - <var> state 4 - state 4: #0 - <var> state 5 - state 5: #0 -} end; do_sscanf (u/*0:0101*/,nread/*0:01101*/,ret/*0:0111*/) (scanf_format_str s/*0:11*/) = u/*0:*/,nread/*3:01101*/+res/*2:*/,ret/*1:*/ when res/*0:*/ = pure_sscanf u/*0:0101*/ s/*0:11*/; ret/*0:*/ = if res/*0:*/>=0 then ret/*1:0111*/ else throw (scanf_error ret/*1:0111*/); u/*0:*/ = drop res/*1:*/ u/*2:0101*/ { - rule #0: u = drop res u - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: ret = if res>=0 then ret else throw (scanf_error ret) - state 0: #0 - <var> state 1 - state 1: #0 -} { - rule #0: res = pure_sscanf u s - state 0: #0 - <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_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 (scan... [truncated message content] |