freenode/#lisp - IRC Chatlog
Search
0:37:47
Josh_2
The question isn't write Let*, although that is kewl, It's to convert a let* form into lambdas
0:39:10
pjb
(macroexpand-1 '(let* ((x 6)(y (* x x))) (+ x y))) -> ((lambda (y) (let* ((x 6)) (+ x y))) (* x x)) ; t
0:39:34
pjb
(macroexpand-1 '(let* ((x 6)) (+ x y))) #| --> ((lambda (x) (let* nil (+ x y))) 6) ; t |#
0:46:50
moldybits
Josh_2: x should be bound to 6. y should be bound to (* x x), where x is visible. (+ x y) should be evaluated where x and y are visible
0:47:51
aeth
insert a bunch of prints (well, FORMATs) in the middle of your code so you can see where everything is at each step
1:01:50
aeth
bt:with-lock-held isn't used, but you can still read/write from multiple threads (I'm guessing)
1:07:48
gabbiel
oh I see. I made my own queue implementation, but I never considered threading as I've never really played with that
1:34:12
aeth
gabbiel: Generally, you don't have to think about it, you just pair it with a lock and expect the user to use bt:with-lock-held around it.
1:38:48
drmeister
Does anyone use 'fork' in their day jobs? I'm trying to figure out how to definitively tell if a forked child has crashed. In clasp we are building using 'fork' to compile-file source files and I need to figure out if a child has crashed in C++.
1:40:10
pjb
drmeister: you would establish a pipe between the monitored process and the monitoring process, you exchange 1-byte sized messages, and when you get a SIGPIPE, you know the remote process is dead.
1:41:06
pjb
drmeister: if you need less precise monitoring, between a parent and a children, you can use wait/wait3/wait4/waitpid.
1:41:32
pjb
(and anyways, a parent should use one of those wait functions to reap the children so they don't become zombies).
1:42:18
drmeister
I am using wait and monitoring what signals the children get. But I'm still seeing crashes where the child processes just sit there crashed.
1:43:45
drmeister
Ok, I'll think on that. I was using select/read to try and read all of the output that the children were generating into the parent - but that turned into a disaster.
1:44:39
pjb
with wait you just need to be careful with the retur values and errors. Normally you will call wait once per children, but if a call fails or is interrupted for signals (to the parent), you will have to call wait more times.
1:44:48
drmeister
Then we figured out that gnu make uses a different strategy with -j<value> - they write into unlinked files and the parent keeps a copy of the fd for the unlinked file.
1:45:34
pjb
drmeister: yes, this is why when monitoring, we use 1-byte messages. reading longuer messages will block.
1:45:41
drmeister
saturn2: A forked clasp child crashes in the llvm code and it sits there using about 50% cpu and as far as I can tell does nothing useful.
1:46:45
drmeister
I want to vacuum up all of the child's output (stdout and stderr - which it looks like I'm doing well now with the unlink'd files) into the parent AND I need to know when a child crashes in llvm (still a problem).
1:50:47
drmeister
This is my code: https://github.com/clasp-developers/clasp/blob/dev/src/lisp/kernel/clasp-builder.lsp#L481
1:51:23
drmeister
But it's "pidgin Common Lisp" - I don't have much of Common Lisp up at this point so I rely on a lot of C++ code.
1:51:57
drmeister
https://github.com/clasp-developers/clasp/blob/dev/src/lisp/kernel/clasp-builder.lsp#L363
1:52:31
drmeister
I thought it would catch every problem a child could have but on macOS I could still see children crash and the parent wasn't aware.
1:53:34
drmeister
We have made a lot of progress with Clasp - it is now failing less than 1% of ANSI tests.
1:54:21
drmeister
I'm in the process of exposing debugging information using DWARF. So you will be able to debug compiled Clasp code using DWARF.
1:57:42
drmeister
We've been bringing a new compiler online that gives us much, much better source location information. It should help debug everything.
1:58:50
aeth
In particular, there might be some interest in using Clasp or ECL with Godot via https://github.com/GodotNativeTools/godot_headers for the next Lisp game jams. I might do my own wrapper of the API. There already is one. https://github.com/borodust/bodge-godot
1:59:03
drmeister
But we've been doing work to keep defcallback happy - so I'll run the tests once my build finishes.
1:59:25
gabbiel
this discussion is relevant to me because I'm going to write a C interpreter and was wondering what would happen when the C program crashes
2:25:33
pjb
drmeister: you will need asynchronous I/O or threads to read both stdout and stderr otherwise you risk blocking in the parent.
3:00:54
drmeister
pjb: We switched to using unlink'd files - that's the approach gnu make uses when you specify -j<#>.
3:01:24
drmeister
So we let the children finish writing into the files and then the parent reads the results out.
3:08:50
ck_
I haven't been here in a long while. What has changed? Has Clasp been finished, can I compute a supermolecule a la carte with it already?
3:23:41
ck_
Common Lisp seems pretty finished. Especially compared to newer languages. I could tell you some stories about clojure meetups...
3:26:02
aeth
What happens is one implementation does an extension and if it's popular it slowly trickles everywhere else, either directly or with a portability library over it. And this slow process just recently has gotten the "package local nicknames" extension in most implementations (at least by users)
3:26:27
aeth
So even the language itself isn't static. Most notably stuff like MOP, CFFI, bordeaux-threads, etc.
3:26:40
drmeister
ck_: Both lldb/gdb and slime. I'm using the standard C++ approach of DWARF metadata and exposing that to slime.
3:26:55
ck_
I already yielded. What I meant with that line is: compared to newer, even lisp-like languages, I very often want my common lisp job back because, comparatively, it is at a much higher level of maturity
9:25:50
LdBeth
If a language is very terse (TECO), where almost every token is one character, is there any possibility benefiting from using a parser generator?
9:45:43
beach
Then it has nothing to do with the tokens themselves, but with the fact that the grammar is very simple too.
9:49:37
beach
Implementing a typical language often consists of defining two separate things, namely a lexer and a parser. The lexer turns sequences of characters into tokens, and the parser turns the sequence of tokens into a parse tree (usually). If the tokens are simple, the lexer is simple. If the grammar for combining tokens into parse trees is simple, then the parser is simple. The two are orthogonal.
9:55:18
aeth
I wonder where optimizations fit. These are especially key when you have a minimal command language where you're supposed to compose things. One case would be +++++ which in a hypothetical simple language taken literally would mean (progn (incf x 1) (incf x 1) (incf x 1) (incf x 1) (incf x 1)) but can be optimized to (incf x 5)
9:55:34
aeth
It seems like this kind of thing could be done at either the lexer or the parser, and would complicate even a seemingly simple language.
9:57:57
beach
The role of the lexer and that of the parser are often blurred. In most real languages, a lexer is in fact not possible as a first step. It has to know the context as defined by the grammar. Also, there are parsing techniques that do not need a lexer at all.
10:29:58
White_Flame
aeth: generally the parser does not optimize. Once you have the parse tree or AST or whatever, then you perform that sort of analysis in the compiler
11:32:18
White_Flame
I guess that depends on if that concatenation is a lexical construct, a parser construct, or neither
11:33:10
White_Flame
obviously your language definition could demand that at any level, or leave it optional for the compiler to optimize. It would be fairly transparent to the actual source code, but not to implementers
12:29:48
ck_
it reminded me to see whether the source is available, or somebody ported it to today's CL