Thanks for the hint! I added template arguments wherever I could and now I got some error messages that actually say something. However, I do find it a bit disconcerting that the compiler would segfault rather than tell me I need to annotate templates.
Den måndag 13 mars 2017 kl. 22:02:57 UTC+1 skrev gmhwxi: > > I will take a look later. Based on your description, the issue > seems to be caused by not providing certain template arguments > explicitly: > > Say, foo is a template. Please use foo<...>(...) instead of foo(...) > > Compared to Haskell, type inference in ATS is quite limited :) > > On Mon, Mar 13, 2017 at 4:51 PM, August Alm <augu...@gmail.com > <javascript:>> wrote: > >> So... I added some "second stage" parsing functionality, to get the en >> result in tabular form rahter than as a single [stream_vt], and to check >> for global errors such as unequal number of columns in the rows, and now I >> am back to segfaulting! =( However, this time it does not seem to be a >> stack issue because I run into the segmentation fault already at the >> compilation stage. >> >> I code in Vim and have it set up so that typing ":make" will run "patsopt >> -tc -d %", i.e., typechecking only. When I do everything seems fine--no >> complaints. I have used this utility for some time now and it has always >> worked like a charm. Wierdly though, if I issue "$ patsopt -tc -d >> csv_lexer.dats" in the console instead I get a segfault. The same happens >> for every other compilation command: I've tried compiling just using type >> checking, just to c, or etc. Always segfault. Compiling with the "-verbose" >> flag prints >> >> exec(patsopt --output csv_lexer_dats.c --dynamic csv_lexer.dats) >> Segmentation fault >> exec(patsopt --output csv_lexer_dats.c --dynamic csv_lexer.dats) = 35584 >> >> which does not tell me anything. >> >> My code can be found at https://github.com/August-Alm/ats_csv_lexer Note >> that I have moved some function implementations into a hats-file. Might >> this be a cause of trouble? Any tips at all on how to debug this are most >> appreciated. I don't know where to even begin as gdb seems useless as long >> as I can't even generate the C-code. >> >> Best wishes, >> August >> >> Den onsdag 8 mars 2017 kl. 23:44:10 UTC+1 skrev gmhwxi: >>> >>> >>I take that as being somewhat tongue-in-cheek. ATS is a very >>> theoretical language, after all. >>> >>> I know that this sounds very ironic but interesting stuff often does >>> sound ironic :) >>> >>> My view of programming language research is changing gradually but >>> surely. I now strongly feel >>> that the most important programming support is to facilitate the need to >>> alter/adapt the behaviour >>> of a written program without actually requiring direct changes to be >>> made to the program. And the >>> template system of ATS can be seen as an attempt to provide programming >>> support of this sort. >>> >>> >>> On Wed, Mar 8, 2017 at 4:47 PM, August Alm <augu...@gmail.com> wrote: >>> >>>> See in. >>>> >>>> Den onsdag 8 mars 2017 kl. 17:51:36 UTC+1 skrev gmhwxi: >>>>> >>>>> Tangential to the topic of monads: Do you know if someone has thought >>>>>> about the relations between ATS and "enriched effect calculus" (as >>>>>> described in >>>>>> http://homepages.inf.ed.ac.uk/als/Research/Sources/eec.pdf) or >>>>>> "linear state monads" (as mentioned in >>>>>> https://arxiv.org/pdf/1403.1477.pdf)? There is a clear analogy. >>>>>> Implementing a concept such as a linear state monad in ATS would be >>>>>> nice, I >>>>>> think. Monadic programming on an Arduino, anyone? =) It would certainly >>>>>> be >>>>>> a unique selling point. >>>>>> >>>>> >>>>> I can't really follow these monad papers. Too much for me :) >>>>> Given your background, maybe you could give this a try? >>>>> >>>>> I'm tempted but I feel like I have to understand ATS:s function tags >>>> ("cloref" and the like, the flavours of function) better first, and >>>> generally get a more solid footing. I don't want to write something >>>> "cool", >>>> I want it to be useful, too. >>>> >>>> >>>>> Over the years, I have gradually grown more and more cynic about >>>>> "theoretic" research >>>>> in the area of programming languages. I feel that the most urgent >>>>> issue in programming is >>>>> to find effective approaches to reducing programming complexity. >>>>> >>>>> I take that as being somewhat tongue-in-cheek. ATS is a very >>>> theoretical language, after all. To clarify, I think Haskell suffers >>>> greatly from having too little focus on efficiency (among many of its >>>> users, not among the guys working on the compiler). I heard about ATS >>>> about >>>> the same time as I heard about Idris (the dependent type thing) and >>>> decided >>>> to pursue ATS precisely because of its air of efficiency and >>>> "real-world-readiness". I do still love my Haskell though, mainly because >>>> it is so easy to be productive with it. Scala has a very good no-bs >>>> culture >>>> and good library hygiene, but I'm not too fond of OOP so... >>>> >>>> >>>>> For instance, in your csv parser, there are a lot of if-then-else's. >>>>> Maybe you took them from >>>>> some Haskel code. The point is that if-then-else's make programming >>>>> hard to write and harder >>>>> to read/follow. I propose the following style: >>>>> >>>>> I first tried to write it using only pattern matching but failed to >>>> get it passed the typechecker. Maybe I will have another go at it. >>>> >>>> >>>>> 1) Implementing a csv parser without worrying about quotes (DQUOT). >>>>> Call this version 1. >>>>> 2) Using templates to improve version 1 without directly modifying >>>>> version 1. Another way >>>>> to put it: you still have version 1 available after doing the >>>>> improvement. >>>>> >>>>> If I was uncertain about the algorithm then such an incremental >>>> development style would surely be preferable, but since the code is a port >>>> of a tried and tested Haskell library I'm >>>> not very motivated to scrap and start over. But for my next project(s) >>>> I will try to heed your words. >>>> >>>> I know that this may sound a bit vague but that is my point. Being >>>>> vague makes people >>>>> think more and more deeply :) >>>>> >>>>> Cheers! >>>>> >>>>> >>>>> On Tuesday, March 7, 2017 at 4:52:58 PM UTC-5, August Alm wrote: >>>>>> >>>>>> I'm glad too! I wrote my first "Hello World" program (in Haskell) >>>>>> less than four months ago, before that I was completely illiterate about >>>>>> programming--writing a linear, lazy CSV-parser in ATS has definitely >>>>>> been >>>>>> my most challenging venture so far. I mean this in a good way. ATS is >>>>>> quickly becoming my favorite language. It is daunting at times, sure, >>>>>> but >>>>>> its unique combination of low-level abilities and functional >>>>>> abstractions >>>>>> makes me feel like the Star Trek idiom "To boldly go where no one has >>>>>> gone >>>>>> before", heh. The ATS sky is so vast I've almost forgot about monads. >>>>>> And >>>>>> YES!, I do suggest trying ATS to every programmer I meet. >>>>>> >>>>>> Tangential to the topic of monads: Do you know if someone has thought >>>>>> about the relations between ATS and "enriched effect calculus" (as >>>>>> described in >>>>>> http://homepages.inf.ed.ac.uk/als/Research/Sources/eec.pdf) or >>>>>> "linear state monads" (as mentioned in >>>>>> https://arxiv.org/pdf/1403.1477.pdf)? There is a clear analogy. >>>>>> Implementing a concept such as a linear state monad in ATS would be >>>>>> nice, I >>>>>> think. Monadic programming on an Arduino, anyone? =) It would certainly >>>>>> be >>>>>> a unique selling point. >>>>>> >>>>>> I do not understand what you're aiming at with your suggestion to >>>>>> maje CSVState a datavtype or absvtype. Could you elaborate? I have seen >>>>>> abstract types used as a way to make otherwise allowed operation illegal >>>>>> (there is an example in your book, I think, of how to construct a record >>>>>> type where some fields are mutable and some are not), but not for the >>>>>> sake >>>>>> of overloading symbols. >>>>>> >>>>>> I will rewrite the code so that DELIM and QNLIN are passed as >>>>>> templates. I also intend to add some further functionality, like >>>>>> functions >>>>>> for filtering out errors, for printing and for collecting the output in >>>>>> tabular form with rows and columns rather than as a single row. When I'm >>>>>> satisfied I will make an npm-package out of it. >>>>>> >>>>>> Best wishes, >>>>>> August >>>>>> >>>>>> Den tisdag 7 mars 2017 kl. 02:21:00 UTC+1 skrev gmhwxi: >>>>>>> >>>>>>> Really glad that you got it to work! >>>>>>> >>>>>>> I suggest that you make a npm-package for the parser and then >>>>>>> publish the package. In this way, other ats-lang users can benefit >>>>>>> from your work easily. >>>>>>> >>>>>>> You could try to introduce some abstract types into your code. For >>>>>>> instance, I would suggest that you make CSVstate a datavtype (linear >>>>>>> datatype) >>>>>>> (a datatype is often referred to as being semi-abstract). Then you >>>>>>> can >>>>>>> introduce overloaded symbols for functions processing CSVstate, >>>>>>> making your code >>>>>>> more accessible. >>>>>>> >>>>>>> Also, the following interface: >>>>>>> >>>>>>> extern fun >>>>>>> lex_csv(QNLIN: bool, DELIM: char, cs: llstring): CSVEntries >>>>>>> >>>>>>> can and probably should be changed into >>>>>>> >>>>>>> extern >>>>>>> fun{} >>>>>>> lex_csv(cs: listing): CSVEntries >>>>>>> >>>>>>> The parameters QNLIN and DELIM can be passed via templates: >>>>>>> >>>>>>> extern >>>>>>> fun{} lex_csv$QNLIN(): char >>>>>>> extern >>>>>>> fun{} lex_csv$DELIM(): char >>>>>>> >>>>>>> implement{} lex_csv$QNLIN() = false >>>>>>> implement{} lex_csv$DELIM() = ',' // default value >>>>>>> >>>>>>> Writing function templates (instead of functions) enables you to move >>>>>>> your code around very conveniently. You can even move template code >>>>>>> into the body of another function. >>>>>>> >>>>>>> That's all for now. Hope you will like ATS and tell/teach it to your >>>>>>> friends. >>>>>>> >>>>>>> Cheers! >>>>>>> >>>>>>> On Monday, March 6, 2017 at 4:06:11 PM UTC-5, August Alm wrote: >>>>>>>> >>>>>>>> The code now seems to work as inteded! >>>>>>>> >>>>>>>> https://github.com/August-Alm/ats_csv_lexer >>>>>>>> >>>>>>>> Thank you for all the help. I still don't fully grokk why the >>>>>>>> function needs to consume each of its arguments--will have to meditate >>>>>>>> more >>>>>>>> on that--but at least I know how to write code like this from now on. >>>>>>>> >>>>>>>> Den måndag 6 mars 2017 kl. 17:43:36 UTC+1 skrev gmhwxi: >>>>>>>>> >>>>>>>>> Yes, CSVstate needs to be changed as well. >>>>>>>>> >>>>>>>>> However, your code needs very little change. This is like a >>>>>>>>> a 5 minute job to me. I would be happy to give it a try if you say >>>>>>>>> so. >>>>>>>>> But I thought that you might want to get the thrill of fixing the >>>>>>>>> code :) >>>>>>>>> >>>>>>>>> On Monday, March 6, 2017 at 11:30:27 AM UTC-5, August Alm wrote: >>>>>>>>>> >>>>>>>>>> Hrrm, I had: >>>>>>>>>> >>>>>>>>>> fun >>>>>>>>>> parse_entry >>>>>>>>>> ( st: !CSVState >> _ >>>>>>>>>> , at: (int, int) >>>>>>>>>> , acc: !$SBF.stringbuf >>>>>>>>>> , cs: llstring >>>>>>>>>> ) : stream_vt(CSVEntry) >>>>>>>>>> >>>>>>>>>> I gather I have to change not just [!$SBF.stringbuf] but also >>>>>>>>>> [!CSVState >> _], right? What about if I did >>>>>>>>>> >>>>>>>>>> fun >>>>>>>>>> parse_entry_con >>>>>>>>>> ( st: !CSVState >> _ >>>>>>>>>> , at: (int, int) >>>>>>>>>> , acc: !$SBF.stringbuf >>>>>>>>>> , cs: llstring >>>>>>>>>> ) : stream_vt_con(CSVEntry) >>>>>>>>>> >>>>>>>>>> and then put >>>>>>>>>> >>>>>>>>>> parse_entry(...) = >>>>>>>>>> $ldelay >>>>>>>>>> ( parse_entry_con(...) >>>>>>>>>> , ( free(st) >>>>>>>>>> ; free(acc) >>>>>>>>>> ; free(cs) >>>>>>>>>> ) >>>>>>>>>> ) >>>>>>>>>> >>>>>>>>>> --would that work? Would it be idiomatic and efficient? >>>>>>>>>> >>>>>>>>>> Thanks, again, >>>>>>>>>> August >>>>>>>>>> >>>>>>>>>> Den måndag 6 mars 2017 kl. 14:30:05 UTC+1 skrev gmhwxi: >>>>>>>>>>> >>>>>>>>>>> I forgot to tell you something essential in using stream_vt. >>>>>>>>>>> The following interface for 'test' cannot work: >>>>>>>>>>> >>>>>>>>>>> fun test (acc: !$SBF.stringbuf, cs: llstring): stream_vt(DT) = >>>>>>>>>>> >>>>>>>>>>> What you need is >>>>>>>>>>> >>>>>>>>>>> fun test (acc: $SBF.stringbuf, cs: llstring): stream_vt(DT) = >>>>>>>>>>> >>>>>>>>>>> The 'acc' stringbuf needs to be consumed by 'test'. The >>>>>>>>>>> implementation >>>>>>>>>>> of 'test' looks like this: >>>>>>>>>>> >>>>>>>>>>> $ldelay >>>>>>>>>>> ( >>>>>>>>>>> <code for stream construction> >>>>>>>>>>> , >>>>>>>>>>> (freeing(acc); freeing(cs)) // this part is executed when the >>>>>>>>>>> stream is freed >>>>>>>>>>> ) >>>>>>>>>>> >>>>>>>>>>> On Mon, Mar 6, 2017 at 8:19 AM, August Alm <augu...@gmail.com> >>>>>>>>>>> wrote: >>>>>>>>>>> >>>>>>>>>>>> The points you mention are part of the reason I chose to wrote >>>>>>>>>>>> the csv lexer the way I did. It follows one of the fastests >>>>>>>>>>>> Haskell csv >>>>>>>>>>>> parsers, and I was curious to see how using linear types could >>>>>>>>>>>> optimize >>>>>>>>>>>> performance. >>>>>>>>>>>> >>>>>>>>>>>> Regarding your suggestion on how to make better use of $ldelay >>>>>>>>>>>> in my code: I'm stuck on a compiler error that I can't make sense >>>>>>>>>>>> of. The >>>>>>>>>>>> following pseudo-minimal example throws the same kind of errors: >>>>>>>>>>>> >>>>>>>>>>>> #include "share/atspre_define.hats" >>>>>>>>>>>> #include "share/atspre_staload.hats" >>>>>>>>>>>> staload UN = "prelude/SATS/unsafe.sats" >>>>>>>>>>>> staload SBF = "libats/SATS/stringbuf.sats" >>>>>>>>>>>> staload _(*SBF*) = "libats/DATS/stringbuf.dats" >>>>>>>>>>>> >>>>>>>>>>>> datatype DT = D_T of @{ alpha = char } >>>>>>>>>>>> vtypedef llstring = stream_vt(char) >>>>>>>>>>>> >>>>>>>>>>>> fun >>>>>>>>>>>> test (acc: !$SBF.stringbuf, cs: llstring): >>>>>>>>>>>> stream_vt(DT) = >>>>>>>>>>>> $ldelay >>>>>>>>>>>> ( case !cs of >>>>>>>>>>>> | ~stream_vt_nil() => >>>>>>>>>>>> if $SBF.stringbuf_get_size(acc) = i2sz(0) then >>>>>>>>>>>> stream_vt_nil() >>>>>>>>>>>> else stream_vt_cons(D_T(@{alpha = 'a'}), >>>>>>>>>>>> stream_vt_make_nil()) >>>>>>>>>>>> | ~stream_vt_cons(c, cs1) => >>>>>>>>>>>> let val crec = D_T(@{alpha = c}) >>>>>>>>>>>> in stream_vt_cons(crec, test(acc, cs1)) >>>>>>>>>>>> end >>>>>>>>>>>> , ~cs >>>>>>>>>>>> ) >>>>>>>>>>>> >>>>>>>>>>>> The compiler can not infer the type I want (which is >>>>>>>>>>>> [stream_vt_con(DT)] for the [stream_vt_nil()] following the first >>>>>>>>>>>> [then] in >>>>>>>>>>>> the function body. The error message says >>>>>>>>>>>> >>>>>>>>>>>> the dynamic expression cannot be assigned the type >>>>>>>>>>>> [S2EVar(5492)]. >>>>>>>>>>>> [...] mismatch of sorts in unification: >>>>>>>>>>>> The sort of variable is: S2RTbas(S2RTBASimp(1; t@ype)) >>>>>>>>>>>> The sort of solution is: S2RTbas(S2RTBASimp(2; viewtype)) >>>>>>>>>>>> [...] mismatch of static terms (tyleq): >>>>>>>>>>>> The actual term is: S2Eapp(S2Ecst(stream_vt_con); S2EVar(5495)) >>>>>>>>>>>> The needed term is: S2EVar(5492) >>>>>>>>>>>> >>>>>>>>>>>> (There are further errors of the same form.) Is the culprit >>>>>>>>>>>> that [stream_vt] of a nonlinear datatype requires some special >>>>>>>>>>>> care? The >>>>>>>>>>>> version with [stream_vt_make_nil()] instead of explicit [$ldelay] >>>>>>>>>>>> works so >>>>>>>>>>>> the error ought to be subtle. >>>>>>>>>>>> >>>>>>>>>>>> Best wishes, >>>>>>>>>>>> August >>>>>>>>>>>> >>>>>>>>>>>> Den söndag 5 mars 2017 kl. 23:58:35 UTC+1 skrev gmhwxi: >>>>>>>>>>>>> >>>>>>>>>>>>> Yes, you definitely got it :) >>>>>>>>>>>>> >>>>>>>>>>>>> Stream_vt is very memory-frugal. >>>>>>>>>>>>> >>>>>>>>>>>>> Haskell relies on deforestation (complex complier optimization) >>>>>>>>>>>>> to reduce memory usage of lazy evaluation. In ATS, >>>>>>>>>>>>> deforestation is >>>>>>>>>>>>> not supported. Instead, the programmer needs to recycle memory >>>>>>>>>>>>> explicitly. >>>>>>>>>>>>> >>>>>>>>>>>>> Compared to Haskell, corresponding code using stream_vt in ATS >>>>>>>>>>>>> can be >>>>>>>>>>>>> much more efficient both time-wise and memory-wise. >>>>>>>>>>>>> >>>>>>>>>>>>> For instance, the following example (for computing Mersenne >>>>>>>>>>>>> primes) can >>>>>>>>>>>>> run for days without run-time GC: >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> https://github.com/githwxi/ATS-Postiats/blob/master/doc/EXAMPLE/RosettaCode/Lucas-Lehmer_test2.dats >>>>>>>>>>>>> >>>>>>>>>>>>> It convincingly attests to the power of linear streams. >>>>>>>>>>>>> >>>>>>>>>>>>> Cheers! >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On Sun, Mar 5, 2017 at 5:34 PM, August Alm <augu...@gmail.com> >>>>>>>>>>>>> wrote: >>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks for the tip! I think I understand. I treated $ldelay >>>>>>>>>>>>>> much as a data constructor, so that all streams are equally >>>>>>>>>>>>>> lazy, whereas >>>>>>>>>>>>>> there are in fact many ways to sequence into thunks. Let me give >>>>>>>>>>>>>> an example >>>>>>>>>>>>>> to anchor the discussion. Both the following implementations of >>>>>>>>>>>>>> a >>>>>>>>>>>>>> map-template for linear streams typecheck: >>>>>>>>>>>>>> >>>>>>>>>>>>>> fun {a, b: t0ype} >>>>>>>>>>>>>> map_make_cons >>>>>>>>>>>>>> ( xs: stream_vt(a) >>>>>>>>>>>>>> , f: a -> b >>>>>>>>>>>>>> ) : stream_vt(b) = >>>>>>>>>>>>>> case !xs of >>>>>>>>>>>>>> | ~stream_vt_nil() => stream_vt_make_nil() >>>>>>>>>>>>>> | ~stream_vt_cons(x, xs1) => >>>>>>>>>>>>>> stream_vt_make_cons(f(x), map_make_cons(xs1, f)) >>>>>>>>>>>>>> >>>>>>>>>>>>>> fun {a, b: t0ype} >>>>>>>>>>>>>> map_ldelay >>>>>>>>>>>>>> ( xs: stream_vt(a) >>>>>>>>>>>>>> , f: a -> b >>>>>>>>>>>>>> ) : stream_vt(b) = >>>>>>>>>>>>>> $ldelay >>>>>>>>>>>>>> ( case !xs of >>>>>>>>>>>>>> | ~stream_vt_nil() => stream_vt_nil() >>>>>>>>>>>>>> | ~stream_vt_cons(x, xs1) => >>>>>>>>>>>>>> stream_vt_cons(f(x), map_ldelay(xs1, f)) >>>>>>>>>>>>>> , ~xs >>>>>>>>>>>>>> ) >>>>>>>>>>>>>> >>>>>>>>>>>>>> The second is maximally lazy. The first, [map_make_cons] is >>>>>>>>>>>>>> less lazy because checking the case-conditions is not delayed. >>>>>>>>>>>>>> My code was >>>>>>>>>>>>>> like the first example, only much more was going on inside the >>>>>>>>>>>>>> case >>>>>>>>>>>>>> expressions. Is that a correct assessment? >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Den söndag 5 mars 2017 kl. 04:07:42 UTC+1 skrev gmhwxi: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> BTW, it seems you don't need to do much to fix the issue. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Basically, you just do >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> 1) Put the body of parse_entry into $ldelay(...) >>>>>>>>>>>>>>> 2) Change stream_vt_make_cons into stream_vt_cons >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> There may be a few other things but they should all be >>>>>>>>>>>>>>> very minor. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On Saturday, March 4, 2017 at 9:47:07 PM UTC-5, gmhwxi wrote: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I took a glance at your code. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I noticed a very common mistake involving the use of >>>>>>>>>>>>>>>> stream (or stream_vt). Basically, the way stream is used >>>>>>>>>>>>>>>> in your code is like the way list is used. This causes the >>>>>>>>>>>>>>>> stack issue you encountered. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Say that you have a function that returns a stream. In >>>>>>>>>>>>>>>> nearly >>>>>>>>>>>>>>>> all cases, the correct way to implement such a function >>>>>>>>>>>>>>>> should >>>>>>>>>>>>>>>> use the following style: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> fun foo(...): stream_vt(...) = $ldelay >>>>>>>>>>>>>>>> ( >>>>>>>>>>>>>>>> ... >>>>>>>>>>>>>>>> ) >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> The idea is that 'foo' should return in O(1) time. The body >>>>>>>>>>>>>>>> of $ldelay >>>>>>>>>>>>>>>> is only evaluated with the first element of the returned >>>>>>>>>>>>>>>> stream is neede. >>>>>>>>>>>>>>>> Sometimes, this is call full laziness. Without full >>>>>>>>>>>>>>>> laziness, a stream may >>>>>>>>>>>>>>>> behave like a list, defeating the very purpose of using a >>>>>>>>>>>>>>>> stream. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On Saturday, March 4, 2017 at 7:27:03 PM UTC-5, August Alm >>>>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I've spent few hours trying to figure out how to make >>>>>>>>>>>>>>>>> proper use of npm and gave up--for now. If the project turns >>>>>>>>>>>>>>>>> into something >>>>>>>>>>>>>>>>> more serious (i.e., useful to others) then I will have >>>>>>>>>>>>>>>>> another go at it. >>>>>>>>>>>>>>>>> For now my naive attempts at making effective use of linear >>>>>>>>>>>>>>>>> streams can be >>>>>>>>>>>>>>>>> witnessed at GitHub: >>>>>>>>>>>>>>>>> https://github.com/August-Alm/ats_csv_lexer Any and all >>>>>>>>>>>>>>>>> comments on how to improve are appreciated. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Best wishes, August. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Den fredag 3 mars 2017 kl. 23:57:54 UTC+1 skrev gmhwxi: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> One possibility is to build a npm package and then >>>>>>>>>>>>>>>>>> publish it. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> If you go to https://www.npmjs.com/ and seach for >>>>>>>>>>>>>>>>>> 'atscntrb'. You can find >>>>>>>>>>>>>>>>>> plenty packages. You may need to install npm first. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> If you do build a npm package, I suggest that you choose >>>>>>>>>>>>>>>>>> a name space for >>>>>>>>>>>>>>>>>> yourself. E.g., atscntrb-a?a-..., where ? is the first >>>>>>>>>>>>>>>>>> letter of your middle name. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On Fri, Mar 3, 2017 at 5:48 PM, August Alm < >>>>>>>>>>>>>>>>>> augu...@gmail.com> wrote: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> How would I best share larger code portions? I have no >>>>>>>>>>>>>>>>>>> concerns about my making my mistakes public, heh. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I believe everything is lazy as-is (all data is >>>>>>>>>>>>>>>>>>> [stream_vt("sometype")]). And I've tried to write >>>>>>>>>>>>>>>>>>> tail-recursive functional >>>>>>>>>>>>>>>>>>> code. The algorithm is based on two mutually recursing >>>>>>>>>>>>>>>>>>> functions, "fun ... >>>>>>>>>>>>>>>>>>> and ..", similar to how you did things in your csv-parser >>>>>>>>>>>>>>>>>>> (thanks for >>>>>>>>>>>>>>>>>>> pointing out that piece of code). However, I cannot set >>>>>>>>>>>>>>>>>>> them up with "fn* >>>>>>>>>>>>>>>>>>> .. and .." to enforce a local jump because they call each >>>>>>>>>>>>>>>>>>> other in a too >>>>>>>>>>>>>>>>>>> intertwined way. Might that be it? >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Den fredag 3 mars 2017 kl. 23:32:15 UTC+1 skrev gmhwxi: >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> You are welcome! >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Since I have not seen your code, I could only guess :) >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Usually, what you described can be fixed by using >>>>>>>>>>>>>>>>>>>> tail-recursion, or >>>>>>>>>>>>>>>>>>>> by using lazy-evaluation. The former approach is >>>>>>>>>>>>>>>>>>>> straightforward. You >>>>>>>>>>>>>>>>>>>> just need to identify the function or functions that >>>>>>>>>>>>>>>>>>>> cause the deep stack >>>>>>>>>>>>>>>>>>>> usage. Then try to rewrite using tail-recursion. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On Fri, Mar 3, 2017 at 5:25 PM, August Alm < >>>>>>>>>>>>>>>>>>>> augu...@gmail.com> wrote: >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Hi! >>>>>>>>>>>>>>>>>>>>> I had indeed made a logical error that caused any >>>>>>>>>>>>>>>>>>>>> stream with "carriage return" followed by "newline" to >>>>>>>>>>>>>>>>>>>>> recurse >>>>>>>>>>>>>>>>>>>>> indefinitely. Thank you for your patience and pedagogical >>>>>>>>>>>>>>>>>>>>> instincts, >>>>>>>>>>>>>>>>>>>>> Professor! There is still some issue though, one that I >>>>>>>>>>>>>>>>>>>>> believe is more >>>>>>>>>>>>>>>>>>>>> subtle. I fixed the logical error and my algorithm now >>>>>>>>>>>>>>>>>>>>> handles all the test >>>>>>>>>>>>>>>>>>>>> cases you suggested. However, when fed an actual CSV-file >>>>>>>>>>>>>>>>>>>>> with a thousand >>>>>>>>>>>>>>>>>>>>> rows and about 300 columns it still segfaults--unless I >>>>>>>>>>>>>>>>>>>>> manually increase >>>>>>>>>>>>>>>>>>>>> the stack space on my computer! I don't know exactly >>>>>>>>>>>>>>>>>>>>> where the critical >>>>>>>>>>>>>>>>>>>>> limit is, but increasing it from 8192 kbytes to 65536 >>>>>>>>>>>>>>>>>>>>> certainly did the >>>>>>>>>>>>>>>>>>>>> trick. The whole file parsed without problem, and rather >>>>>>>>>>>>>>>>>>>>> quickly at that. >>>>>>>>>>>>>>>>>>>>> It seems my algorithm makes too much use of stack >>>>>>>>>>>>>>>>>>>>> allocation and that I may >>>>>>>>>>>>>>>>>>>>> have to rethink some of my (would-be) optimization >>>>>>>>>>>>>>>>>>>>> choices. >>>>>>>>>>>>>>>>>>>>> Best wishes, >>>>>>>>>>>>>>>>>>>>> August >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Den fredag 3 mars 2017 kl. 15:22:00 UTC+1 skrev gmhwxi: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Now you may do the following tests: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Try: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> val ins = streamize_string_char("a;b") // should work >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Try: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> val ins = streamize_string_char("a;b\n") // may not >>>>>>>>>>>>>>>>>>>>>> work >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Try: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> val ins = streamize_string_char("a;b\015\012") // >>>>>>>>>>>>>>>>>>>>>> should cause crash >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> On Thursday, March 2, 2017 at 9:21:21 PM UTC-5, >>>>>>>>>>>>>>>>>>>>>> gmhwxi wrote: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> When tried, I saw the following 5 chars (ascii) in >>>>>>>>>>>>>>>>>>>>>>> small.csv: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 97 >>>>>>>>>>>>>>>>>>>>>>> 59 >>>>>>>>>>>>>>>>>>>>>>> 98 >>>>>>>>>>>>>>>>>>>>>>> 13 >>>>>>>>>>>>>>>>>>>>>>> 10 >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> My testing code: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> #include"share/atspre_staload.hats" >>>>>>>>>>>>>>>>>>>>>>> #include"share/HATS/atspre_staload_libats_ML.hats" >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> implement main0 () = { >>>>>>>>>>>>>>>>>>>>>>> val inp = fileref_open_exn("small.csv", >>>>>>>>>>>>>>>>>>>>>>> file_mode_r) >>>>>>>>>>>>>>>>>>>>>>> val ins = streamize_fileref_char(inp) >>>>>>>>>>>>>>>>>>>>>>> val ins = stream2list_vt(ins) >>>>>>>>>>>>>>>>>>>>>>> val ins = g0ofg1(list_vt2t(ins))97 >>>>>>>>>>>>>>>>>>>>>>> val ( ) = println! ("length(ins) = ", length(ins)) >>>>>>>>>>>>>>>>>>>>>>> val ( ) = (ins).foreach()(lam c => >>>>>>>>>>>>>>>>>>>>>>> println!(char2int0(c))) >>>>>>>>>>>>>>>>>>>>>>> (* >>>>>>>>>>>>>>>>>>>>>>> val lexed = lex_csv(true, ';', ins) >>>>>>>>>>>>>>>>>>>>>>> *) >>>>>>>>>>>>>>>>>>>>>>> val () = fileref_close(inp) >>>>>>>>>>>>>>>>>>>>>>> (* >>>>>>>>>>>>>>>>>>>>>>> val h = (lexed.head()) >>>>>>>>>>>>>>>>>>>>>>> val- CSV_Field(r) = h >>>>>>>>>>>>>>>>>>>>>>> val a = r.csvFieldContent >>>>>>>>>>>>>>>>>>>>>>> val () = println!(a) >>>>>>>>>>>>>>>>>>>>>>> *) >>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> On Thu, Mar 2, 2017 at 9:13 PM, August Alm <...> >>>>>>>>>>>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Just "a;b", or? (Attached.) >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Den fredag 3 mars 2017 kl. 03:03:08 UTC+1 skrev >>>>>>>>>>>>>>>>>>>>>>>> gmhwxi: >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> I suspect that the file you used contains other >>>>>>>>>>>>>>>>>>>>>>>>> characters. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> What is in "small.csv"? >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Mar 2, 2017 at 8:52 PM, August Alm <...> >>>>>>>>>>>>>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> The file compiles (I've tried a few compiler >>>>>>>>>>>>>>>>>>>>>>>>>> options) and "gdb run" yields >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Program received signal SIGSEGV, Segmentation >>>>>>>>>>>>>>>>>>>>>>>>>> fault. >>>>>>>>>>>>>>>>>>>>>>>>>> 0x00007ffff783eea5 in _int_malloc >>>>>>>>>>>>>>>>>>>>>>>>>> (av=0x7ffff7b6a620 <main_arena>, bytes=16) at >>>>>>>>>>>>>>>>>>>>>>>>>> malloc.c:3790 >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> The frames 0-3 involve allocation functions that >>>>>>>>>>>>>>>>>>>>>>>>>> are not particular to my file. Frame 4 says: >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> #4 __patsfun_28__28__14 (arg0=<optimized >>>>>>>>>>>>>>>>>>>>>>>>>> out>, env1=0x605540, env0=10 '\n') at >>>>>>>>>>>>>>>>>>>>>>>>>> csv_lexer_dats.c:9023 >>>>>>>>>>>>>>>>>>>>>>>>>> 9023 ATSINSmove_con1_new(tmpret63__14, >>>>>>>>>>>>>>>>>>>>>>>>>> postiats_tysum_7) ; >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> My not-so-educated guess is that this refers to >>>>>>>>>>>>>>>>>>>>>>>>>> making a cons-cell of a stream. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> But: How can my function do just fine when >>>>>>>>>>>>>>>>>>>>>>>>>> manually fed >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> cons('a', cons( ';', sing('b'))): >>>>>>>>>>>>>>>>>>>>>>>>>> stream_vt(char), >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> but segfault when I use [streamize_fileref_char] >>>>>>>>>>>>>>>>>>>>>>>>>> to construct the very same stream from the string >>>>>>>>>>>>>>>>>>>>>>>>>> "a;b" in a file? Where is >>>>>>>>>>>>>>>>>>>>>>>>>> the room for an infinite recursion in that? >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Thank you, >>>>>>>>>>>>>>>>>>>>>>>>>> August >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Den torsdag 2 mars 2017 kl. 23:04:35 UTC+1 skrev >>>>>>>>>>>>>>>>>>>>>>>>>> August Alm: >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Hi! >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> I'm in over my head and tried writing a >>>>>>>>>>>>>>>>>>>>>>>>>>> CSV-parser using linear lazy streams. My code thus >>>>>>>>>>>>>>>>>>>>>>>>>>> far is 600 lines and >>>>>>>>>>>>>>>>>>>>>>>>>>> almost to my own surprise I get it to compile! >>>>>>>>>>>>>>>>>>>>>>>>>>> However, there is something >>>>>>>>>>>>>>>>>>>>>>>>>>> fishy because I get a segfault when applying my >>>>>>>>>>>>>>>>>>>>>>>>>>> program to an actual >>>>>>>>>>>>>>>>>>>>>>>>>>> CSV-file. I've been trying to debug using gdb but >>>>>>>>>>>>>>>>>>>>>>>>>>> the fault eludes me. >>>>>>>>>>>>>>>>>>>>>>>>>>> Since I don't expect anyone to mull through 600 >>>>>>>>>>>>>>>>>>>>>>>>>>> lines of code, I am hoping >>>>>>>>>>>>>>>>>>>>>>>>>>> these code snippets are enough for one of you guys >>>>>>>>>>>>>>>>>>>>>>>>>>> to give me some advice. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> This code executes just fine: >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> implement main0 () = { >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> val test = stream_vt_make_cons( >>>>>>>>>>>>>>>>>>>>>>>>>>> 'a', >>>>>>>>>>>>>>>>>>>>>>>>>>> stream_vt_make_cons( >>>>>>>>>>>>>>>>>>>>>>>>>>> ';', >>>>>>>>>>>>>>>>>>>>>>>>>>> stream_vt_make_sing('b'))) (* the stream >>>>>>>>>>>>>>>>>>>>>>>>>>> ('a', ';', 'b') *) >>>>>>>>>>>>>>>>>>>>>>>>>>> val lexed = lex_csv(true, ';', test) >>>>>>>>>>>>>>>>>>>>>>>>>>> val h = (lexed.head()) >>>>>>>>>>>>>>>>>>>>>>>>>>> val- CSV_Field(r) = h >>>>>>>>>>>>>>>>>>>>>>>>>>> val a = r.csvFieldContent >>>>>>>>>>>>>>>>>>>>>>>>>>> val () = println!(a) >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Here [lex_csv] is my 600-line alogrithm. It >>>>>>>>>>>>>>>>>>>>>>>>>>> reads a [stream_vt(char)] and gives back a >>>>>>>>>>>>>>>>>>>>>>>>>>> [stream_vt(CSVEntry)], where >>>>>>>>>>>>>>>>>>>>>>>>>>> [CSVEntry] is a record type, one of whose fields is >>>>>>>>>>>>>>>>>>>>>>>>>>> [CSVFieldContent]. When >>>>>>>>>>>>>>>>>>>>>>>>>>> executing the program I get "a" printed to the >>>>>>>>>>>>>>>>>>>>>>>>>>> console. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> This code results in a segfault: >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> implement main0 () = { >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> val inp = >>>>>>>>>>>>>>>>>>>>>>>>>>> fileref_open_exn("small.csv", file_mode_r) >>>>>>>>>>>>>>>>>>>>>>>>>>> val ins = streamize_fileref_char(inp) >>>>>>>>>>>>>>>>>>>>>>>>>>> val lexed = lex_csv(true, ';', ins) >>>>>>>>>>>>>>>>>>>>>>>>>>> val () = fileref_close(inp) >>>>>>>>>>>>>>>>>>>>>>>>>>> val h = (lexed.head()) >>>>>>>>>>>>>>>>>>>>>>>>>>> val- CSV_Field(r) = h >>>>>>>>>>>>>>>>>>>>>>>>>>> val a = r.csvFieldContent >>>>>>>>>>>>>>>>>>>>>>>>>>> val () = println!(a) >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> The file "small.csv" only contains the string >>>>>>>>>>>>>>>>>>>>>>>>>>> "a;b". Hence I would expect this code to give the >>>>>>>>>>>>>>>>>>>>>>>>>>> result as the previous >>>>>>>>>>>>>>>>>>>>>>>>>>> one! But, it doesn't just return something else, it >>>>>>>>>>>>>>>>>>>>>>>>>>> segfaults. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> gdb indicates there is a malloc problem having >>>>>>>>>>>>>>>>>>>>>>>>>>> to do with "GC_clear_stack_inner", in case that's >>>>>>>>>>>>>>>>>>>>>>>>>>> helpful. (I'm a >>>>>>>>>>>>>>>>>>>>>>>>>>> mathematician who recently left academia after >>>>>>>>>>>>>>>>>>>>>>>>>>> postdoc and decided to teach >>>>>>>>>>>>>>>>>>>>>>>>>>> myself programming to become more useful outside of >>>>>>>>>>>>>>>>>>>>>>>>>>> academia; hence I >>>>>>>>>>>>>>>>>>>>>>>>>>> understand type systems and the like--the mathy >>>>>>>>>>>>>>>>>>>>>>>>>>> stuff--a lot better than I >>>>>>>>>>>>>>>>>>>>>>>>>>> understand memory allocation and other stuff that >>>>>>>>>>>>>>>>>>>>>>>>>>> most programmers are >>>>>>>>>>>>>>>>>>>>>>>>>>> supposed to be confident with.) >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> What could be the problem here? >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Best wishes, >>>>>>>>>>>>>>>>>>>>>>>>>>> August >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>>>>>>>>>>>> You received this message because you are >>>>>>>>>>>>>>>>>>>>>>>>>> subscribed to the Google Groups "ats-lang-users" >>>>>>>>>>>>>>>>>>>>>>>>>> group. >>>>>>>>>>>>>>>>>>>>>>>>>> To unsubscribe from this group and stop receiving >>>>>>>>>>>>>>>>>>>>>>>>>> emails from it, send an email to >>>>>>>>>>>>>>>>>>>>>>>>>> ats-lang-user...@googlegroups.com. >>>>>>>>>>>>>>>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>>>>>>>>>>>>>>> ats-lan...@googlegroups.com. >>>>>>>>>>>>>>>>>>>>>>>>>> Visit this group at >>>>>>>>>>>>>>>>>>>>>>>>>> https://groups.google.com/group/ats-lang-users. >>>>>>>>>>>>>>>>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>>>>>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/69535c5c-eac3-472c-bb39-062ad4708a72%40googlegroups.com >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/69535c5c-eac3-472c-bb39-062ad4708a72%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>>>>>>>>>>>>>>>>>>>> . >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>>>>>>>>>> You received this message because you are >>>>>>>>>>>>>>>>>>>>>>>> subscribed to the Google Groups "ats-lang-users" group. >>>>>>>>>>>>>>>>>>>>>>>> To unsubscribe from this group and stop receiving >>>>>>>>>>>>>>>>>>>>>>>> emails from it, send an email to >>>>>>>>>>>>>>>>>>>>>>>> ats-lang-user...@googlegroups.com. >>>>>>>>>>>>>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>>>>>>>>>>>>> ats-lan...@googlegroups.com. >>>>>>>>>>>>>>>>>>>>>>>> Visit this group at >>>>>>>>>>>>>>>>>>>>>>>> https://groups.google.com/group/ats-lang-users. >>>>>>>>>>>>>>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>>>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/e608c7bb-42ce-457b-a606-9fe3525f801d%40googlegroups.com >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/e608c7bb-42ce-457b-a606-9fe3525f801d%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>>>>>>>>>>>>>>>>>> . >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>>>>>>> You received this message because you are subscribed >>>>>>>>>>>>>>>>>>>>> to the Google Groups "ats-lang-users" group. >>>>>>>>>>>>>>>>>>>>> To unsubscribe from this group and stop receiving >>>>>>>>>>>>>>>>>>>>> emails from it, send an email to >>>>>>>>>>>>>>>>>>>>> ats-lang-user...@googlegroups.com. >>>>>>>>>>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>>>>>>>>>> ats-lan...@googlegroups.com. >>>>>>>>>>>>>>>>>>>>> Visit this group at >>>>>>>>>>>>>>>>>>>>> https://groups.google.com/group/ats-lang-users. >>>>>>>>>>>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/34dfad01-9bd4-464f-9ccd-6dfae8207f4c%40googlegroups.com >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/34dfad01-9bd4-464f-9ccd-6dfae8207f4c%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>>>>>>>>>>>>>>> . >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>>>>> You received this message because you are subscribed to >>>>>>>>>>>>>>>>>>> the Google Groups "ats-lang-users" group. >>>>>>>>>>>>>>>>>>> To unsubscribe from this group and stop receiving emails >>>>>>>>>>>>>>>>>>> from it, send an email to >>>>>>>>>>>>>>>>>>> ats-lang-user...@googlegroups.com. >>>>>>>>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>>>>>>>> ats-lan...@googlegroups.com. >>>>>>>>>>>>>>>>>>> Visit this group at >>>>>>>>>>>>>>>>>>> https://groups.google.com/group/ats-lang-users. >>>>>>>>>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/c2f9d2b7-61f5-4142-b8b2-930147ee589d%40googlegroups.com >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/c2f9d2b7-61f5-4142-b8b2-930147ee589d%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>>>>>>>>>>>>> . >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>> You received this message because you are subscribed to the >>>>>>>>>>>>>> Google Groups "ats-lang-users" group. >>>>>>>>>>>>>> To unsubscribe from this group and stop receiving emails from >>>>>>>>>>>>>> it, send an email to ats-lang-user...@googlegroups.com. >>>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>>> ats-lan...@googlegroups.com. >>>>>>>>>>>>>> Visit this group at >>>>>>>>>>>>>> https://groups.google.com/group/ats-lang-users. >>>>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/d78409e2-aff1-4b96-98f3-eb3a5d20ff95%40googlegroups.com >>>>>>>>>>>>>> >>>>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/d78409e2-aff1-4b96-98f3-eb3a5d20ff95%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>>>>>>>> . >>>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> -- >>>>>>>>>>>> You received this message because you are subscribed to the >>>>>>>>>>>> Google Groups "ats-lang-users" group. >>>>>>>>>>>> To unsubscribe from this group and stop receiving emails from >>>>>>>>>>>> it, send an email to ats-lang-user...@googlegroups.com. >>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>> ats-lan...@googlegroups.com. >>>>>>>>>>>> Visit this group at >>>>>>>>>>>> https://groups.google.com/group/ats-lang-users. >>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/716c8c61-d535-412d-8584-d4030d20801d%40googlegroups.com >>>>>>>>>>>> >>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/716c8c61-d535-412d-8584-d4030d20801d%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>>>>>> . >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "ats-lang-users" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to ats-lang-user...@googlegroups.com. >>>> To post to this group, send email to ats-lan...@googlegroups.com. >>>> Visit this gro >>> >>> -- You received this message because you are subscribed to the Google Groups "ats-lang-users" group. To unsubscribe from this group and stop receiving emails from it, send an email to ats-lang-users+unsubscr...@googlegroups.com. To post to this group, send email to ats-lang-users@googlegroups.com. Visit this group at https://groups.google.com/group/ats-lang-users. To view this discussion on the web visit https://groups.google.com/d/msgid/ats-lang-users/67332c80-cfb4-4349-a7de-2326d99b037c%40googlegroups.com.