pure-lang-svn Mailing List for Pure (Page 7)
Status: Beta
Brought to you by:
agraef
You can subscribe to this list here.
2008 |
Jan
|
Feb
|
Mar
|
Apr
(5) |
May
(141) |
Jun
(184) |
Jul
(97) |
Aug
(232) |
Sep
(196) |
Oct
|
Nov
|
Dec
|
---|
From: <ag...@us...> - 2008-09-05 14:12:05
|
Revision: 720 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=720&view=rev Author: agraef Date: 2008-09-05 14:12:15 +0000 (Fri, 05 Sep 2008) Log Message: ----------- Print warning message if the prelude wasn't found. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/pure.cc Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-09-05 13:40:46 UTC (rev 719) +++ pure/trunk/ChangeLog 2008-09-05 14:12:15 UTC (rev 720) @@ -1,5 +1,9 @@ 2008-09-05 Albert Graef <Dr....@t-...> + * pure.cc (main): In interactive mode, print a warning if -n was + not specified and the prelude wasn't found. Suggested by Rob + Hubbard. + * printer.cc (operator << (ostream& os, const pure_expr *x)): Experimental support for calling a user-defined __show__ function to override print representations of expressions at runtime. Modified: pure/trunk/pure.cc =================================================================== --- pure/trunk/pure.cc 2008-09-05 13:40:46 UTC (rev 719) +++ pure/trunk/pure.cc 2008-09-05 14:12:15 UTC (rev 720) @@ -408,6 +408,8 @@ << COPYRIGHT << endl << LICENSE; if (have_prelude) cout << "Loaded prelude from " << prelude << ".\n"; + else if (want_prelude) + cout << "Couldn't find the prelude. Please check your PURELIB environment variable.\n"; cout << endl; } interp.compile(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-05 13:40:37
|
Revision: 719 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=719&view=rev Author: agraef Date: 2008-09-05 13:40:46 +0000 (Fri, 05 Sep 2008) Log Message: ----------- User can now override print representations of expressions at runtime via the __show__ function. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/printer.cc pure/trunk/symtable.cc pure/trunk/symtable.hh Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-09-05 12:11:50 UTC (rev 718) +++ pure/trunk/ChangeLog 2008-09-05 13:40:46 UTC (rev 719) @@ -1,5 +1,9 @@ 2008-09-05 Albert Graef <Dr....@t-...> + * printer.cc (operator << (ostream& os, const pure_expr *x)): + Experimental support for calling a user-defined __show__ function + to override print representations of expressions at runtime. + * configure.ac, runtime.cc (pure_sys_vars): Add configure checks for POSIX/ISOC99 complex types. (Requires reconfigure.) Modified: pure/trunk/printer.cc =================================================================== --- pure/trunk/printer.cc 2008-09-05 12:11:50 UTC (rev 718) +++ pure/trunk/printer.cc 2008-09-05 13:40:46 UTC (rev 719) @@ -622,6 +622,28 @@ return os << p.x; } +static inline bool pstr(ostream& os, pure_expr *x) +{ + interpreter& interp = *interpreter::g_interp; + int32_t f = interp.symtab.__show__sym; + if (f > 0 && interp.globenv.find(f) != interp.globenv.end()) { + assert(x->refc > 0); + pure_expr *y = pure_app(pure_symbol(f), x); + assert(y); + if (y->tag == EXPR::STR) { + char *s = fromutf8(y->data.s); + pure_freenew(y); + if (s) { + os << s; free(s); + return true; + } else + return false; + } else + return false; + } else + return false; +} + ostream& operator << (ostream& os, const pure_expr *x) { char test; @@ -631,6 +653,7 @@ throw err("stack overflow in printer"); char buf[64]; assert(x); + if (pstr(os, (pure_expr*)x)) return os; //os << "{" << x->refc << "}"; switch (x->tag) { case EXPR::INT: Modified: pure/trunk/symtable.cc =================================================================== --- pure/trunk/symtable.cc 2008-09-05 12:11:50 UTC (rev 718) +++ pure/trunk/symtable.cc 2008-09-05 13:40:46 UTC (rev 719) @@ -2,7 +2,7 @@ #include "symtable.hh" #include <assert.h> -symtable::symtable() : fno(0), rtab(1024) +symtable::symtable() : fno(0), rtab(1024), __show__sym(0) { // enter any predefined symbols here, e.g.: //sym("-", 6, infixl); @@ -72,6 +72,7 @@ _sym = symbol(s, fno, modno); //cout << "new symbol " << _sym.f << ": " << _sym.s << endl; rtab[fno] = &_sym; + if (__show__sym == 0 && s == "__show__") __show__sym = fno; } return _sym; } @@ -88,6 +89,7 @@ _sym = symbol(s, fno, prec, fix, modno); //cout << "new symbol " << _sym.f << ": " << _sym.s << endl; rtab[fno] = &_sym; + if (__show__sym == 0 && s == "__show__") __show__sym = fno; } return _sym; } @@ -125,6 +127,7 @@ _sym = symbol(s, fno, prec, fix, modno); //cout << "new symbol " << _sym.f << ": " << _sym.s << endl; rtab[fno] = &_sym; + if (__show__sym == 0 && s == "__show__") __show__sym = fno; } return _sym; } Modified: pure/trunk/symtable.hh =================================================================== --- pure/trunk/symtable.hh 2008-09-05 12:11:50 UTC (rev 718) +++ pure/trunk/symtable.hh 2008-09-05 13:40:46 UTC (rev 719) @@ -63,6 +63,7 @@ // get a symbol by its number symbol& sym(int32_t f); // retrieve various builtin symbols (create when necessary) + int32_t __show__sym; // This is cached here to improve performance. symbol& nil_sym(); symbol& cons_sym(); symbol& void_sym(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-05 12:11:40
|
Revision: 718 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=718&view=rev Author: agraef Date: 2008-09-05 12:11:50 +0000 (Fri, 05 Sep 2008) Log Message: ----------- Updated ChangeLog. Modified Paths: -------------- pure/trunk/ChangeLog Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-09-05 11:13:38 UTC (rev 717) +++ pure/trunk/ChangeLog 2008-09-05 12:11:50 UTC (rev 718) @@ -108,7 +108,8 @@ * lib/: Clean up the public namespace. * lexer.ll: Added limited support for unicode symbols. These can - now be declared as operator or nullary symbols. + now be declared as operator or nullary symbols. (At present this + is only guaranteed to work if your scripts are encoded in UTF-8.) * parser.yy, etc.: Symbols can now be declared 'private'. These aren't visible anywhere except in the module that declares them. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-05 11:13:27
|
Revision: 717 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=717&view=rev Author: agraef Date: 2008-09-05 11:13:38 +0000 (Fri, 05 Sep 2008) Log Message: ----------- Add configure checks for POSIX/ISOC99 complex types. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/config.h.in pure/trunk/configure pure/trunk/configure.ac pure/trunk/runtime.cc Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-09-05 11:08:32 UTC (rev 716) +++ pure/trunk/ChangeLog 2008-09-05 11:13:38 UTC (rev 717) @@ -1,5 +1,8 @@ 2008-09-05 Albert Graef <Dr....@t-...> + * configure.ac, runtime.cc (pure_sys_vars): Add configure checks + for POSIX/ISOC99 complex types. (Requires reconfigure.) + * runtime.cc (pure_force): Fix a rather obscure segfault in the thunk implementation. See also test/test023.pure. Modified: pure/trunk/config.h.in =================================================================== --- pure/trunk/config.h.in 2008-09-05 11:08:32 UTC (rev 716) +++ pure/trunk/config.h.in 2008-09-05 11:13:38 UTC (rev 717) @@ -78,6 +78,12 @@ /* Define to 1 if you have the `usleep' function. */ #undef HAVE_USLEEP +/* Define to 1 if the system has the type `_Complex double'. */ +#undef HAVE__COMPLEX_DOUBLE + +/* Define to 1 if the system has the type `_Complex float'. */ +#undef HAVE__COMPLEX_FLOAT + /* Define to the name of the host system. */ #undef HOST Modified: pure/trunk/configure =================================================================== --- pure/trunk/configure 2008-09-05 11:08:32 UTC (rev 716) +++ pure/trunk/configure 2008-09-05 11:13:38 UTC (rev 717) @@ -5472,6 +5472,129 @@ fi done +{ echo "$as_me:$LINENO: checking for _Complex float" >&5 +echo $ECHO_N "checking for _Complex float... $ECHO_C" >&6; } +if test "${ac_cv_type__Complex_float+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef _Complex float ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type__Complex_float=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type__Complex_float=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type__Complex_float" >&5 +echo "${ECHO_T}$ac_cv_type__Complex_float" >&6; } +if test $ac_cv_type__Complex_float = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE__COMPLEX_FLOAT 1 +_ACEOF + + +fi +{ echo "$as_me:$LINENO: checking for _Complex double" >&5 +echo $ECHO_N "checking for _Complex double... $ECHO_C" >&6; } +if test "${ac_cv_type__Complex_double+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef _Complex double ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type__Complex_double=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type__Complex_double=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type__Complex_double" >&5 +echo "${ECHO_T}$ac_cv_type__Complex_double" >&6; } +if test $ac_cv_type__Complex_double = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE__COMPLEX_DOUBLE 1 +_ACEOF + + +fi + ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF Modified: pure/trunk/configure.ac =================================================================== --- pure/trunk/configure.ac 2008-09-05 11:08:32 UTC (rev 716) +++ pure/trunk/configure.ac 2008-09-05 11:13:38 UTC (rev 717) @@ -91,6 +91,8 @@ AC_FUNC_ALLOCA dnl Platform-dependent time functions. AC_CHECK_FUNCS(ftime gettimeofday nanosleep usleep) +dnl Check to see whether we have POSIX/ISOC99 complex numbers. +AC_CHECK_TYPES([_Complex float, _Complex double]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-09-05 11:08:32 UTC (rev 716) +++ pure/trunk/runtime.cc 2008-09-05 11:13:38 UTC (rev 717) @@ -3263,8 +3263,12 @@ cdf(interp, "SIZEOF_LONG_LONG", pure_int(sizeof(long long))); cdf(interp, "SIZEOF_FLOAT", pure_int(sizeof(float))); cdf(interp, "SIZEOF_DOUBLE", pure_int(sizeof(double))); +#ifdef HAVE__COMPLEX_FLOAT cdf(interp, "SIZEOF_COMPLEX_FLOAT", pure_int(sizeof(_Complex float))); +#endif +#ifdef HAVE__COMPLEX_DOUBLE cdf(interp, "SIZEOF_COMPLEX_DOUBLE", pure_int(sizeof(_Complex double))); +#endif cdf(interp, "SIZEOF_POINTER", pure_int(sizeof(void*))); // clock cdf(interp, "CLOCKS_PER_SEC", pure_int(CLOCKS_PER_SEC)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-05 11:08:23
|
Revision: 716 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=716&view=rev Author: agraef Date: 2008-09-05 11:08:32 +0000 (Fri, 05 Sep 2008) Log Message: ----------- Update logs. Modified Paths: -------------- pure/trunk/test/prelude.log Modified: pure/trunk/test/prelude.log =================================================================== --- pure/trunk/test/prelude.log 2008-09-05 10:47:34 UTC (rev 715) +++ pure/trunk/test/prelude.log 2008-09-05 11:08:32 UTC (rev 716) @@ -773,7 +773,67 @@ scanl1 f/*0:01*/ [] = []; scanl1 f/*0:01*/ (x/*0:101*/:xs/*0:11*/) = scanl f/*0:01*/ x/*0:101*/ xs/*0:11*/; scanr f/*0:001*/ a/*0:01*/ [] = [a/*0:01*/]; -scanr f/*0:001*/ a/*0:01*/ xs@(_/*0:101*/:_/*0:11*/) = tick/*0*/ [] xs/*0:1*/ with tick zs/*0:01*/ (x/*0:101*/:xs/*0:11*/) = tack/*1*/ zs/*0:01*/ (f/*3:001*/ x/*2:101*/ (y/*0:01*/ when y/*0:01*/:_/*0:1*/ = ys/*1:*/ { +scanr f/*0:001*/ a/*0:01*/ xs@(_/*0:101*/:_/*0:11*/) = tick/*0*/ [] xs/*0:1*/ with tick zs/*0:01*/ (x/*0:101*/:xs/*0:11*/) = tack/*4*/ zs/*3:01*/ us/*0:*/ when ys/*0:*/ = scanr f/*2:001*/ a/*2:01*/ xs/*1:11*/&; y/*0:*/ = (case ys/*1:*/ of y/*0:01*/:_/*0:1*/ = y/*0:01*/; scanr _/*0:001*/ _/*0:01*/ ys/*0:1*/ = throw (bad_list_value ys/*0:1*/); _/*0:*/ = throw (bad_list_value ys/*2:*/) { + rule #0: y:_ = y + rule #1: scanr _ _ ys = throw (bad_list_value ys) + rule #2: _ = throw (bad_list_value ys) + state 0: #0 #1 #2 + <var> state 1 + <app> state 2 + state 1: #2 + state 2: #0 #1 #2 + <var> state 3 + <app> state 5 + state 3: #2 + <var> state 4 + state 4: #2 + state 5: #0 #1 #2 + <var> state 6 + : state 9 + <app> state 12 + state 6: #2 + <var> state 7 + state 7: #2 + <var> state 8 + state 8: #2 + state 9: #0 #2 + <var> state 10 + state 10: #0 #2 + <var> state 11 + state 11: #0 #2 + state 12: #1 #2 + <var> state 13 + scanr state 17 + state 13: #2 + <var> state 14 + state 14: #2 + <var> state 15 + state 15: #2 + <var> state 16 + state 16: #2 + state 17: #1 #2 + <var> state 18 + state 18: #1 #2 + <var> state 19 + state 19: #1 #2 + <var> state 20 + state 20: #1 #2 +} end)&; us/*0:*/ = f/*3:001*/ x/*2:101*/ y/*0:*/:ys/*1:*/ { + rule #0: us = f x y:ys + state 0: #0 + <var> state 1 + state 1: #0 +} { + rule #0: y = (case ys of y:_ = y; scanr _ _ ys = throw (bad_list_value ys); _ = throw (bad_list_value ys) end)& + state 0: #0 + <var> state 1 + state 1: #0 +} { + rule #0: ys = scanr f a xs& + state 0: #0 + <var> state 1 + state 1: #0 +} end if thunkp xs/*0:11*/; tick zs/*0:01*/ (x/*0:101*/:xs/*0:11*/) = tack/*1*/ zs/*0:01*/ (f/*3:001*/ x/*2:101*/ (y/*0:01*/ when y/*0:01*/:_/*0:1*/ = ys/*1:*/ { rule #0: y:_ = ys state 0: #0 <app> state 1 @@ -792,37 +852,38 @@ <var> state 1 state 1: #0 } end) if thunkp xs/*0:11*/; tick zs/*0:01*/ (x/*0:101*/:xs/*0:11*/) = tick/*1*/ (x/*0:101*/:zs/*0:01*/) xs/*0:11*/; tick zs/*0:01*/ [] = tack/*1*/ zs/*0:01*/ [a/*1:01*/]; tick zs/*0:01*/ xs/*0:1*/ = throw (bad_list_value xs/*0:1*/) { - rule #0: tick zs (x:xs) = tack zs (f x (y when y:_ = ys end)&:ys when ys = scanr f a xs& end) if thunkp xs - rule #1: tick zs (x:xs) = tick (x:zs) xs - rule #2: tick zs [] = tack zs [a] - rule #3: tick zs xs = throw (bad_list_value xs) - state 0: #0 #1 #2 #3 + rule #0: tick zs (x:xs) = tack zs us when ys = scanr f a xs&; y = (case ys of y:_ = y; scanr _ _ ys = throw (bad_list_value ys); _ = throw (bad_list_value ys) end)&; us = f x y:ys end if thunkp xs + rule #1: tick zs (x:xs) = tack zs (f x (y when y:_ = ys end)&:ys when ys = scanr f a xs& end) if thunkp xs + rule #2: tick zs (x:xs) = tick (x:zs) xs + rule #3: tick zs [] = tack zs [a] + rule #4: tick zs xs = throw (bad_list_value xs) + state 0: #0 #1 #2 #3 #4 <var> state 1 - state 1: #0 #1 #2 #3 + state 1: #0 #1 #2 #3 #4 <var> state 2 <app> state 3 [] state 13 - state 2: #3 - state 3: #0 #1 #3 + state 2: #4 + state 3: #0 #1 #2 #4 <var> state 4 <app> state 6 - state 4: #3 + state 4: #4 <var> state 5 - state 5: #3 - state 6: #0 #1 #3 + state 5: #4 + state 6: #0 #1 #2 #4 <var> state 7 : state 10 - state 7: #3 + state 7: #4 <var> state 8 - state 8: #3 + state 8: #4 <var> state 9 - state 9: #3 - state 10: #0 #1 #3 + state 9: #4 + state 10: #0 #1 #2 #4 <var> state 11 - state 11: #0 #1 #3 + state 11: #0 #1 #2 #4 <var> state 12 - state 12: #0 #1 #3 - state 13: #2 #3 + state 12: #0 #1 #2 #4 + state 13: #3 #4 }; tack (x/*0:0101*/:xs/*0:011*/) ys/*0:1*/ = tack/*2*/ xs/*1:011*/ (f/*2:001*/ x/*1:0101*/ y/*0:01*/:ys/*1:1*/) when y/*0:01*/:_/*0:1*/ = ys/*0:1*/ { rule #0: y:_ = ys state 0: #0 @@ -859,25 +920,55 @@ } end; scanr1 f/*0:01*/ [] = []; scanr1 f/*0:01*/ [x/*0:101*/] = [x/*0:101*/]; -scanr1 f/*0:01*/ xs@(_/*0:101*/:_/*0:11*/) = tick/*0*/ [] xs/*0:1*/ with tick zs/*0:01*/ (x/*0:101*/:xs/*0:11*/) = tack/*1*/ zs/*0:01*/ (f/*3:01*/ x/*2:101*/ (y/*0:01*/ when y/*0:01*/:_/*0:1*/ = ys/*1:*/ { - rule #0: y:_ = ys +scanr1 f/*0:01*/ xs@(_/*0:101*/:_/*0:11*/) = tick/*0*/ [] xs/*0:1*/ with tick zs/*0:01*/ (x/*0:101*/:xs/*0:11*/) = tack/*4*/ zs/*3:01*/ us/*0:*/ when ys/*0:*/ = scanr1 f/*2:01*/ xs/*1:11*/&; y/*0:*/ = (case ys/*1:*/ of y/*0:01*/:_/*0:1*/ = y/*0:01*/; scanr1 _/*0:01*/ ys/*0:1*/ = throw (bad_list_value ys/*0:1*/); _/*0:*/ = throw (bad_list_value ys/*2:*/) { + rule #0: y:_ = y + rule #1: scanr1 _ ys = throw (bad_list_value ys) + rule #2: _ = throw (bad_list_value ys) + state 0: #0 #1 #2 + <var> state 1 + <app> state 2 + state 1: #2 + state 2: #0 #1 #2 + <var> state 3 + <app> state 5 + state 3: #2 + <var> state 4 + state 4: #2 + state 5: #0 #1 #2 + <var> state 6 + : state 9 + scanr1 state 12 + state 6: #2 + <var> state 7 + state 7: #2 + <var> state 8 + state 8: #2 + state 9: #0 #2 + <var> state 10 + state 10: #0 #2 + <var> state 11 + state 11: #0 #2 + state 12: #1 #2 + <var> state 13 + state 13: #1 #2 + <var> state 14 + state 14: #1 #2 +} end)&; us/*0:*/ = f/*3:01*/ x/*2:101*/ y/*0:*/:ys/*1:*/ { + rule #0: us = f x y:ys state 0: #0 - <app> state 1 + <var> 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)&:ys/*0:*/ when ys/*0:*/ = scanr1 f/*2:01*/ xs/*1:11*/& { +} { + rule #0: y = (case ys of y:_ = y; scanr1 _ ys = throw (bad_list_value ys); _ = throw (bad_list_value ys) end)& + state 0: #0 + <var> state 1 + state 1: #0 +} { rule #0: ys = scanr1 f xs& state 0: #0 <var> state 1 state 1: #0 -} end) if thunkp xs/*0:11*/; tick zs/*0:01*/ xs/*0:1*/ = case xs/*0:1*/ of [x/*0:01*/] = tack/*2*/ zs/*1:01*/ [x/*0:01*/]; x/*0:01*/:xs/*0:1*/ = tick/*2*/ (x/*0:01*/:zs/*1:01*/) xs/*0:1*/; _/*0:*/ = throw (bad_list_value xs/*1:1*/) { +} end if thunkp xs/*0:11*/; tick zs/*0:01*/ xs/*0:1*/ = case xs/*0:1*/ of [x/*0:01*/] = tack/*2*/ zs/*1:01*/ [x/*0:01*/]; x/*0:01*/:xs/*0:1*/ = tick/*2*/ (x/*0:01*/:zs/*1:01*/) xs/*0:1*/; _/*0:*/ = throw (bad_list_value xs/*1:1*/) { rule #0: [x] = tack zs [x] rule #1: x:xs = tick (x:zs) xs rule #2: _ = throw (bad_list_value xs) @@ -907,7 +998,7 @@ state 11: #1 #2 state 12: #0 #1 #2 } end { - rule #0: tick zs (x:xs) = tack zs (f x (y when y:_ = ys end)&:ys when ys = scanr1 f xs& end) if thunkp xs + rule #0: tick zs (x:xs) = tack zs us when ys = scanr1 f xs&; y = (case ys of y:_ = y; scanr1 _ ys = throw (bad_list_value ys); _ = throw (bad_list_value ys) end)&; us = f x y:ys end if thunkp xs rule #1: tick zs xs = case xs of [x] = tack zs [x]; x:xs = tick (x:zs) xs; _ = throw (bad_list_value xs) end state 0: #0 #1 <var> state 1 @@ -1801,8 +1892,8 @@ dowith3 f/*0:0001*/ (x/*0:00101*/:xs/*0:0011*/) (y/*0:0101*/:ys/*0:011*/) (z/*0:101*/:zs/*0:11*/) = f/*0:0001*/ x/*0:00101*/ y/*0:0101*/ z/*0:101*/$$dowith3 f/*0:0001*/ xs/*0:0011*/ ys/*0:011*/ zs/*0:11*/; dowith3 f/*0:0001*/ _/*0:001*/ _/*0:01*/ _/*0:1*/ = (); unzip [] = [],[]; -unzip us@(_/*0:101*/:_/*0:11*/) = foldr accum/*0*/ ([],[]) us/*0:1*/ with accum u@(x/*0:0101*/,y/*0:011*/) us/*0:1*/ = x/*0:0101*/:(xs/*0:01*/ when xs/*0:01*/,_/*0:1*/ = us/*1:1*/ { - rule #0: xs,_ = us +unzip us@(_/*0:101*/:_/*0:11*/) = foldr accum/*0*/ ([],[]) us/*0:1*/ with accum u@(x/*0:0101*/,y/*0:011*/) us/*0:1*/ = x/*0:0101*/:(xs/*0:01*/ when xs/*0:01*/,_/*0:1*/ = check/*2*/ us/*1:1*/ { + rule #0: xs,_ = check us state 0: #0 <app> state 1 state 1: #0 @@ -1814,8 +1905,8 @@ state 4: #0 <var> state 5 state 5: #0 -} end)&,y/*0:011*/:(ys/*0:1*/ when _/*0:01*/,ys/*0:1*/ = us/*1:1*/ { - rule #0: _,ys = us +} end)&,y/*0:011*/:(ys/*0:1*/ when _/*0:01*/,ys/*0:1*/ = check/*2*/ us/*1:1*/ { + rule #0: _,ys = check us state 0: #0 <app> state 1 state 1: #0 @@ -1827,8 +1918,8 @@ state 4: #0 <var> state 5 state 5: #0 -} end)& if thunkp us/*0:1*/; accum u@(x/*0:0101*/,y/*0:011*/) us/*0:1*/ = x/*1:0101*/:xs/*0:01*/,y/*1:011*/:ys/*0:1*/ when xs/*0:01*/,ys/*0:1*/ = us/*0:1*/ { - rule #0: xs,ys = us +} end)& if thunkp us/*0:1*/; accum u@(x/*0:0101*/,y/*0:011*/) us/*0:1*/ = x/*1:0101*/:xs/*0:01*/,y/*1:011*/:ys/*0:1*/ when xs/*0:01*/,ys/*0:1*/ = check/*1*/ us/*0:1*/ { + rule #0: xs,ys = check us state 0: #0 <app> state 1 state 1: #0 @@ -1841,8 +1932,8 @@ <var> state 5 state 5: #0 } end; accum u/*0:01*/ _/*0:1*/ = throw (bad_tuple_value u/*0:01*/) { - rule #0: accum u@(x,y) us = x:(xs when xs,_ = us end)&,y:(ys when _,ys = us end)& if thunkp us - rule #1: accum u@(x,y) us = x:xs,y:ys when xs,ys = us end + rule #0: accum u@(x,y) us = x:(xs when xs,_ = check us end)&,y:(ys when _,ys = check us end)& if thunkp us + rule #1: accum u@(x,y) us = x:xs,y:ys when xs,ys = check us end rule #2: accum u _ = throw (bad_tuple_value u) state 0: #0 #1 #2 <var> state 1 @@ -1875,10 +1966,55 @@ state 14: #0 #1 #2 <var> state 15 state 15: #0 #1 #2 +}; check us@(_/*0:101*/,_/*0:11*/) = us/*0:1*/; check (foldr _/*0:1001*/ _/*0:101*/ us/*0:11*/) = throw (bad_list_value us/*0:11*/); check us/*0:1*/ = throw (bad_tuple_value us/*0:1*/) { + rule #0: check us@(_,_) = us + rule #1: check (foldr _ _ us) = throw (bad_list_value us) + rule #2: check us = throw (bad_tuple_value us) + state 0: #0 #1 #2 + <var> state 1 + <app> state 2 + state 1: #2 + state 2: #0 #1 #2 + <var> state 3 + <app> state 5 + state 3: #2 + <var> state 4 + state 4: #2 + state 5: #0 #1 #2 + <var> state 6 + , state 9 + <app> state 12 + state 6: #2 + <var> state 7 + state 7: #2 + <var> state 8 + state 8: #2 + state 9: #0 #2 + <var> state 10 + state 10: #0 #2 + <var> state 11 + state 11: #0 #2 + state 12: #1 #2 + <var> state 13 + foldr state 17 + state 13: #2 + <var> state 14 + state 14: #2 + <var> state 15 + state 15: #2 + <var> state 16 + state 16: #2 + state 17: #1 #2 + <var> state 18 + state 18: #1 #2 + <var> state 19 + state 19: #1 #2 + <var> state 20 + state 20: #1 #2 } end; unzip3 [] = [],[],[]; -unzip3 us@(_/*0:101*/:_/*0:11*/) = foldr accum/*0*/ ([],[],[]) us/*0:1*/ with accum u@(x/*0:0101*/,y/*0:01101*/,z/*0:0111*/) us/*0:1*/ = x/*0:0101*/:(xs/*0:01*/ when xs/*0:01*/,_/*0:101*/,_/*0:11*/ = us/*1:1*/ { - rule #0: xs,_,_ = us +unzip3 us@(_/*0:101*/:_/*0:11*/) = foldr accum/*0*/ ([],[],[]) us/*0:1*/ with accum u@(x/*0:0101*/,y/*0:01101*/,z/*0:0111*/) us/*0:1*/ = x/*0:0101*/:(xs/*0:01*/ when xs/*0:01*/,_/*0:101*/,_/*0:11*/ = check/*2*/ us/*1:1*/ { + rule #0: xs,_,_ = check us state 0: #0 <app> state 1 state 1: #0 @@ -1898,8 +2034,8 @@ state 8: #0 <var> state 9 state 9: #0 -} end)&,y/*0:01101*/:(ys/*0:101*/ when _/*0:01*/,ys/*0:101*/,_/*0:11*/ = us/*1:1*/ { - rule #0: _,ys,_ = us +} end)&,y/*0:01101*/:(ys/*0:101*/ when _/*0:01*/,ys/*0:101*/,_/*0:11*/ = check/*2*/ us/*1:1*/ { + rule #0: _,ys,_ = check us state 0: #0 <app> state 1 state 1: #0 @@ -1919,8 +2055,8 @@ state 8: #0 <var> state 9 state 9: #0 -} end)&,z/*0:0111*/:(zs/*0:11*/ when _/*0:01*/,_/*0:101*/,zs/*0:11*/ = us/*1:1*/ { - rule #0: _,_,zs = us +} end)&,z/*0:0111*/:(zs/*0:11*/ when _/*0:01*/,_/*0:101*/,zs/*0:11*/ = check/*2*/ us/*1:1*/ { + rule #0: _,_,zs = check us state 0: #0 <app> state 1 state 1: #0 @@ -1940,8 +2076,8 @@ state 8: #0 <var> state 9 state 9: #0 -} end)& if thunkp us/*0:1*/; accum u@(x/*0:0101*/,y/*0:01101*/,z/*0:0111*/) us/*0:1*/ = x/*1:0101*/:xs/*0:01*/,y/*1:01101*/:ys/*0:101*/,z/*1:0111*/:zs/*0:11*/ when xs/*0:01*/,ys/*0:101*/,zs/*0:11*/ = us/*0:1*/ { - rule #0: xs,ys,zs = us +} end)& if thunkp us/*0:1*/; accum u@(x/*0:0101*/,y/*0:01101*/,z/*0:0111*/) us/*0:1*/ = x/*1:0101*/:xs/*0:01*/,y/*1:01101*/:ys/*0:101*/,z/*1:0111*/:zs/*0:11*/ when xs/*0:01*/,ys/*0:101*/,zs/*0:11*/ = check/*1*/ us/*0:1*/ { + rule #0: xs,ys,zs = check us state 0: #0 <app> state 1 state 1: #0 @@ -1962,8 +2098,8 @@ <var> state 9 state 9: #0 } end; accum u/*0:01*/ _/*0:1*/ = throw (bad_tuple_value u/*0:01*/) { - rule #0: accum u@(x,y,z) us = x:(xs when xs,_,_ = us end)&,y:(ys when _,ys,_ = us end)&,z:(zs when _,_,zs = us end)& if thunkp us - rule #1: accum u@(x,y,z) us = x:xs,y:ys,z:zs when xs,ys,zs = us end + rule #0: accum u@(x,y,z) us = x:(xs when xs,_,_ = check us end)&,y:(ys when _,ys,_ = check us end)&,z:(zs when _,_,zs = check us end)& if thunkp us + rule #1: accum u@(x,y,z) us = x:xs,y:ys,z:zs when xs,ys,zs = check us end rule #2: accum u _ = throw (bad_tuple_value u) state 0: #0 #1 #2 <var> state 1 @@ -2022,4 +2158,69 @@ state 27: #0 #1 #2 <var> state 28 state 28: #0 #1 #2 +}; check us@(_/*0:101*/,_/*0:1101*/,_/*0:111*/) = us/*0:1*/; check (foldr _/*0:1001*/ _/*0:101*/ us/*0:11*/) = throw (bad_list_value us/*0:11*/); check us/*0:1*/ = throw (bad_tuple_value us/*0:1*/) { + rule #0: check us@(_,_,_) = us + rule #1: check (foldr _ _ us) = throw (bad_list_value us) + rule #2: check us = throw (bad_tuple_value us) + state 0: #0 #1 #2 + <var> state 1 + <app> state 2 + state 1: #2 + state 2: #0 #1 #2 + <var> state 3 + <app> state 5 + state 3: #2 + <var> state 4 + state 4: #2 + state 5: #0 #1 #2 + <var> state 6 + , state 9 + <app> state 22 + state 6: #2 + <var> state 7 + state 7: #2 + <var> state 8 + state 8: #2 + state 9: #0 #2 + <var> state 10 + state 10: #0 #2 + <var> state 11 + <app> state 12 + state 11: #2 + state 12: #0 #2 + <var> state 13 + <app> state 15 + state 13: #2 + <var> state 14 + state 14: #2 + state 15: #0 #2 + <var> state 16 + , state 19 + state 16: #2 + <var> state 17 + state 17: #2 + <var> state 18 + state 18: #2 + state 19: #0 #2 + <var> state 20 + state 20: #0 #2 + <var> state 21 + state 21: #0 #2 + state 22: #1 #2 + <var> state 23 + foldr state 27 + state 23: #2 + <var> state 24 + state 24: #2 + <var> state 25 + state 25: #2 + <var> state 26 + state 26: #2 + state 27: #1 #2 + <var> state 28 + state 28: #1 #2 + <var> state 29 + state 29: #1 #2 + <var> state 30 + state 30: #1 #2 } end; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-05 10:47:23
|
Revision: 715 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=715&view=rev Author: agraef Date: 2008-09-05 10:47:34 +0000 (Fri, 05 Sep 2008) Log Message: ----------- Improved error handling for refuted lazy matches in scanr and unzip operations. Modified Paths: -------------- pure/trunk/lib/prelude.pure Modified: pure/trunk/lib/prelude.pure =================================================================== --- pure/trunk/lib/prelude.pure 2008-09-05 09:52:31 UTC (rev 714) +++ pure/trunk/lib/prelude.pure 2008-09-05 10:47:34 UTC (rev 715) @@ -377,6 +377,15 @@ scanr f a xs@(_:_) = tick [] xs with /* Hack around with thunks to make these matches irrefutable. */ + tick zs (x:xs) = tack zs us when + ys = scanr f a xs&; + y = (case ys of + y:_ = y; + scanr _ _ ys = throw (bad_list_value ys); + _ = throw (bad_list_value ys); + end)&; + us = f x y : ys; + end if thunkp xs; tick zs (x:xs) = tack zs (f x (y when y:_ = ys end)&:ys when ys = scanr f a xs& end) if thunkp xs; = tick (x:zs) xs; @@ -390,8 +399,15 @@ scanr1 f [x] = [x]; scanr1 f xs@(_:_) = tick [] xs with - tick zs (x:xs) = tack zs (f x (y when y:_ = ys end)&:ys - when ys = scanr1 f xs& end) if thunkp xs; + tick zs (x:xs) = tack zs us when + ys = scanr1 f xs&; + y = (case ys of + y:_ = y; + scanr1 _ ys = throw (bad_list_value ys); + _ = throw (bad_list_value ys); + end)&; + us = f x y : ys; + end if thunkp xs; tick zs xs = case xs of [x] = tack zs [x]; x:xs = tick (x:zs) xs; @@ -575,18 +591,24 @@ unzip [] = [],[]; unzip us@(_:_) = foldr accum ([],[]) us with - accum u@(x,y) us = x:(xs when xs,_ = us end)&, - y:(ys when _,ys = us end)& if thunkp us; - = x:xs,y:ys when xs,ys = us end; + accum u@(x,y) us = x:(xs when xs,_ = check us end)&, + y:(ys when _,ys = check us end)& if thunkp us; + = x:xs,y:ys when xs,ys = check us end; accum u _ = throw (bad_tuple_value u); + check us@(_,_) = us; + check (foldr _ _ us) = throw (bad_list_value us); + check us = throw (bad_tuple_value us); end; unzip3 [] = [],[],[]; unzip3 us@(_:_) = foldr accum ([],[],[]) us with - accum u@(x,y,z) us = x:(xs when xs,_,_ = us end)&, - y:(ys when _,ys,_ = us end)&, - z:(zs when _,_,zs = us end)& if thunkp us; - = x:xs,y:ys,z:zs when xs,ys,zs = us end; + accum u@(x,y,z) us = x:(xs when xs,_,_ = check us end)&, + y:(ys when _,ys,_ = check us end)&, + z:(zs when _,_,zs = check us end)& if thunkp us; + = x:xs,y:ys,z:zs when xs,ys,zs = check us end; accum u _ = throw (bad_tuple_value u); + check us@(_,_,_) = us; + check (foldr _ _ us) = throw (bad_list_value us); + check us = throw (bad_tuple_value us); end; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-05 09:52:20
|
Revision: 714 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=714&view=rev Author: agraef Date: 2008-09-05 09:52:31 +0000 (Fri, 05 Sep 2008) Log Message: ----------- Comment change. Modified Paths: -------------- pure/trunk/lib/prelude.pure Modified: pure/trunk/lib/prelude.pure =================================================================== --- pure/trunk/lib/prelude.pure 2008-09-05 09:51:32 UTC (rev 713) +++ pure/trunk/lib/prelude.pure 2008-09-05 09:52:31 UTC (rev 714) @@ -440,7 +440,7 @@ lazy in Pure, because it's also used for arithmetic operations. Using it here would make foldr (and hence cat) eager. Therefore we use our own concatenation operation here, which properly deals with the case that ys - is an infinite stream. */ + is an infinite stream when applied recursively. */ []+ys = ys; xs@(_:_)+ys = tick [] xs ys; tick zs (x:xs) ys = tack (x:zs) ((xs+ys)&) if thunkp xs; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-05 09:51:23
|
Revision: 713 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=713&view=rev Author: agraef Date: 2008-09-05 09:51:32 +0000 (Fri, 05 Sep 2008) Log Message: ----------- Comment change. Modified Paths: -------------- pure/trunk/lib/prelude.pure Modified: pure/trunk/lib/prelude.pure =================================================================== --- pure/trunk/lib/prelude.pure 2008-09-05 09:38:43 UTC (rev 712) +++ pure/trunk/lib/prelude.pure 2008-09-05 09:51:32 UTC (rev 713) @@ -439,7 +439,8 @@ /* Unfortunately, the global list concatenation operator (+) isn't fully lazy in Pure, because it's also used for arithmetic operations. Using it here would make foldr (and hence cat) eager. Therefore we use our own - lazy concatenation operation here. */ + concatenation operation here, which properly deals with the case that ys + is an infinite stream. */ []+ys = ys; xs@(_:_)+ys = tick [] xs ys; tick zs (x:xs) ys = tack (x:zs) ((xs+ys)&) if thunkp xs; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-05 09:38:35
|
Revision: 712 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=712&view=rev Author: agraef Date: 2008-09-05 09:38:43 +0000 (Fri, 05 Sep 2008) Log Message: ----------- Bugfixes. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/runtime.cc Added Paths: ----------- pure/trunk/test/test023.log pure/trunk/test/test023.pure Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-09-05 02:15:43 UTC (rev 711) +++ pure/trunk/ChangeLog 2008-09-05 09:38:43 UTC (rev 712) @@ -1,5 +1,8 @@ 2008-09-05 Albert Graef <Dr....@t-...> + * runtime.cc (pure_force): Fix a rather obscure segfault in the + thunk implementation. See also test/test023.pure. + * lexer.ll: Warn about used identifiers which are also interactive commands. Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-09-05 02:15:43 UTC (rev 711) +++ pure/trunk/runtime.cc 2008-09-05 09:38:43 UTC (rev 712) @@ -1438,6 +1438,7 @@ // that recursively if (ret->tag == 0 && ret->data.clos && ret->data.clos->n == 0) ret = pure_force(pure_new_internal(ret)); + pure_new_internal(ret); // memoize the result assert(x!=ret); pure_free_clos(x); @@ -1458,7 +1459,7 @@ x->data.clos = pure_copy_clos(x->data.clos); break; } - pure_freenew(ret); + pure_free_internal(ret); return x; } else { #if DEBUG>2 Added: pure/trunk/test/test023.log =================================================================== --- pure/trunk/test/test023.log (rev 0) +++ pure/trunk/test/test023.log 2008-09-05 09:38:43 UTC (rev 712) @@ -0,0 +1,47 @@ +odd x/*0:1*/ = x/*0:1*/ mod 2; +{ + rule #0: odd x = x mod 2 + state 0: #0 + <var> state 1 + state 1: #0 +} +{ + rule #0: x = 1..1e+307*1e+307 + state 0: #0 + <var> state 1 + state 1: #0 +} +let x = 1..1e+307*1e+307; +{ + rule #0: y = filter odd x + state 0: #0 + <var> state 1 + state 1: #0 +} +let y = filter odd x; +{ + rule #0: z = zip x y + state 0: #0 + <var> state 1 + state 1: #0 +} +let z = zip x y; +{ + rule #0: u,v = unzip z + 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 +} +let u,v = unzip z; +list (take 10 u); +[1,2,3,4,5,6,7,8,9,10] +list (take 10 v); +[1,3,5,7,9,11,13,15,17,19] Added: pure/trunk/test/test023.pure =================================================================== --- pure/trunk/test/test023.pure (rev 0) +++ pure/trunk/test/test023.pure 2008-09-05 09:38:43 UTC (rev 712) @@ -0,0 +1,9 @@ +// thunk regression test (cf. r712) + +odd x = x mod 2; + +let x = 1..inf; let y = filter odd x; let z = zip x y; +let u,v = unzip z; + +list (take 10 u); +list (take 10 v); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-05 02:15:33
|
Revision: 711 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=711&view=rev Author: agraef Date: 2008-09-05 02:15:43 +0000 (Fri, 05 Sep 2008) Log Message: ----------- Bugfixes. Modified Paths: -------------- pure/trunk/test/test020.log pure/trunk/test/test020.pure pure/trunk/test/test021.log pure/trunk/test/test021.pure Modified: pure/trunk/test/test020.log =================================================================== --- pure/trunk/test/test020.log 2008-09-05 02:11:39 UTC (rev 710) +++ pure/trunk/test/test020.log 2008-09-05 02:15:43 UTC (rev 711) @@ -43,14 +43,14 @@ check (f/*0:0101*/,x/*0:01101*/,y/*0:0111*/) (g@_/*0:100*/ u/*0:101*/ v/*0:11*/) = __failed__ if f/*0:0101*/===g/*0:100*/&&x/*0:01101*/===u/*0:101*/&&y/*0:0111*/===v/*0:11*/; check (f/*0:0101*/,x/*0:011*/) (g@_/*0:10*/ u/*0:11*/) = __failed__ if f/*0:0101*/===g/*0:10*/&&x/*0:011*/===u/*0:11*/; check _/*0:01*/ z/*0:1*/ = z/*0:1*/; -format (f/*0:101*/,x/*0:1101*/,y/*0:11101*/,z/*0:1111*/) = str f/*0:101*/+","+show x/*0:1101*/+","+show y/*0:11101*/+","+show z/*0:1111*/; -format (f/*0:101*/,x/*0:1101*/,z/*0:111*/) = str f/*0:101*/+","+show x/*0:1101*/+","+show z/*0:111*/; -show x/*0:1*/::double = str x/*0:1*/ if infp x/*0:1*/||nanp x/*0:1*/; -show x/*0:1*/::double = sprintf double_format 0.0 if x/*0:1*/==0.0; -show x/*0:1*/::double = sprintf double_format x/*0:1*/; -show (x/*0:101*/+:y/*0:11*/) = show x/*0:101*/+"+:"+show y/*0:11*/; -show (x/*0:101*/<:y/*0:11*/) = show x/*0:101*/+"<:"+show y/*0:11*/; -show x/*0:1*/ = str x/*0:1*/; +format (f/*0:101*/,x/*0:1101*/,y/*0:11101*/,z/*0:1111*/) = str f/*0:101*/+","+print x/*0:1101*/+","+print y/*0:11101*/+","+print z/*0:1111*/; +format (f/*0:101*/,x/*0:1101*/,z/*0:111*/) = str f/*0:101*/+","+print x/*0:1101*/+","+print z/*0:111*/; +print x/*0:1*/::double = str x/*0:1*/ if infp x/*0:1*/||nanp x/*0:1*/; +print x/*0:1*/::double = sprintf double_format 0.0 if x/*0:1*/==0.0; +print x/*0:1*/::double = sprintf double_format x/*0:1*/; +print (x/*0:101*/+:y/*0:11*/) = print x/*0:101*/+"+:"+print y/*0:11*/; +print (x/*0:101*/<:y/*0:11*/) = print x/*0:101*/+"<:"+print y/*0:11*/; +print x/*0:1*/ = str x/*0:1*/; tests = puts "*** UNARY ***"$$do (\f/*0:*/ -> catmap (\x/*0:*/ -> [test (f/*1:*/,x/*0:*/)] { rule #0: x = [test (f,x)] state 0: #0 @@ -168,8 +168,8 @@ state 44: #0 #1 #2 #3 } { - rule #0: format (f,x,y,z) = str f+","+show x+","+show y+","+show z - rule #1: format (f,x,z) = str f+","+show x+","+show z + rule #0: format (f,x,y,z) = str f+","+print x+","+print y+","+print z + rule #1: format (f,x,z) = str f+","+print x+","+print z state 0: #0 #1 <app> state 1 state 1: #0 #1 @@ -246,12 +246,12 @@ state 15: #0 #1 } { - rule #0: show x::double = str x if infp x||nanp x - rule #1: show x::double = sprintf double_format 0.0 if x==0.0 - rule #2: show x::double = sprintf double_format x - rule #3: show (x+:y) = show x+"+:"+show y - rule #4: show (x<:y) = show x+"<:"+show y - rule #5: show x = str x + rule #0: print x::double = str x if infp x||nanp x + rule #1: print x::double = sprintf double_format 0.0 if x==0.0 + rule #2: print x::double = sprintf double_format x + rule #3: print (x+:y) = print x+"+:"+print y + rule #4: print (x<:y) = print x+"<:"+print y + rule #5: print x = str x state 0: #0 #1 #2 #3 #4 #5 <var> state 1 <var>::double state 2 Modified: pure/trunk/test/test020.pure =================================================================== --- pure/trunk/test/test020.pure 2008-09-05 02:11:39 UTC (rev 710) +++ pure/trunk/test/test020.pure 2008-09-05 02:15:43 UTC (rev 711) @@ -43,19 +43,19 @@ check (f,x) (g@_ u) = __failed__ if f===g && x===u; check _ z = z otherwise; -format (f,x,y,z) = str f+","+show x+","+show y+","+show z; -format (f,x,z) = str f+","+show x+","+show z; +format (f,x,y,z) = str f+","+print x+","+print y+","+print z; +format (f,x,z) = str f+","+print x+","+print z; -show x::double +print x::double = str x if infp x || nanp x; // Windoze compatibility // Kludge: Some systems have -0.0, some don't, on some it's broken. Simply // ignore the sign of floating point zeros for now. = sprintf double_format 0.0 if x==0.0; = sprintf double_format x otherwise; -show (x+:y) = show x+"+:"+show y; -show (x<:y) = show x+"<:"+show y; -show x = str x otherwise; +print (x+:y) = print x+"+:"+print y; +print (x<:y) = print x+"<:"+print y; +print x = str x otherwise; tests = puts "*** UNARY ***" $$ void [test (f,x); f=f; x=x] $$ Modified: pure/trunk/test/test021.log =================================================================== --- pure/trunk/test/test021.log 2008-09-05 02:11:39 UTC (rev 710) +++ pure/trunk/test/test021.log 2008-09-05 02:15:43 UTC (rev 711) @@ -5,14 +5,14 @@ check (f/*0:0101*/,x/*0:01101*/,y/*0:0111*/) (g@_/*0:100*/ u/*0:101*/ v/*0:11*/) = __failed__ if f/*0:0101*/===g/*0:100*/&&x/*0:01101*/===u/*0:101*/&&y/*0:0111*/===v/*0:11*/; check (f/*0:0101*/,x/*0:011*/) (g@_/*0:10*/ u/*0:11*/) = __failed__ if f/*0:0101*/===g/*0:10*/&&x/*0:011*/===u/*0:11*/; check _/*0:01*/ z/*0:1*/ = z/*0:1*/; -format (f/*0:101*/,x/*0:1101*/,y/*0:11101*/,z/*0:1111*/) = str f/*0:101*/+","+show x/*0:1101*/+","+show y/*0:11101*/+","+show z/*0:1111*/; -format (f/*0:101*/,x/*0:1101*/,z/*0:111*/) = str f/*0:101*/+","+show x/*0:1101*/+","+show z/*0:111*/; -show x/*0:1*/::double = str x/*0:1*/ if infp x/*0:1*/||nanp x/*0:1*/; -show x/*0:1*/::double = sprintf double_format 0.0 if x/*0:1*/==0.0; -show x/*0:1*/::double = sprintf double_format x/*0:1*/; -show (x/*0:101*/+:y/*0:11*/) = show x/*0:101*/+"+:"+show y/*0:11*/; -show (x/*0:101*/<:y/*0:11*/) = show x/*0:101*/+"<:"+show y/*0:11*/; -show x/*0:1*/ = str x/*0:1*/; +format (f/*0:101*/,x/*0:1101*/,y/*0:11101*/,z/*0:1111*/) = str f/*0:101*/+","+print x/*0:1101*/+","+print y/*0:11101*/+","+print z/*0:1111*/; +format (f/*0:101*/,x/*0:1101*/,z/*0:111*/) = str f/*0:101*/+","+print x/*0:1101*/+","+print z/*0:111*/; +print x/*0:1*/::double = str x/*0:1*/ if infp x/*0:1*/||nanp x/*0:1*/; +print x/*0:1*/::double = sprintf double_format 0.0 if x/*0:1*/==0.0; +print x/*0:1*/::double = sprintf double_format x/*0:1*/; +print (x/*0:101*/+:y/*0:11*/) = print x/*0:101*/+"+:"+print y/*0:11*/; +print (x/*0:101*/<:y/*0:11*/) = print x/*0:101*/+"<:"+print y/*0:11*/; +print x/*0:1*/ = str x/*0:1*/; tests = puts "*** EXACT/INEXACT ***"$$do test (catmap (\op/*0:*/ -> catmap (\a/*0:*/ -> [(op/*1:*/,2,a/*0:*/)] { rule #0: a = [(op,2,a)] state 0: #0 @@ -150,8 +150,8 @@ state 44: #0 #1 #2 #3 } { - rule #0: format (f,x,y,z) = str f+","+show x+","+show y+","+show z - rule #1: format (f,x,z) = str f+","+show x+","+show z + rule #0: format (f,x,y,z) = str f+","+print x+","+print y+","+print z + rule #1: format (f,x,z) = str f+","+print x+","+print z state 0: #0 #1 <app> state 1 state 1: #0 #1 @@ -228,12 +228,12 @@ state 15: #0 #1 } { - rule #0: show x::double = str x if infp x||nanp x - rule #1: show x::double = sprintf double_format 0.0 if x==0.0 - rule #2: show x::double = sprintf double_format x - rule #3: show (x+:y) = show x+"+:"+show y - rule #4: show (x<:y) = show x+"<:"+show y - rule #5: show x = str x + rule #0: print x::double = str x if infp x||nanp x + rule #1: print x::double = sprintf double_format 0.0 if x==0.0 + rule #2: print x::double = sprintf double_format x + rule #3: print (x+:y) = print x+"+:"+print y + rule #4: print (x<:y) = print x+"<:"+print y + rule #5: print x = str x state 0: #0 #1 #2 #3 #4 #5 <var> state 1 <var>::double state 2 Modified: pure/trunk/test/test021.pure =================================================================== --- pure/trunk/test/test021.pure 2008-09-05 02:11:39 UTC (rev 710) +++ pure/trunk/test/test021.pure 2008-09-05 02:15:43 UTC (rev 711) @@ -18,19 +18,19 @@ check (f,x) (g@_ u) = __failed__ if f===g && x===u; check _ z = z otherwise; -format (f,x,y,z) = str f+","+show x+","+show y+","+show z; -format (f,x,z) = str f+","+show x+","+show z; +format (f,x,y,z) = str f+","+print x+","+print y+","+print z; +format (f,x,z) = str f+","+print x+","+print z; -show x::double +print x::double = str x if infp x || nanp x; // Windoze compatibility // Kludge: Some systems have -0.0, some don't, on some it's broken. Simply // ignore the sign of floating point zeros for now. = sprintf double_format 0.0 if x==0.0; = sprintf double_format x otherwise; -show (x+:y) = show x+"+:"+show y; -show (x<:y) = show x+"<:"+show y; -show x = str x otherwise; +print (x+:y) = print x+"+:"+print y; +print (x<:y) = print x+"<:"+print y; +print x = str x otherwise; tests = puts "*** EXACT/INEXACT ***" $$ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-05 02:11:29
|
Revision: 710 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=710&view=rev Author: agraef Date: 2008-09-05 02:11:39 +0000 (Fri, 05 Sep 2008) Log Message: ----------- Update documentation. Modified Paths: -------------- pure/trunk/pure.1.in Modified: pure/trunk/pure.1.in =================================================================== --- pure/trunk/pure.1.in 2008-09-05 02:01:42 UTC (rev 709) +++ pure/trunk/pure.1.in 2008-09-05 02:11:39 UTC (rev 710) @@ -1897,9 +1897,11 @@ See the DEFINITION LEVELS section below for details. .PP Note that these special commands are only recognized at the beginning of the -interactive command line. (Thus you can escape an identifier at the beginning -of the command line, which looks like a command, by prefixing it with a space -or by wrapping it up in parentheses.) +interactive command line (they are not reserved keywords of the Pure +language). Thus it's possible to ``escape'' identifiers looking like commands +by entering a space at the start of the line. However, the compiler also warns +you about identifiers which might be mistaken as command names, so that you +can avoid this kind of problem. .PP Some commands which are especially important for effective operation of the interpreter are discussed in more detail in the following sections. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-05 02:01:32
|
Revision: 709 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=709&view=rev Author: agraef Date: 2008-09-05 02:01:42 +0000 (Fri, 05 Sep 2008) Log Message: ----------- Warn about used identifiers which are also interactive commands. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/lexer.ll Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-09-05 01:12:59 UTC (rev 708) +++ pure/trunk/ChangeLog 2008-09-05 02:01:42 UTC (rev 709) @@ -1,5 +1,8 @@ 2008-09-05 Albert Graef <Dr....@t-...> + * lexer.ll: Warn about used identifiers which are also interactive + commands. + * printer.cc: Changed <<...>> syntax for "external" objects such as closures, thunks and pointers to #<...> syntax pilfered from Scheme. This is less likely to be mistaken for a valid Pure Modified: pure/trunk/lexer.ll =================================================================== --- pure/trunk/lexer.ll 2008-09-05 01:12:59 UTC (rev 708) +++ pure/trunk/lexer.ll 2008-09-05 02:01:42 UTC (rev 709) @@ -215,6 +215,27 @@ free(matches); } } + +static void check(const yy::location& l, const char* s) +{ + static set<string> done; + const char *name; + size_t i = 0; + while ((name = commands[i++])) + /* We warn about each identifier at most once. FIXME: We should also check + whether the interpreter is running in (global) interactive mode, but at + present this information isn't available before we actually enter the + interactive loop, when all source files from the command line have + already been processed. */ + if (strcmp(name, s) == 0 && done.find(s) == done.end()) { + assert(interpreter::g_interp); + interpreter& interp = *interpreter::g_interp; + interp.warning(l, "warning: identifier '"+string(s)+ + "' is also an interpreter command"); + done.insert(s); + return; + } +} %} %option noyywrap nounput debug @@ -257,7 +278,7 @@ <comment>[\n]+ yylloc->lines(yyleng); yylloc->step(); <comment>"*"+"/" yylloc->step(); BEGIN(INITIAL); -<xdecl>{id} yylval->sval = new string(yytext); return token::ID; +<xdecl>{id} check(*yylloc, yytext); yylval->sval = new string(yytext); return token::ID; <xdecl>[()*,=] return yy::parser::token_type(yytext[0]); <xdecl>"//".* yylloc->step(); <xdecl>"/*" BEGIN(xdecl_comment); @@ -275,7 +296,7 @@ <xdecl_comment>[\n]+ yylloc->lines(yyleng); yylloc->step(); <xdecl_comment>"*"+"/" yylloc->step(); BEGIN(xdecl); -<xusing>{id} yylval->sval = new string(yytext); return token::ID; +<xusing>{id} check(*yylloc, yytext); yylval->sval = new string(yytext); return token::ID; <xusing>, return yy::parser::token_type(yytext[0]); <xusing>"//".* yylloc->step(); <xusing>"/*" BEGIN(xusing_comment); @@ -930,6 +951,7 @@ with return token::WITH; using BEGIN(xusing); return token::USING; {id} { + check(*yylloc, yytext); if (interp.declare_op) { yylval->sval = new string(yytext); return token::ID; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-05 01:12:49
|
Revision: 708 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=708&view=rev Author: agraef Date: 2008-09-05 01:12:59 +0000 (Fri, 05 Sep 2008) Log Message: ----------- Update documentation. Modified Paths: -------------- pure/trunk/pure.1.in Modified: pure/trunk/pure.1.in =================================================================== --- pure/trunk/pure.1.in 2008-09-05 00:59:21 UTC (rev 707) +++ pure/trunk/pure.1.in 2008-09-05 01:12:59 UTC (rev 708) @@ -614,7 +614,7 @@ .nf > foo x = bar \fBwith\fP bar y = x+y \fBend\fP; > \fBlet\fP f = foo 99; f; -{{closure bar}} +#<closure bar> > f 10, f 20; 109,119 .fi @@ -800,7 +800,7 @@ .nf > fibs = 0L : 1L : zipwith (+) fibs (tail fibs) &; > fibs; -0L:1L:{{thunk 0xb5f875e8}} +0L:1L:#<thunk 0xb5f875e8> .fi .PP Note the `&' on the tail of the list. This turns `fibs' into a stream, which @@ -819,7 +819,7 @@ .sp .nf > take 10 fibs; -0L:1L:{{thunk 0xb5f87630}} +0L:1L:#<thunk 0xb5f87630> .fi .PP Hmm, not much progress there, but that's just how streams work (or rather @@ -843,7 +843,7 @@ .fi .PP Well, this naive definition of the Fibonacci stream works, but it's awfully -inefficient. In fact, it takes exponential running time to determine the +slow. In fact, it takes exponential running time to determine the .IR n th member of the sequence, because of the two recursive calls to `fibs' on the right-hand side. This defect soon becomes rather annoying if we access larger @@ -864,10 +864,10 @@ > \fBstats off\fP .fi .PP -It's quite apparent that the ratios between successive running times converge -to the golden ratio from above (which is of course no accident!). So, assuming -a fast computer which can produce the first stream element in a nanosecond, a -conservative estimate of the time needed to compute just the 128th Fibonacci +It's quite apparent that the ratios between successive running times are about +the golden ratio (which is of course no accident!). So, assuming a fast +computer which can produce the head element of a stream in just a nanosecond, +a conservative estimate of the time needed to compute just the 128th Fibonacci number would already exceed the current age of the universe by some 29.6%, if done this way. It goes without saying that this kind of algorithm won't even pass muster in a freshman course. @@ -904,11 +904,11 @@ > \fBclear\fP fibs > \fBlet\fP fibs = fix (\ef -> 0L : 1L : zipwith (+) f (tail f) &); > fibs; -0L:1L:{{thunk 0xb58d8ae0}} +0L:1L:#<thunk 0xb58d8ae0> > takel 10 fibs; [0L,1L,1L,2L,3L,5L,8L,13L,21L,34L] > fibs; -0L:1L:1L:2L:3L:5L:8L:13L:21L:34L:{{thunk 0xb4ce5d30}} +0L:1L:1L:2L:3L:5L:8L:13L:21L:34L:#<thunk 0xb4ce5d30> .fi .PP As you can see, the invokation of our `takel' function forced the @@ -960,7 +960,7 @@ .sp .nf > \fBlet\fP rats = [m,n-m; n=2..inf; m=1..n-1; gcd m (n-m) == 1]; rats; -(1,1):{{thunk 0xb5fd08b8}} +(1,1):#<thunk 0xb5fd08b8> > takel 10 rats; [(1,1),(1,2),(2,1),(1,3),(3,1),(1,4),(2,3),(3,2),(4,1),(1,5)] .fi This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-05 00:59:11
|
Revision: 707 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=707&view=rev Author: agraef Date: 2008-09-05 00:59:21 +0000 (Fri, 05 Sep 2008) Log Message: ----------- Change print syntax of external objects, 2nd attempt. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/printer.cc pure/trunk/test/test004.log Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-09-05 00:44:33 UTC (rev 706) +++ pure/trunk/ChangeLog 2008-09-05 00:59:21 UTC (rev 707) @@ -1,5 +1,10 @@ 2008-09-05 Albert Graef <Dr....@t-...> + * printer.cc: Changed <<...>> syntax for "external" objects such + as closures, thunks and pointers to #<...> syntax pilfered from + Scheme. This is less likely to be mistaken for a valid Pure + expression. + * pure.cc, lexer.ll: Renamed the interactive 'list' command to 'show', as suggested by John Cowan. This hopefully puts an end to inadvertent execution of that command, since 'show' is no prelude Modified: pure/trunk/printer.cc =================================================================== --- pure/trunk/printer.cc 2008-09-05 00:44:33 UTC (rev 706) +++ pure/trunk/printer.cc 2008-09-05 00:59:21 UTC (rev 707) @@ -166,7 +166,7 @@ static ostream& printx(ostream& os, const expr& x, bool pat, bool aspat) { char buf[64]; - if (x.is_null()) return os << "{{NULL}}"; + if (x.is_null()) return os << "#<NULL>"; //os << "{" << x.refc() << "}"; // handle "as" patterns if (aspat && x.astag()>0) { @@ -243,7 +243,7 @@ return os; } case EXPR::PTR: - return os << "{{pointer " << x.pval() << "}}"; + return os << "#<pointer " << x.pval() << ">"; case EXPR::APP: { expr u, v, w, y; exprl xs; @@ -665,7 +665,7 @@ return os; } case EXPR::PTR: - return os << "{{pointer " << x->data.p << "}}"; + return os << "#<pointer " << x->data.p << ">"; case EXPR::APP: { list<const pure_expr*> xs; prec_t p; @@ -760,11 +760,11 @@ default: { if (x->tag == 0) { const char *s = (x->data.clos && x->data.clos->n==0)?"thunk":"closure"; - return os << "{{" << s << " " << (void*)x << "}}"; + return os << "#<" << s << " " << (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 << "}}"; + return os << "#<closure " << sym.s << ">"; if (sym.prec < 10) return os << '(' << sym.s << ')'; else Modified: pure/trunk/test/test004.log =================================================================== --- pure/trunk/test/test004.log 2008-09-05 00:44:33 UTC (rev 706) +++ pure/trunk/test/test004.log 2008-09-05 00:59:21 UTC (rev 707) @@ -35,15 +35,15 @@ foo 99; 99 foo2 99; -{{closure bar}} 100 +#<closure bar> 100 foo2 98; -{{closure bar}} 98 +#<closure bar> 98 foo3 99; -{{closure bar}} +#<closure bar> foo3 99 98; -{{closure bar}} 98 +#<closure bar> 98 foo3 99 99; -{{closure 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-09-05 00:44:23
|
Revision: 706 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=706&view=rev Author: agraef Date: 2008-09-05 00:44:33 +0000 (Fri, 05 Sep 2008) Log Message: ----------- Update documentation. Modified Paths: -------------- pure/trunk/pure.1.in Modified: pure/trunk/pure.1.in =================================================================== --- pure/trunk/pure.1.in 2008-09-04 23:13:50 UTC (rev 705) +++ pure/trunk/pure.1.in 2008-09-05 00:44:33 UTC (rev 706) @@ -192,7 +192,7 @@ modules imported through a .B using clause. As a remedy, you can use the interactive -.B list +.B show command (see the INTERACTIVE USAGE section below) to list definitions along with additional debugging information. .SH PURE OVERVIEW @@ -738,7 +738,7 @@ > pi; 3.14159265358979 > foo x = 2*pi*x; -> \fBlist\fP foo +> \fBshow\fP foo foo x = 2*3.14159265358979*x; > foo 1; 6.28318530717958 @@ -765,7 +765,7 @@ expression the comprehension expanded to: .sp .nf -> \fBlist\fP primes +> \fBshow\fP primes primes n = sieve (2..n) \fBwith\fP sieve [] = []; sieve (p:qs) = p:sieve (catmap (\eq -> if q mod p then [q] else []) qs) \fBend\fP; .fi @@ -828,16 +828,10 @@ forcing its evaluation: .sp .nf -> (list) (take 10 fibs); +> list (take 10 fibs); [0L,1L,1L,2L,3L,5L,8L,13L,21L,34L] .fi .PP -(Note that we typed `(list)' instead of just `list' here, so that the -interpreter does not mistake this for the interactive -.B list -command. This is only necessary at the interactive command prompt, see -INTERACTIVE USAGE.) -.PP For interactive usage it's often convenient to define an eager variation of `take' which combines `take' and `list'. Let's do this now, so that we can use this operation in the following examples. @@ -876,7 +870,7 @@ conservative estimate of the time needed to compute just the 128th Fibonacci number would already exceed the current age of the universe by some 29.6%, if done this way. It goes without saying that this kind of algorithm won't even -pass muster in a computer science freshman course. +pass muster in a freshman course. .PP So let's get back to the drawing board. One nice trick of the trade is to have the @@ -893,7 +887,7 @@ in Pure and defined in the prelude as follows: .sp .nf -> \fBlist\fP fix +> \fBshow\fP fix fix f = y y \fBwhen\fP y = \ex -> f (x x&) \fBend\fP; .fi .PP @@ -952,7 +946,7 @@ which have been adopted from Haskell. In fact, infinite arithmetic progressions are implemented in terms of `iterate'. The `repeat' function just repeats its argument, and `cycle' cycles through the elements of the given -list until hell freezes over: +list: .sp .nf > takel 10 (repeat 1); @@ -1158,7 +1152,7 @@ .nf > \fBdef\fP succ x = x+1; > foo x::int = succ (succ x); -> \fBlist\fP foo +> \fBshow\fP foo foo x::int = x+1+1; .fi .PP @@ -1181,7 +1175,7 @@ .sp .nf > foo x = bar $ bar $ 2*x; -> \fBlist\fP foo +> \fBshow\fP foo foo x = bar (bar (2*x)); .fi .PP @@ -1205,7 +1199,7 @@ > \fBusing\fP system; > f = [printf "%g\en" (2^x+1); x=1..5; x mod 2]; > g = void [printf "%g\en" (2^x+1); x=1..5; x mod 2]; -> \fBlist\fP f g +> \fBshow\fP f g f = catmap (\ex -> if x mod 2 then [printf "%g\n" (2^x+1)] else []) (1..5); g = do (\ex -> if x mod 2 then [printf "%g\n" (2^x+1)] else []) (1..5); .fi @@ -1228,7 +1222,7 @@ .sp .nf > u = void [puts $ str (x,y); x=1..2; y=1..3]; -> \fBlist\fP u +> \fBshow\fP u u = do (\ex -> catmap (\ey -> [puts (str (x,y))]) (1..3)) (1..2); .fi .PP @@ -1237,7 +1231,7 @@ .sp .nf > v = void [void [puts $ str (x,y); y=1..3]; x=1..2]; -> \fBlist\fP v +> \fBshow\fP v v = do (\ex -> [do (\ey -> [puts (str (x,y))]) (1..3)]) (1..2); .fi .PP @@ -1255,7 +1249,7 @@ > \fBdef\fP foo (bar x) = foo x+1; > \fBdef\fP foo x = x; > baz = foo (bar (bar (bar x))); -> \fBlist\fP baz +> \fBshow\fP baz baz = x+1+1+1; .fi .PP @@ -1845,10 +1839,6 @@ .BR man (1) with the given arguments. .TP -.B "list \fR[\fIoption\fP ...]\fP \fR[\fIsymbol\fP ...]\fP" -List defined symbols in various formats. See the LIST COMMAND section below -for details. -.TP .B "ls \fR[\fIargs\fP]\fP" List files (shell \fBls\fP(1) command). .TP @@ -1891,6 +1881,10 @@ (or the beginning of the interactive session). See the DEFINITION LEVELS section below for details. .TP +.B "show \fR[\fIoption\fP ...]\fP \fR[\fIsymbol\fP ...]\fP" +Show the definitions of symbols in various formats. See the SHOW COMMAND +section below for details. +.TP .B "stats \fR[on|off]\fP" Enables (default) or disables ``stats'' mode, in which various statistics are printed after an expression has been evaluated. Currently, this just prints @@ -1909,12 +1903,12 @@ .PP Some commands which are especially important for effective operation of the interpreter are discussed in more detail in the following sections. -.SH LIST COMMAND +.SH SHOW COMMAND In interactive mode, the -.B list +.B show command can be used to obtain information about defined symbols in various formats. This command recognizes the following options. Options may be -combined, thus, e.g., \fBlist\fP -tvl is the same as \fBlist\fP -t -v -l. +combined, thus, e.g., \fBshow\fP -tvl is the same as \fBshow\fP -t -v -l. .TP .B -a Disassembles pattern matching automata. Works like the @@ -1999,7 +1993,7 @@ prelude), simply say: .sp .nf -> \fBlist\fP +> \fBshow\fP .fi .PP This may produce quite a lot of output, depending on which scripts are @@ -2007,7 +2001,7 @@ variable symbols along with their current values (using the ``long format''): .sp .nf -> \fBlist\fP -lv +> \fBshow\fP -lv argc var argc = 0; argv var argv = []; sysinfo var sysinfo = "i686-pc-linux-gnu"; @@ -2018,12 +2012,12 @@ If you're like me then you'll frequently have to look up how some operations are defined. No sweat, with the Pure interpreter there's no need to dive into the sources, the -.B list +.B show command can easily do it for you. For instance, here's how you can list the definitions of all ``fold-left'' operations from the prelude in one go: .sp .nf -> \fBlist\fP -g foldl* +> \fBshow\fP -g foldl* foldl f a s::string = foldl f a (chars s); foldl f a [] = a; foldl f a (x:xs) = foldl f (f a x) xs; @@ -2050,14 +2044,14 @@ .nf > foo (x:xs) = x+foo xs; > foo [] = 0; -> \fBlist\fP -t +> \fBshow\fP -t foo (x:xs) = x+foo xs; foo [] = 0; > foo (1..10); 55 > \fBclear\fP This will clear all temporary definitions at level #1. Continue (y/n)? y -> \fBlist\fP foo +> \fBshow\fP foo > foo (1..10); foo [1,2,3,4,5,6,7,8,9,10] .fi @@ -2076,7 +2070,7 @@ .nf > foo (x:xs) = x+foo xs; > foo [] = 0; -> \fBlist\fP foo +> \fBshow\fP foo foo (x:xs) = x+foo xs; foo [] = 0; > foo (1..10); @@ -2085,7 +2079,7 @@ save: now at temporary definitions level #2 > \fBoverride\fP > foo (x:xs) = x*foo xs; -> \fBlist\fP foo +> \fBshow\fP foo foo (x:xs) = x*foo xs; foo (x:xs) = x+foo xs; foo [] = 0; @@ -2102,7 +2096,7 @@ .sp .nf > foo [] = 1; -> \fBlist\fP foo +> \fBshow\fP foo foo (x:xs) = x*foo xs; foo [] = 1; foo (x:xs) = x+foo xs; @@ -2123,7 +2117,7 @@ This will clear all temporary definitions at level #2. Continue (y/n)? y clear: now at temporary definitions level #1 clear: override mode is on -> \fBlist\fP foo +> \fBshow\fP foo foo (x:xs) = x+foo xs; foo [] = 0; > foo (1..10); @@ -2339,7 +2333,7 @@ > \fBextern\fP double atan(double); > \fBconst\fP pi = 4*atan 1.0; > foo x = 2*pi*x; -> \fBlist\fP foo +> \fBshow\fP foo foo x = 2*3.14159265358979*x; .fi .PP @@ -2355,7 +2349,7 @@ > \fBclear\fP pi foo > \fBdef\fP pi = 4*atan 1.0; > foo x = 2*pi*x; -> \fBlist\fP foo +> \fBshow\fP foo foo x = 2*(4*atan 1.0)*x; .fi .PP @@ -2388,7 +2382,7 @@ .nf > \fBconst\fP c = 2; > foo x = c*x; -> \fBlist\fP foo +> \fBshow\fP foo foo x = 2*x; > foo 99; 198 @@ -2405,7 +2399,7 @@ > \fBclear\fP c > \fBconst\fP c = 3; > bar x = c*x; -> \fBlist\fP foo bar +> \fBshow\fP foo bar foo x = 2*x; bar x = 3*x; .fi @@ -2441,15 +2435,15 @@ call-by-name argument processing. .PP .B Laziness. -Pure approaches lazy evaluation in basically the same as Alice ML, providing -an explicit operation (&) to defer evaluation and create a ``future'' which is -called by need. However, note that like any language with a basically eager -evaluation strategy, Pure cannot really support lazy evaluation in a fully -automatic way. That is, coding an operation so that it works with infinite -data structures always requires additional effort to recognize futures in the -input and handle them accordingly. This can be hard, but of course in the case -of the prelude operations this work has already been done for you, so as long -as you stick to these, you'll never have to think about these issues. +Pure does lazy evaluation in the same way as Alice ML, providing an explicit +operation (&) to defer evaluation and create a ``future'' which is called by +need. However, note that like any language with a basically eager evaluation +strategy, Pure cannot really support lazy evaluation in a fully automatic +way. That is, coding an operation so that it works with infinite data +structures always requires additional effort to recognize futures in the input +and handle them accordingly. This can be hard, but of course in the case of +the prelude operations this work has already been done for you, so as long as +you stick to these, you'll never have to think about these issues. .PP Specifically, the prelude goes to great lengths to implement all standard list operations in a way that properly deals with streams (a.k.a. list futures). @@ -2594,7 +2588,7 @@ .TP .B PURE_MORE Shell command to be used for paging through output of the -.B list +.B show command, when the interpreter runs in interactive mode. .TP .B PURE_PS This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-04 23:13:40
|
Revision: 705 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=705&view=rev Author: agraef Date: 2008-09-04 23:13:50 +0000 (Thu, 04 Sep 2008) Log Message: ----------- Renamed 'list' command to 'show'. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/lexer.ll pure/trunk/pure.cc Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-09-04 23:01:42 UTC (rev 704) +++ pure/trunk/ChangeLog 2008-09-04 23:13:50 UTC (rev 705) @@ -1,3 +1,11 @@ +2008-09-05 Albert Graef <Dr....@t-...> + + * pure.cc, lexer.ll: Renamed the interactive 'list' command to + 'show', as suggested by John Cowan. This hopefully puts an end to + inadvertent execution of that command, since 'show' is no prelude + function and is deemed less likely to be used as a function name + by the programmer. + 2008-09-04 Albert Graef <Dr....@t-...> * lib/prelude.pure: Added the normal order fixed point combinator, Modified: pure/trunk/lexer.ll =================================================================== --- pure/trunk/lexer.ll 2008-09-04 23:01:42 UTC (rev 704) +++ pure/trunk/lexer.ll 2008-09-04 23:13:50 UTC (rev 705) @@ -133,8 +133,9 @@ static const char *commands[] = { "cd", "clear", "const", "def", "extern", "help", "infix", "infixl", - "infixr", "let", "list", "ls", "nullary", "override", "postfix", "prefix", - "private", "pwd", "quit", "run", "save", "stats", "underride", "using", 0 + "infixr", "let", "ls", "nullary", "override", "postfix", "prefix", + "private", "pwd", "quit", "run", "save", "show", "stats", "underride", + "using", 0 }; typedef map<string, symbol> symbol_map; @@ -357,8 +358,8 @@ else if (chdir(args.l.begin()->c_str())) perror("cd"); } -^list.* { - // list command is only permitted in interactive mode +^show.* { + // show command is only permitted in interactive mode if (!interp.interactive) REJECT; uint8_t s_verbose = interpreter::g_verbose; uint8_t tflag = 0; int pflag = -1; @@ -368,7 +369,7 @@ const char *s = yytext+4; if (*s && !isspace(*s)) REJECT; yylloc->step(); - argl args(s, "list"); + argl args(s, "show"); list<string>::iterator arg; if (!args.ok) goto out; // process option arguments @@ -402,8 +403,8 @@ tflag = interp.temp; break; 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\ + cout << "show command help: show [options ...] [symbol ...]\n\ +Options may be combined, e.g., show -tvl is the same as show -t -v -l.\n\ -a Disassembles pattern matching automata. Useful for debugging purposes.\n\ -c Print information about defined constants.\n\ -d Disassembles LLVM IR, showing the generated LLVM assembler code of a\n\ @@ -427,7 +428,7 @@ -v Print information about defined variables.\n"; goto out; default: - cerr << "list: invalid option character '" << *s << "'\n"; + cerr << "show: invalid option character '" << *s << "'\n"; goto out; } } Modified: pure/trunk/pure.cc =================================================================== --- pure/trunk/pure.cc 2008-09-04 23:01:42 UTC (rev 704) +++ pure/trunk/pure.cc 2008-09-04 23:13:50 UTC (rev 705) @@ -48,15 +48,16 @@ PURELIB Directory to search for library scripts and the prelude.\n\ PURE_INCLUDE Path to search for included source files.\n\ PURE_LIBRARY Path to search for dynamic libraries.\n\ -PURE_MORE Shell command for paging through output of the 'list' command.\n\ +PURE_MORE Shell command for paging through output of the 'show' command.\n\ PURE_PS Command prompt to be used in the interactive command loop.\n\ PURE_STACK Maximum stack size in kilobytes (default: 0 = unlimited).\n" #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", "const", "def", "extern", "help", "infix", "infixl", - "infixr", "let", "list", "ls", "nullary", "override", "postfix", "prefix", - "private", "pwd", "quit", "run", "save", "stats", "underride", "using", 0 + "infixr", "let", "ls", "nullary", "override", "postfix", "prefix", + "private", "pwd", "quit", "run", "save", "show", "stats", "underride", + "using", 0 }; /* Generator functions for command completion. */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-04 23:01:31
|
Revision: 704 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=704&view=rev Author: agraef Date: 2008-09-04 23:01:42 +0000 (Thu, 04 Sep 2008) Log Message: ----------- Update documentation. Modified Paths: -------------- pure/trunk/pure.1.in Modified: pure/trunk/pure.1.in =================================================================== --- pure/trunk/pure.1.in 2008-09-04 16:14:26 UTC (rev 703) +++ pure/trunk/pure.1.in 2008-09-04 23:01:42 UTC (rev 704) @@ -2020,21 +2020,15 @@ the sources, the .B list command can easily do it for you. For instance, here's how you can list the -definitions of all list ``fold'' operations from the prelude in one go: +definitions of all ``fold-left'' operations from the prelude in one go: .sp .nf -> \fBlist\fP -g fold* +> \fBlist\fP -g foldl* foldl f a s::string = foldl f a (chars s); foldl f a [] = a; foldl f a (x:xs) = foldl f (f a x) xs; foldl1 f s::string = foldl1 f (chars s); foldl1 f (x:xs) = foldl f x xs; -foldr f a s::string = foldr f a (chars s); -foldr f a [] = a; -foldr f a (x:xs) = f x (foldl (flip f) a (reverse xs)); -foldr1 f s::string = foldr1 f (chars s); -foldr1 f [x] = x; -foldr1 f (x:xs) = f x (foldl1 (flip f) (reverse xs)); .fi .SH DEFINITION LEVELS To help with incremental development, the interpreter also offers some This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-04 16:14:15
|
Revision: 703 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=703&view=rev Author: agraef Date: 2008-09-04 16:14:26 +0000 (Thu, 04 Sep 2008) Log Message: ----------- Prelude changes. Modified Paths: -------------- pure/trunk/lib/prelude.pure pure/trunk/test/prelude.log Modified: pure/trunk/lib/prelude.pure =================================================================== --- pure/trunk/lib/prelude.pure 2008-09-04 16:13:51 UTC (rev 702) +++ pure/trunk/lib/prelude.pure 2008-09-04 16:14:26 UTC (rev 703) @@ -89,6 +89,10 @@ uncurry3 f (x,y,z) = f x y z; +/* The (normal order) fixed point combinator. */ + +fix f = y y when y = \x -> f (x x&) end; + /* Some convenient optimization rules which eliminate saturated calls of the function composition combinators. */ @@ -211,7 +215,7 @@ accum ys xs = throw (bad_list_value xs); end; -/* Convert between lists and tuples. */ +/* Conversions between lists, tuples and streams. */ list () = []; list (x,xs) = accum [x] xs with @@ -226,8 +230,6 @@ accum ys xs = ys,xs; end; -/* Convert between lists and streams. */ - list [] = []; list (x:xs) = x:list xs; @@ -235,6 +237,9 @@ stream (x:xs) = x:xs if thunkp xs; = x:stream xs& otherwise; +stream () = []; +stream xs@(_,_) = stream (list xs); + /* Slicing. xs!!ns returns the list of xs!n for all members n of the index list ns which are in the valid index range. This is a generic definition which will work with any kind of container data structure which defines (!) Modified: pure/trunk/test/prelude.log =================================================================== --- pure/trunk/test/prelude.log 2008-09-04 16:13:51 UTC (rev 702) +++ pure/trunk/test/prelude.log 2008-09-04 16:14:26 UTC (rev 703) @@ -9,6 +9,17 @@ curry3 f/*0:0001*/ x/*0:001*/ y/*0:01*/ z/*0:1*/ = f/*0:0001*/ (x/*0:001*/,y/*0:01*/,z/*0:1*/); uncurry f/*0:01*/ (x/*0:101*/,y/*0:11*/) = f/*0:01*/ x/*0:101*/ y/*0:11*/; uncurry3 f/*0:01*/ (x/*0:101*/,y/*0:1101*/,z/*0:111*/) = f/*0:01*/ x/*0:101*/ y/*0:1101*/ z/*0:111*/; +fix f/*0:1*/ = y/*0:*/ y/*0:*/ when y/*0:*/ = \x/*0:*/ -> f/*1:1*/ (x/*1:*/ x/*1:*/&) { + rule #0: x = f (x x&) + state 0: #0 + <var> state 1 + state 1: #0 +} { + rule #0: y = \x -> f (x x&) + state 0: #0 + <var> state 1 + state 1: #0 +} end; def f/*0:01*/$x/*0:1*/ = f/*0:01*/ x/*0:1*/; def (f/*0:001*/.g/*0:01*/) x/*0:1*/ = f/*0:001*/ (g/*0:01*/ x/*0:1*/); def void (catmap f/*0:101*/ x/*0:11*/) = do f/*0:101*/ x/*0:11*/; @@ -303,6 +314,8 @@ stream [] = []; stream (x/*0:101*/:xs/*0:11*/) = x/*0:101*/:xs/*0:11*/ if thunkp xs/*0:11*/; stream (x/*0:101*/:xs/*0:11*/) = x/*0:101*/:stream xs/*1:11*/&; +stream () = []; +stream xs@(_/*0:101*/,_/*0:11*/) = stream (list xs/*0:1*/); xs/*0:01*/!!ns/*0:1*/ = catmap (nth/*0*/ xs/*0:01*/) ns/*0:1*/ with nth xs/*0:01*/ n/*0:1*/ = catch (cst []) [xs/*1:01*/!n/*1:1*/] { rule #0: nth xs n = catch (cst []) [xs!n] 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-09-04 16:13:42
|
Revision: 702 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=702&view=rev Author: agraef Date: 2008-09-04 16:13:51 +0000 (Thu, 04 Sep 2008) Log Message: ----------- Fixed point combinator is now defined in the prelude. Modified Paths: -------------- pure/trunk/examples/hello.pure Modified: pure/trunk/examples/hello.pure =================================================================== --- pure/trunk/examples/hello.pure 2008-09-04 16:12:04 UTC (rev 701) +++ pure/trunk/examples/hello.pure 2008-09-04 16:13:51 UTC (rev 702) @@ -84,9 +84,9 @@ // Using fixed points. This technique allows you to define a recursive // function without referring to the name of the function in its body. See // http://en.wikipedia.org/wiki/Fixed_point_combinator for an explanation. +// The (normal order) fixed point combinator 'fix' is defined in the prelude. -fact6 = Z (\f n -> if n<=0 then 1 else n*f (n-1)); -Z = \f -> (\x -> f (\y -> x x y)) (\x -> f (\y -> x x y)); +fact6 = fix (\f n -> if n<=0 then 1 else n*f (n-1)); // These should all evaluate to the same list of the first 10 factorials. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-04 16:11:57
|
Revision: 701 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=701&view=rev Author: agraef Date: 2008-09-04 16:12:04 +0000 (Thu, 04 Sep 2008) Log Message: ----------- Update documentation. Modified Paths: -------------- pure/trunk/pure.1.in Modified: pure/trunk/pure.1.in =================================================================== --- pure/trunk/pure.1.in 2008-09-04 16:11:47 UTC (rev 700) +++ pure/trunk/pure.1.in 2008-09-04 16:12:04 UTC (rev 701) @@ -793,39 +793,43 @@ This special kind of list is also called a .IR stream . Streams enable you to work with infinite lists (or finite lists which are so -huge that we would never want to keep them in memory). E.g., here's one way to -create the infinite list of all positive integers: +huge that you would never want to keep them in memory in their +entirety). E.g., here's one way to define the infinite stream of all Fibonacci +numbers: .sp .nf -> ones = 1:ones&; -> integers = 1 : zipwith (+) ones integers&; -> \fBlet\fP ints = integers; ints; -1:{{thunk 0xb5fdd5b8}} +> fibs = 0L : 1L : zipwith (+) fibs (tail fibs) &; +> fibs; +0L:1L:{{thunk 0xb5f875e8}} .fi .PP -(Note that we use machine integers in this example, so in fact the list will -wrap around to the smallest negative integer at some point.) +Note the `&' on the tail of the list. This turns `fibs' into a stream, which +is required to prevent `fibs' from recursing into samadhi. Also note that we +work with bigints in this example because the Fibonacci numbers grow quite +rapidly, so with machine integers the values would soon start wrapping around +to negative integers. .PP -Of course, care must be taken not to invoke ``eager'' operations such as `#' -(which computes the size of a list) on infinite streams, since this never -terminates. However, many list operations work with infinite streams just -fine, and return the appropriate stream results. E.g., the `take' function -(which retrieves a given number of elements from the front of a list) works -with streams just as well as with ``eager'' lists: +Streams like these can be worked with in pretty much the same way as with +lists. Of course, care must be taken not to invoke ``eager'' operations such +as `#' (which computes the size of a list) on infinite streams, to prevent +infinite recursion. However, many list operations work with infinite streams +just fine, and return the appropriate stream results. E.g., the `take' +function (which retrieves a given number of elements from the front of a list) +works with streams just as well as with ``eager'' lists: .sp .nf -> take 10 ints; -1:{{thunk 0xb5fdd5e8}} +> take 10 fibs; +0L:1L:{{thunk 0xb5f87630}} .fi .PP Hmm, not much progress there, but that's just how streams work (or rather -don't, they're lazy bums indeed!). But the stream computed with `take' is in -fact finite and we can readily convert it to an ordinary list, forcing its -evaluation: +don't, they're lazy bums indeed!). Nevertheless, the stream computed with +`take' is in fact finite and we can readily convert it to an ordinary list, +forcing its evaluation: .sp .nf -> (list) (take 10 ints); -[1,2,3,4,5,6,7,8,9,10] +> (list) (take 10 fibs); +[0L,1L,1L,2L,3L,5L,8L,13L,21L,34L] .fi .PP (Note that we typed `(list)' instead of just `list' here, so that the @@ -840,25 +844,98 @@ .sp .nf > takel n xs = list (take n xs); -> takel 10 ints; -[1,2,3,4,5,6,7,8,9,10] +> takel 10 fibs; +[0L,1L,1L,2L,3L,5L,8L,13L,21L,34L] .fi .PP -Let's take another look at the `ints' stream now: +Well, this naive definition of the Fibonacci stream works, but it's awfully +inefficient. In fact, it takes exponential running time to determine the +.IR n th +member of the sequence, because of the two recursive calls to `fibs' on the +right-hand side. This defect soon becomes rather annoying if we access larger +members of the sequence. Just for fun, let's measure some evaluation times +with the interactive +.B stats +command: .sp .nf -> ints; -1:2:3:4:5:6:7:8:9:10:{{thunk 0xb5fddcd8}} +> \fBstats\fP +> fibs!25; fibs!26; fibs!27; +75025L +2.29s +121393L +3.75s +196418L +6.12s +> \fBstats off\fP .fi .PP -As you can see, the invokation of `list' on the result of `take' forced the -corresponding prefix of the `ints' stream to be computed. The result of this -is memoized, so that this portion of the stream is now readily available in -case we need to have another look at it again later. By these means, possibly -costly reevaluations are avoided, trading memory for execution speed. +It's quite apparent that the ratios between successive running times converge +to the golden ratio from above (which is of course no accident!). So, assuming +a fast computer which can produce the first stream element in a nanosecond, a +conservative estimate of the time needed to compute just the 128th Fibonacci +number would already exceed the current age of the universe by some 29.6%, if +done this way. It goes without saying that this kind of algorithm won't even +pass muster in a computer science freshman course. .PP -A number of convenience operations are available for generating stream values. -The prelude defines infinite arithmetic sequences, using +So let's get back to the drawing board. One nice trick of the trade is to have +the +.I value +of the Fibonacci stream refer to itself in its definition, rather than just +the function generating it. For that we need a kind of ``recursive variable +definition'' which Pure doesn't have. (Haskellers should note here that the +values of parameterless functions are never memoized in Pure, because that +would wreak havoc on functions with side effects.) Fortunately, we can work +around this quite easily by employing the so-called +.IR "fixed point combinator" , +incidentally called +.B fix +in Pure and defined in the prelude as follows: +.sp +.nf +> \fBlist\fP fix +fix f = y y \fBwhen\fP y = \ex -> f (x x&) \fBend\fP; +.fi +.PP +(Functional programming buffs surely notice that this is an implementation of +the normal order fixed point combinator, decorated with `&' in the right place +to make it work with eager evaluation. Aspiring novices may go read Wikipedia +or a good book on the lambda calculus now.) +.PP +So here's how we can define a ``linear-time'' version of the Fibonacci +stream. (Note that we also define the stream as a variable now, to take full +advantage of memoization.) +.sp +.nf +> \fBclear\fP fibs +> \fBlet\fP fibs = fix (\ef -> 0L : 1L : zipwith (+) f (tail f) &); +> fibs; +0L:1L:{{thunk 0xb58d8ae0}} +> takel 10 fibs; +[0L,1L,1L,2L,3L,5L,8L,13L,21L,34L] +> fibs; +0L:1L:1L:2L:3L:5L:8L:13L:21L:34L:{{thunk 0xb4ce5d30}} +.fi +.PP +As you can see, the invokation of our `takel' function forced the +corresponding prefix of the `fibs' stream to be computed. The result of the +evaluation is memoized, so that this portion of the stream is now readily +available in case we need to have another look at it later. By these means, +possibly costly reevaluations are avoided, trading memory for execution speed. +.PP +Also, the trick we played with the fixed point combinator pays off, and in +fact computing large Fibonacci numbers is a piece of cake now: +.sp +.nf +> \fBstats\fP +> fibs!199; +173402521172797813159685037284371942044301L +0.1s +> \fBstats off\fP +.fi +.PP +Let's take a look at some of the other convenience operations for generating +stream values. The prelude defines infinite arithmetic sequences, using .B inf or .B -inf @@ -872,16 +949,28 @@ .fi .PP Other useful stream generator functions are `iterate', `repeat' and `cycle', -which have been adopted from Haskell. Moreover, list comprehensions can draw -values from streams and return the appropriate stream result: +which have been adopted from Haskell. In fact, infinite arithmetic +progressions are implemented in terms of `iterate'. The `repeat' function just +repeats its argument, and `cycle' cycles through the elements of the given +list until hell freezes over: .sp .nf -> \fBlet\fP pairs = [i,j; i=1..inf; j=1..i]; pairs; -(1,1):{{thunk 0xb5f28818}} -> takel 10 pairs; -[(1,1),(2,1),(2,2),(3,1),(3,2),(3,3),(4,1),(4,2),(4,3),(4,4)] +> takel 10 (repeat 1); +[1,1,1,1,1,1,1,1,1,1] +> takel 10 (cycle [0,1]); +[0,1,0,1,0,1,0,1,0,1] .fi .PP +Moreover, list comprehensions can draw values from streams and return the +appropriate stream result: +.sp +.nf +> \fBlet\fP rats = [m,n-m; n=2..inf; m=1..n-1; gcd m (n-m) == 1]; rats; +(1,1):{{thunk 0xb5fd08b8}} +> takel 10 rats; +[(1,1),(1,2),(2,1),(1,3),(3,1),(1,4),(2,3),(3,2),(4,1),(1,5)] +.fi +.PP Finally, let's rewrite our prime sieve so that it generates the infinite stream of .I all @@ -915,6 +1004,12 @@ 5 ... .fi +.PP +(Make sure that you really use the `all_primes' function instead of the P +variable to print the stream. Otherwise the stream stored in P will grow with +the number of elements printed until memory is exhausted. Calling `do' on a +fresh instance of the stream of primes allows `do' to get rid of each `cons' +cell after having printed the corresponding stream element.) .SH RULE SYNTAX Basically, the same rule syntax is used in all kinds of global and local definitions. However, some constructs (specifically, \fBwhen\fP, \fBlet\fP, @@ -2345,11 +2440,49 @@ .PP .B Special forms. Special forms are recognized at compile time only. Thus the catch function as -well as the logical connectives && and || and the sequencing operator $$ are -only treated as special forms in direct (saturated) calls. They can still be -used if you pass them around as function values or partial applications, but -in this case they lose all their special call-by-name argument processing. +well as the logical connectives && and ||, the sequencing operator $$ and the +lazy evaluation operator & are only treated as special forms in direct +(saturated) calls. They can still be used if you pass them around as function +values or partial applications, but in this case they lose all their special +call-by-name argument processing. .PP +.B Laziness. +Pure approaches lazy evaluation in basically the same as Alice ML, providing +an explicit operation (&) to defer evaluation and create a ``future'' which is +called by need. However, note that like any language with a basically eager +evaluation strategy, Pure cannot really support lazy evaluation in a fully +automatic way. That is, coding an operation so that it works with infinite +data structures always requires additional effort to recognize futures in the +input and handle them accordingly. This can be hard, but of course in the case +of the prelude operations this work has already been done for you, so as long +as you stick to these, you'll never have to think about these issues. +.PP +Specifically, the prelude goes to great lengths to implement all standard list +operations in a way that properly deals with streams (a.k.a. list futures). +What this all boils down to is that all list operations which can reasonably +be expected to operate in a lazy way on streams, will do so. (Exceptions are +inherently eager operations such as `#', reverse and foldl.) Only those +portions of an input stream will be traversed which are strictly required to +produce the result. For most purposes, this works just like in fully lazy FPLs +such as Haskell. However, there are some notable differences: +.IP * +Since Pure uses dynamic typing, some of the list functions may have to peek +ahead one element in input streams to check their arguments for validity, +meaning that these functions will be slightly more eager than their Haskell +counterparts. +.IP * +Pure's list functions never produce truly cyclic list structures such as the +ones you get, e.g., with Haskell's `cycle' operation. (This is actually a good +thing, because the current implementation of the interpreter cannot +garbage-collect cyclic expression data.) Cyclic streams such as `cycle [1]' or +`fix (\ex -> 1:x)' will of course work as expected, but, depending on the +algorithm, memory usage may increase linearly as they are traversed. +.IP * +Pattern matching is always refutable (and therefore eager) in Pure. If you +need something like Haskell's irrefutable matches, you'll have to code them +explicitly using futures. See the definition of the `unzip' function in the +prelude for an example showing how to do this. +.PP .B Stack size and tail recursion. Pure programs may need a considerable amount of stack space to handle recursive function calls, and the interpreter itself also takes its toll. So @@ -2486,6 +2619,10 @@ Another functional programming language based on term rewriting, \fIhttp://wouter.fov120.com/aardappel\fP. .TP +.B Alice ML +A version of ML (see below) with ``futures'', +\fIhttp://www.ps.uni-sb.de/alice\fP. +.TP .B Haskell A popular non-strict FPL, \fIhttp://www.haskell.org\fP. .TP This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-04 16:11:36
|
Revision: 700 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=700&view=rev Author: agraef Date: 2008-09-04 16:11:47 +0000 (Thu, 04 Sep 2008) Log Message: ----------- Bugfixes. Modified Paths: -------------- pure/trunk/runtime.cc Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-09-04 16:10:09 UTC (rev 699) +++ pure/trunk/runtime.cc 2008-09-04 16:11:47 UTC (rev 700) @@ -1477,6 +1477,8 @@ { char test; assert(x && y && x->refc > 0 && y->refc > 0); + // if the function in this call is a thunk, evaluate it now + if (x->tag == 0 && x->data.clos && x->data.clos->n == 0) pure_force(x); // travel down the spine, count arguments pure_expr *f = x, *f0, *ret; uint32_t n = 1; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-04 16:10:00
|
Revision: 699 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=699&view=rev Author: agraef Date: 2008-09-04 16:10:09 +0000 (Thu, 04 Sep 2008) Log Message: ----------- Updated ChangeLog. Modified Paths: -------------- pure/trunk/ChangeLog Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-09-04 01:32:56 UTC (rev 698) +++ pure/trunk/ChangeLog 2008-09-04 16:10:09 UTC (rev 699) @@ -1,3 +1,44 @@ +2008-09-04 Albert Graef <Dr....@t-...> + + * lib/prelude.pure: Added the normal order fixed point combinator, + 'fix'. + + * lib/prelude.pure: Overhaul of list operations in the prelude, so + that they properly work with "thunked" lists (streams). Where + possible, these operations have been redesigned to make them + non-strict, while keeping them tail-recursive for the parts of a + list which have already been evaluated. + + In particular, the cat and catmap operations now handle infinite + streams of infinite streams, and hence list comprehensions can + draw values from infinite streams as well. + + The 'list' function can be used to convert a (finite) stream to an + ordinary list, forcing its evaluation. Conversely, the new + 'stream' function converts an ordinary list (tuple, string) to a + stream. + + There are a few other related changes in the prelude: + + - The slicing operation (!!) is now implemented in a completely + generic way which works with any container data structure which + implements the indexing (!) operation. It also works properly if + both operands are infinite streams. + + - Arithmetic sequences (..) now take an infinity (inf or -inf) as + the second operand and will generate the appropriate stream in + such cases. + + - The repeat and cycle functions have been rewritten to make them + Haskell-compatible, i.e., they only take a single argument now and + generate infinite streams. Haskell's iterate function is now also + implemented. The previous versions of repeat and cycle, which take + an additional integer parameter to denote the desired length of + the result and return an ordinary (eager) list, are now available + under the names repeatn and cyclen. (To make cyclen compatible + with cycle, it now also returns a list if applied to a string, use + strcat to convert the result back to a string if needed.) + 2008-09-01 Albert Graef <Dr....@t-...> * interpreter.cc, runtime.cc, symtable.cc/h, lib/prelude.pure: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-04 01:32:45
|
Revision: 698 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=698&view=rev Author: agraef Date: 2008-09-04 01:32:56 +0000 (Thu, 04 Sep 2008) Log Message: ----------- Update logs. Modified Paths: -------------- pure/trunk/test/test004.log Modified: pure/trunk/test/test004.log =================================================================== --- pure/trunk/test/test004.log 2008-09-04 01:30:26 UTC (rev 697) +++ pure/trunk/test/test004.log 2008-09-04 01:32:56 UTC (rev 698) @@ -35,15 +35,15 @@ foo 99; 99 foo2 99; -<<closure bar>> 100 +{{closure bar}} 100 foo2 98; -<<closure bar>> 98 +{{closure bar}} 98 foo3 99; -<<closure bar>> +{{closure bar}} foo3 99 98; -<<closure bar>> 98 +{{closure bar}} 98 foo3 99 99; -<<closure 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-09-04 01:30:17
|
Revision: 697 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=697&view=rev Author: agraef Date: 2008-09-04 01:30:26 +0000 (Thu, 04 Sep 2008) Log Message: ----------- Update documentation. Modified Paths: -------------- pure/trunk/pure.1.in Modified: pure/trunk/pure.1.in =================================================================== --- pure/trunk/pure.1.in 2008-09-04 01:26:04 UTC (rev 696) +++ pure/trunk/pure.1.in 2008-09-04 01:30:26 UTC (rev 697) @@ -614,7 +614,7 @@ .nf > foo x = bar \fBwith\fP bar y = x+y \fBend\fP; > \fBlet\fP f = foo 99; f; -<<closure bar>> +{{closure bar}} > f 10, f 20; 109,119 .fi @@ -800,7 +800,7 @@ > ones = 1:ones&; > integers = 1 : zipwith (+) ones integers&; > \fBlet\fP ints = integers; ints; -1:<<thunk 0xb5fdd5b8>> +1:{{thunk 0xb5fdd5b8}} .fi .PP (Note that we use machine integers in this example, so in fact the list will @@ -815,7 +815,7 @@ .sp .nf > take 10 ints; -1:<<thunk 0xb5fdd5e8>> +1:{{thunk 0xb5fdd5e8}} .fi .PP Hmm, not much progress there, but that's just how streams work (or rather @@ -848,7 +848,7 @@ .sp .nf > ints; -1:2:3:4:5:6:7:8:9:10:<<thunk 0xb5fddcd8>> +1:2:3:4:5:6:7:8:9:10:{{thunk 0xb5fddcd8}} .fi .PP As you can see, the invokation of `list' on the result of `take' forced the @@ -877,7 +877,7 @@ .sp .nf > \fBlet\fP pairs = [i,j; i=1..inf; j=1..i]; pairs; -(1,1):<<thunk 0xb5f28818>> +(1,1):{{thunk 0xb5f28818}} > takel 10 pairs; [(1,1),(2,1),(2,2),(3,1),(3,2),(3,3),(4,1),(4,2),(4,3),(4,4)] .fi This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ag...@us...> - 2008-09-04 01:25:53
|
Revision: 696 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=696&view=rev Author: agraef Date: 2008-09-04 01:26:04 +0000 (Thu, 04 Sep 2008) Log Message: ----------- Change printing of external objects, so that it can't be misparsed as an ordinary expression. Modified Paths: -------------- pure/trunk/printer.cc Modified: pure/trunk/printer.cc =================================================================== --- pure/trunk/printer.cc 2008-09-04 01:18:14 UTC (rev 695) +++ pure/trunk/printer.cc 2008-09-04 01:26:04 UTC (rev 696) @@ -166,7 +166,7 @@ static ostream& printx(ostream& os, const expr& x, bool pat, bool aspat) { char buf[64]; - if (x.is_null()) return os << "<<NULL>>"; + if (x.is_null()) return os << "{{NULL}}"; //os << "{" << x.refc() << "}"; // handle "as" patterns if (aspat && x.astag()>0) { @@ -243,7 +243,7 @@ return os; } case EXPR::PTR: - return os << "<<pointer " << x.pval() << ">>"; + return os << "{{pointer " << x.pval() << "}}"; case EXPR::APP: { expr u, v, w, y; exprl xs; @@ -665,7 +665,7 @@ return os; } case EXPR::PTR: - return os << "<<pointer " << x->data.p << ">>"; + return os << "{{pointer " << x->data.p << "}}"; case EXPR::APP: { list<const pure_expr*> xs; prec_t p; @@ -760,11 +760,11 @@ default: { if (x->tag == 0) { const char *s = (x->data.clos && x->data.clos->n==0)?"thunk":"closure"; - return os << "<<" << s << " " << (void*)x << ">>"; + return os << "{{" << s << " " << (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 << ">>"; + return os << "{{closure " << sym.s << "}}"; if (sym.prec < 10) return os << '(' << sym.s << ')'; else This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |