freenode/#sicl - IRC Chatlog
Search
9:50:31
heisig
Hmm, the logs tell me that people care about CALL-NEXT-METHOD with arguments. Dammit, now I have to make it work :)
10:11:05
heisig
I am also proud of how portable it is. My only dependencies are closer-mop and trivial-macroexpand-all.
12:52:49
heisig
Tadaa: https://github.com/marcoheisig/sealable-metaobjects/commit/34b1de37ce38d7ce767f93c2f3e48bf66af07168
12:55:05
heisig
Now the only remaining restriction on generic function inlining is "define all methods in the null lexical environment".
13:26:38
scymtym
heisig: is C-N-M with keyword arguments allowed? from a brief glance, that commit doesn't look like it handles that case
14:44:32
heisig
I still have to add type checks to ensure that the arguments do not change the ordered set of applicable methods.
14:47:52
heisig
This is the code for handling lambda lists, if anyone is interested: https://github.com/marcoheisig/sealable-metaobjects/blob/master/code/lambda-lists.lisp
14:52:45
scymtym
heisig: hm, maybe i'm not seeing it. where are keyword parameter defaults (from the next method) for unsupplied keyword arguments computed?
14:56:00
heisig
The crucial part is here: https://github.com/marcoheisig/sealable-metaobjects/blob/075c2be5942aa9946a411686050d8a2df80fbb2c/code/fast-generic-function.lisp#L192
14:58:18
scymtym
i would have to look at a few macroexpansions, i think. but maybe you can check the result of (defmethod bar ((x integer) &key y z) (list x y z (call-next-method x :y y))) (defmethod bar ((x real) &key (y 3) (z 4)) (list x y z)) (bar 1 :y 2). i believe it should be (1 2 nil (1 2 4))
15:09:27
heisig
scymtym: It produces the correct result. Here is the generated inline lambda for (bar 1 :y 2): https://gist.github.com/marcoheisig/36382e06f6b3a1ec9ce7e6fe2c13c15c
15:21:37
beach
This is great! I can't wait to see all these wonderful techniques gathered together in one (working) implementation. :)
15:25:48
heisig
Now I just need to find a better name than 'fast-generic-function'. Unfortunately 'partially-inlineable-generic-function' is too unwieldy.
15:25:55
scymtym
heisig: i recommend seizing the opportunity and asserting that result in the test suite :)
15:32:02
scymtym
heisig: it seems INLINEABLE-[STANDARD-]GENERIC-FUNCTION should no longer be exported and the README should not mention them after 1d668f36471f9f3250693eff657c96d8418af83d
16:24:22
beach
heisig: Did I understand the paper right in that you think it would be reasonable to add the binary versions of the arithmetic functions using your technique?
16:38:34
beach
OK, so I can't treat the CATCH-INSTRUCTION as a function call at the HIR level. The reason is that the HIR interpreter has to do some weird stuff with the host dynamic environment in the form of calls to CL:CATCH. So it would be to late to assign the continuation output and the new dynamic-environment output in RETURN-VALUE-INSTRUCTIONs following the CATCH-INSTRUCTION.
16:38:36
beach
But it's not a big deal. I'll just process the CATCH-INSTRUCTION in the HIR-to-MIR stage, the result of which does not influence the code interpreted by the HIR interpreter.
16:40:49
beach
Now, the ultimate function that will be called to accomplish what the CATCH-INSTRUCTION does, must create a BLOCK/TAGBODY-ENTRY containing (among other things) the caller stack pointer and the caller frame pointer. I suspect I am going to need ASTs and IR instructions to do that. Otherwise, I would have to write that function in assembler.
16:42:46
beach
So I think I'll need a CALLER-STACK-POINTER-AST, a CALLER-FRAME-POINTER-AST, a CALLER-STACK-POINTER-INSTRUCTION, and a CALLER-FRAME-POINTER-INSTRUCTION.
16:44:11
beach
I think I should, rather than making them SICL specific. I think that because the AST and instruction types we add there are not required to be used by client code, but client code that needs such instructions could be helped by already having them available.
16:46:18
alandipert
i only vaguely understand your predicament, but it sounds like you have an opportunity to either implement something high-level in terms of other relatively high level things, or in terms of something lower level
16:50:06
beach
I think I have worked that one out, and I prefer the high-level route. The way it works is I introduce a "primop" which is just a symbol in a particular package, and it is treated as a special operator. The primop turns into a particular AST during CST-to-AST, and to a particular instruction during AST-to-HIR. In this case, the instruction would then just transparently follow into MIR. In MIR-to-LIR, it would be translated into
16:50:52
beach
The only doubt I have is what package to use for the ASTs and the instructions. Should it be SICL-COMPILER or CLEAVIR-AST and CLEAVIR-IR respectively.
16:52:51
beach
And nothing we put there is required to be used by a client, so it could be seen as an optional service.
16:53:31
alandipert
oh, yes. and didn't you mention previously that you're storing AST by default for debugger use? so that AST could presumably be meaningful without loading SICL-COMPILER
16:54:52
beach
The stages of the compiler, i.e. CST-to-AST, AST-to-HIR, etc., are defined as generic functions that take a CLIENT parameter.
16:55:32
beach
Client code would supply a specific instance of some standard class as the CLIENT argument.
16:56:05
alandipert
i seem to remember from your debugger paper that step-able code is always generated, but only interpreted when the debugger becomes involved... or something to that effect
16:56:08
beach
Then, client code would define methods specialized to that client class in order to customize the behavior of the stages.
16:58:55
beach
But nothing prevents me from moving those to Cleavir, should they turn out to be more generally useful.
17:00:17
beach
In this case, it is just an instruction type: BREAKPOINT-INSTRUCTION, and it is generated by a custom method on AST-to-HIR, specialized to a SICL client instance.
17:03:53
beach
Now I am wondering whether there are any other Common Lisp compilers written in this way. And if not, whether it has to do with bootstrapping issues.
17:05:28
beach
I keep thinking that SBCL is perhaps the implementation that has the highest fraction of its code written in Common Lisp. But even the SBCL compiler does not use generic functions, so it would be very hard to customize it for use by other implementations.
17:07:37
beach
I mean, since it was not designed to be implementation independent, there is probably lots and lots of code that is SBCL specific, so that is already a reason why it would be hard to customize for other implementations.
17:07:38
beach
But I am also wondering, more generally, how one would go about writing a Common Lisp compiler that could be customized like Cleavir, but without using generic functions and standard classes.
17:08:08
alandipert
i have a friend implementing a scheme -> js compiler, and he's bootstrapping to the point of hosting the nanopass framework. as i understand, the nanopass framework defines many intermediate languages in terms of syntax-rules patterns
17:08:35
alandipert
in a way, these patterns are "classes", and so maybe the overall structural affordances are similar
17:09:01
alandipert
the biggest difference i perceive is how each stage is "closed", though. since you can't add a rule to a syntax-rules block post-hoc
17:10:26
alandipert
but while the dispatch there is closed, the structure produced by each pass is open to subsequent interpretation
17:10:36
beach
So you wouldn't have the equivalent of an auxiliary method specialized to a particular client-supplied syntax rule.
17:11:43
alandipert
well, i don't think the client can supply a new rule without supplying a new pass
17:13:03
Bike
you could have (foo ...) expand into (%foo ... foo-impl) which then expands into (... (foo-impl ...) ...), maybe?
17:15:23
alandipert
i don't know, but now that i know a bit more about CLOS, i think of nanopass as a kind of degenerate CLOS, situated in the compiler domain
17:17:24
alandipert
i really want to understand it better but i find scheme so hard to get into, personally
17:23:56
alandipert
i couldn't tell, i'm so inured to the nuances of CL at this point. when i read large-scale scheme programs or about nanopass, it strikes me more as just a different set of tradeoffs, with a static bent
17:24:42
beach
Sure, I think the fact that the language is simpler automatically makes applications written in it more complicated.
17:25:09
alandipert
my interest in nanopass is abiding though, if there's anything in scheme i hope to understand some day, it's that
17:25:33
alandipert
i'm interested in it now because i don't have CLOS in JACL yet and it might be a sound structural basis for compiler bootstrap
17:26:46
alandipert
the tl;dr on it is andy keep and kent dybvig developed nanopass as a teaching aid for a compilers course at IU in the 2000s. then later keep went to work with dybvig and they converted the organization of the commercial scheme, Chez, to use nanopass
17:29:50
alandipert
i believe there are even shorter papers that describe the academic version, but i don't have them handy
17:32:06
alandipert
np. i'm looking forward to possibly hanging out with andy at ELS, i used to live near him and get together regularly. really smart and nice person, highly tolerant of my CL affliction
17:35:58
alandipert
i have to go but i wanted to share this because i'm excited about it, i've started to port JACL's reader tests (currently written in JS) to JACL: https://gist.github.com/alandipert/9f86aad6e88ea46658da4e70e1d430ce
17:37:31
alandipert
you too! thanks also Bike for setting me straight on decl. identifiers, ASYNC in (declare (async)) there is JACL:ASYNC