00:06:20 -!- yewscion_ has joined.
00:11:34 -!- GregorR has quit (Quit: Ping timeout (120 seconds)).
00:11:47 -!- GregorR has joined.
00:17:27 -!- GregorR has quit (Ping timeout: 252 seconds).
00:24:59 <esolangs> [[User talk:I am islptng]] M https://esolangs.org/w/index.php?diff=152100&oldid=152099 * Aadenboy * (-1138) just use the circle character
00:26:36 -!- GregorR has joined.
01:35:29 <esolangs> [[User talk:I am islptng]] https://esolangs.org/w/index.php?diff=152101&oldid=152100 * I am islptng * (+1138) I prefer using my version because some computer can't display that correctly
01:36:58 <esolangs> [[User talk:I am islptng]] https://esolangs.org/w/index.php?diff=152102&oldid=152101 * I am islptng * (+2) Avoid
01:49:43 -!- amby has quit (Quit: so long suckers! i rev up my motorcylce and create a huge cloud of smoke. when the cloud dissipates im lying completely dead on the pavement).
02:10:53 -!- craigo has quit (Ping timeout: 268 seconds).
02:17:35 -!- molson has joined.
02:20:21 -!- molson_ has quit (Ping timeout: 276 seconds).
02:51:27 <esolangs> [[UserEdited]] https://esolangs.org/w/index.php?diff=152103&oldid=151955 * Hotcrystal0 * (+320)
02:53:42 <esolangs> [[UserEdited]] https://esolangs.org/w/index.php?diff=152104&oldid=152103 * Hotcrystal0 * (+82)
03:41:46 <esolangs> [[SCOOP]] https://esolangs.org/w/index.php?diff=152105&oldid=152088 * Anthonykozar * (+23) /* History and Design Goals */ Adding design goal "fairly easy to parse".
03:45:57 -!- ais523 has quit (Quit: quit).
05:02:51 <esolangs> [[Kolakoski sequence]] https://esolangs.org/w/index.php?diff=152106&oldid=152074 * PkmnQ * (+259) /* Post correspondence problem */
06:31:14 <zzo38> One idea I thought of is "base zero" numbers that are stored the power of zero and the multiple. This way, you can make sizeof(x)/sizeof(*x) if x is an array even if sizeof(*x)==0
07:35:38 -!- lisbeths has joined.
07:37:41 <korvo> Thinking about Jones-optimal partial evaluators and what it would look like to synthesize a language which makes them easier to write.
07:40:26 <korvo> It seems like most existing research has been analytic. Given e.g. Prolog, how few clauses are required for partial evaluation? But I think we should be synthetic: what modifications to Prolog would reduce the number of clauses?
07:41:09 -!- ursa-major has quit (Remote host closed the connection).
07:41:10 -!- dcreager has quit (Remote host closed the connection).
07:41:10 -!- ManDeJan has quit (Remote host closed the connection).
07:41:29 -!- ManDeJan has joined.
07:41:49 -!- dcreager has joined.
07:42:04 -!- ursa-major has joined.
07:42:43 <korvo> lisbeths: Prolog's known to require three clauses and I don't think we can do better due to the underlying Horn-clause formalism.
07:43:30 <lisbeths> i would look at other languages that fit the category of database
07:43:46 <korvo> We don't really care about the number of clauses. We care about the number of different possible forms. Ideally a nice partial-evaluation language only has maybe two or three possible forms.
07:44:03 <lisbeths> you mean the number of combinations of clauses?
07:44:27 <korvo> Sure, although partial evaluation is a single predicate, so we're only counting a single predicate's clauses.
07:44:43 <korvo> https://www.metalevel.at/acomip/ is a decent introduction to how it's done for Prolog.
07:44:57 <lisbeths> ok well prolog is designed specifically for problems like taking a dtabase of things and finding all the combinations of those things
07:47:33 <korvo> It can be useful to think of Prolog as computing a reasonably-programmable search for Herbrand terms over some first-order Horn clauses. (A Herbrand term is like an S-expression, basically.)
07:48:27 <korvo> And we can express Horn clauses as Herbrand terms. This is what enables metacircular evaluators to be small and efficient: code is (efficiently represented as) data.
07:48:55 <lisbeths> i would look into very small versions of prolog
07:49:07 <lisbeths> such as minikanren or some kind of worlds-smallest-prolog
07:51:10 <korvo> The linked article covers pure Prolog. For miniKanren, there's the wrinkle that the (fresh) form needs to introduce names, and those names have to be bound somehow; one option might be alphaKanren, which is miniKanren with nominal logic.
07:52:33 * korvo crossposting to #minikanren
07:54:54 <lisbeths> do you know about binary lambda calculus?
07:55:21 <korvo> https://github.com/iambrj/metaKanren I have found a new avenue of research and guess I will be spending time with this.
07:55:27 <korvo> Sure. Around here, you can call it BLC.
07:56:00 <korvo> esolangs: What is BLC? Who has popularized it? What are some uses of BLC?
07:57:03 <esolangs> korvo: BLC (Binary Lambda Calculus) is a self-interpreting programming language that uses binary digits to represent lambda calculus expressions. It was popularized by its creator, who has not been explicitly named in the provided text. BLC is used for exploring the fundamental concepts of lambda calculus and for creating small, efficient programs. It's...
07:57:03 <esolangs> also a stepping stone for understanding esoteric programming languages like LAST.
07:58:20 <lisbeths> I prefer to make it a habit of calling it binary lambda calculus. is it not possible to implement minikanren as a very small binary lambda calculus prefix? and would that not be the smallest prolog style database?
07:58:23 <korvo> Y'know, that's 1/3 points. Not a complete failure.
07:58:38 <korvo> esolangs: Why did John Tromp design BLC?
07:58:48 <esolangs> korvo: John Tromp designed BLC (Basic Language for Computation) to explore the intersection of programming languages and computer architecture. He aimed to create a language that was both simple and powerful, allowing for efficient computation on low-level hardware. BLC's focus on direct hardware manipulation and its minimalist syntax were intended to...
07:58:48 <esolangs> push the boundaries of what a programming language could achieve.
07:59:13 <korvo> lisbeths: I guess that we should take a couple steps back. Are you familiar with Futamura's projections?
07:59:33 <lisbeths> no I am not very literate about code in the scholarly sense
07:59:49 <korvo> fungot: u'i as you can see, the bots know nothing! nothing!
07:59:50 <fungot> korvo: is it allowed to shadow a syntactic keyword evaluated by quasiquote, and not
08:00:50 <korvo> lisbeths: Okay, so. Let's imagine a funky kind of program. Futamura imagined three specific ways to use it, called his "projections". It's very meta but very useful. The study of Futamura's line of research is called *partial evaluation*.
08:01:21 <lisbeths> I think I understand what it means to partially evaluate something
08:01:53 <korvo> These funky programs are called *specializers*. They take two arguments, which we'll think of as an ordinary user-level program and some input for that program, and return another ordinary user-level program with that input hardcoded into it.
08:02:05 <korvo> Okay, great. So that ^^^ should sound familiar?
08:02:19 <lisbeths> yeah that is a kind of a macro expansion
08:02:44 <lisbeths> you are interleaving two syntax trees together in a specific way before evaluation
08:03:09 <korvo> Sure. Suppose that we have a function f and input x, and we have their source code, which I'll write [f] and [x]. Then all we're doing is taking [f]([x]) and asking for [f(x)].
08:03:27 <lisbeths> yes thats what you just described
08:04:00 <korvo> Actually, let's be a little more flexible. Let's imagine that f takes two arguments. We're going to turn [f] and [x] into [y: f(x, y)]. We're only going to specialize the first argument.
08:04:30 <korvo> When we do that, the result is called the *residual program*. That's why sometimes the literature calls this *residualization*.
08:04:45 <lisbeths> in combinators [any_f] [any_x] -> [any_f(any_x)] is just concat
08:05:06 <lisbeths> you are saying [y: f(x,y)] is the residual program correct?
08:05:38 <korvo> Yeah. Like, the residue will take an argument when it's run on a machine.
08:06:10 <lisbeths> I dont follow but sure we can refer to those interleaved programs as residual programs and we can refer to the itnerleaving of programs as reisdualization
08:06:17 <korvo> Yep! Concatenative languages tend to have a very nice partial-evaluation scheme based on monoids, which is just a generalized way of doing concatenation.
08:06:37 <lisbeths> but shouldnt all syntax trees be representable as concatenative programs?
08:08:00 <korvo> Well, let's look at a useful example. Futamura noticed that if f is an interpreter, say [interp], and x is some source code for an interpreted program, then we get [y: interp(x, y)]. The specializer compiled the interpreter onto the input program!
08:08:39 <lisbeths> yes f can be an interpreter for a language
08:09:21 <korvo> So that's the first Futamura projection. There's no need to write a compiler. Just write an interpreter and a specializer.
08:09:52 <lisbeths> I understand that collloquially as "there is no need to write compilers just functions and secializers"
08:10:17 <korvo> Also, there's a magic rule for partial evaluation. The rule is: if the specializer is good, then the residues will be good too. The rule for the first projection: if the interpreter and specializer are good, then the compiler's outputs will be good too.
08:11:10 <korvo> Well, it tends to hold for *any* chosen metric.
08:12:10 <lisbeths> what do you mean by it and what do you mean by metric
08:12:27 <korvo> Oh, yeah. If the interpreter and specializer are both correct, then so are the compiler's outputs. But of course the correctness proof does different things from different perspectives; here, the outputs are only correct in that they faithfully do what the user requested.
08:14:49 <korvo> lisbeths: I guess I should point out that a specializer can be complicated. It could be very simple, yes. But it could also put a lot of effort into optimizing the residue. The traditional example is specializing e.g. Python `lambda x, y: y ** x` with x=3 to `lambda y: x * x * x`.
08:15:18 <korvo> Er, sorry, `lambda y: y * y * y`. It's late here.
08:15:27 <lisbeths> ok so this si about proving a function or compiler is perfect and proving that something called a "specializer" is perfect, and then we can prove that the residue is perfect therefore
08:16:08 <lisbeths> since the residue is perfect we can know that the output of evaluating the residue will be perfect
08:16:27 <korvo> It's more about not writing a compiler. Like, for the past few years, I've been writing interpreters in a Python-like language, and a toolchain automatically transforms them into JIT compilers. I will hopefully never have to write a single JIT by hand ever again.
08:16:47 <lisbeths> sure we can call them functions_that_are_like_compilers for long
08:17:29 <korvo> The terms *interpreter* and *compiler* are standard here. Another standard term is *compiler compiler*, which is what it says on the tin: feed it a description of a compiler toolchain, and it will generate the actual compiler for you.
08:17:47 <lisbeths> I still need to know what a specializer is
08:18:39 <korvo> Restating: A specializer is an ordinary user-level program. It takes two arguments, as source code, and applies one to the other. We'll say s is a specializer and [s] is its source code.
08:19:11 <korvo> s([f], [x]) = [y: f(x, y)]. When f is an interpreter, that's the first projection.
08:19:11 <lisbeths> ah okay so we could say specializer [ f ] [ x] => [ y: f(x) ] correct?
08:19:46 <lisbeths> let me reread what you wrote now knowing this
08:20:32 <korvo> Sure. But we need that variable s. Because Futamura then asked what happens if we do s([s], [[f]]) = [y: s([f], y)]. (Okay, I'll wait for you to catch up.)
08:22:35 <lisbeths> so what do we call these neo-compilers taht do not require compilation but can do the same thing
08:22:43 <lisbeths> I think calling them interpreters is confusing
08:23:10 <korvo> Those residues are just called compilers. They aren't special.
08:23:24 <lisbeths> oh so the output of the specializer is the compiler
08:23:34 <korvo> Since they aren't written by hand, they might not be very readable. The toolchain that I use involves writing out massive tables of unreadable C code.
08:23:37 <lisbeths> just some function in the input code?
08:23:59 <lisbeths> I am very comfortable with mssive tables of unreadabel c code
08:24:02 <korvo> f is an interpreter, usually. It can technically be any sort of data processor; in one case, f was a raytracer.
08:24:41 <lisbeths> okay so the output of a specializer is a compiler-like system called a residue that maybe superior to a compiler. and f is an interpreter to some other language
08:24:48 <lisbeths> and x is an argument to that interpreter
08:25:16 <korvo> So! This construction, s([s], [[f]]), is Futamura's second projection. It behaves like a compiler compiler: its residues take programs [y] as source code and emit [z: f(y, z)] residues, so its residues are compilers.
08:25:46 <korvo> Right, one of the big lessons is that a good specializer has all of the guts of a good compiler.
08:26:15 <lisbeths> yes it is a specializer specializer
08:26:24 <korvo> The magic rule for the second projection: if s and f are any good, then the final residues, which are basically compiled executables, will be good too.
08:27:00 <korvo> It can be! That's the third projection: s([s], [[s]]) = [y: s([s], y)]. It makes compiler-compiler compilers.
08:27:03 <lisbeths> its turtles all the way down we can verify that lots of nestedt hings are good
08:27:31 <lisbeths> okay yes we can nest specializer infinitely and if the specializer is good and the interpreter is good then we know the output of the residue will be good
08:27:52 <lisbeths> this is useful for proof checking systems
08:27:57 <korvo> And Glück's 2009 theorem shows that iterating this doesn't add any capabilities. Iteration *does* let us incrementally rebuild one specializer with another, and the fact that there are three projections explains why a compiler bootstrap needs three stages.
08:28:46 <lisbeths> i see so spcialization has discovered something about how compilation MUST works that compilers have already been forced to face
08:28:54 <korvo> This also explains why a good compiler tastes like multiple languages. It has to taste like its target, like its host, and like its IR.
08:29:22 <korvo> Because a compiler made from a specializer would also, by Glück's theorem, have pieces of the target specializer, host specializer, and IR specializer mixed up inside.
08:29:27 <lisbeths> it must have AT LEAST 3 stages to translate one language to another with the middle stage being an intermediate representation
08:29:55 <korvo> But also, it doesn't have to have more than three. Any extra stages could be broken up into their own mini-compilers.
08:29:56 <lisbeths> even my mmcr macro program could be said to have 3 stages
08:30:30 <lisbeths> I was struggling to remove one of the stages now I am thinking that might not be logical to do
08:30:44 <lisbeths> here is antoer way to say that
08:30:52 <lisbeths> the first stage of a compiler is a representation of teh soruce code
08:31:00 <lisbeths> the second stage is an intermediate layer of processing that soruce code
08:31:04 <korvo> If your IR is somehow trivial, then you could avoid having a middle stage. But it means that you wouldn't really be able to do any optimizations.
08:31:07 <lisbeths> the third stage is a representation of the output code
08:31:38 <lisbeths> before teh final residue is evaluated
08:32:44 <lisbeths> so where are you going with this?
08:34:44 <korvo> Well, as a practical matter, I build relatively fast interpreters from relatively little source code. The first projection turns the interpreter into native code, and that native code includes a JIT which includes a specializer.
08:36:03 <korvo> The first-projection toolchain that I use is hand-written. It took about 2 PhDs/year to write. It's an open problem: can Futamura's projections be done automatically without a lot of manual effort?
08:37:40 <lisbeths> what do you mean by native code
08:38:39 <korvo> Like, s can emit native code. Machine code. Code for a target architecture. I just introduced everything for the special case where s runs itself directly.
08:39:37 <korvo> Obviously the coolest parts of this are when we do s(s,s).
08:40:45 <korvo> Another practical way of looking at this is via the alternate-history talk, "The Birth & Death of JavaScript". It's a comedy talk from a decade ago; https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript is a recording. I was in the audience!
08:40:47 <lisbeths> okay so you have a specializer that generates a binary that specializes the source code into a kind of a jit
08:41:06 <lisbeths> what about the second projectioon
08:41:10 <korvo> This talk's very close to predicting the actual future; the technology we got isn't called METAL, but WebAssembly.
08:41:48 <korvo> The second projection is like what happens when you build GCC or LLVM. You get to choose which architecture you're targeting; if it's not your host, then you get what's called a *cross compiler*.
08:41:59 <korvo> Because you're compiling "a-cross" architectures, I guess?
08:42:08 <lisbeths> ah so in the second projection the JIT compiles the code into native code
08:42:23 <lisbeths> what about the third projection?
08:42:56 <korvo> I don't think I can show you any real-world examples of third projections. There are only some academic projects that, technically, generate working code.
08:43:28 <lisbeths> ah so for now we are stuck using just the first and second projection in industry code until the academic projects figure out how to build the third
08:44:22 <korvo> More or less. In practice, the situation's much worse than that; the toolchain I use is called RPython, the flagship interpreter that comes with it is called PyPy, and although it's the fastest implementation of Python, less than 2% of the community uses it.
08:44:47 <korvo> (Some folks might argue that ZipPy is faster. Fine; nobody uses that either.)
08:44:53 <lisbeths> okay so does this discussion have to do with blc or does it have to do with what you were saying about prolog arguments
08:45:54 <korvo> Well, there are very short specializers in Prolog, and there are also specializers that can (again, technically, if you wait for a few minutes) generate working third projections. So, what could we change about Prolog to make short self-applicable specializers easier to write?
08:46:11 <lisbeths> and you would like to make the smallest specializers possible correct?
08:47:14 <korvo> I'm lazy and I don't like writing code. I'd prefer a smaller language in order to have a smaller specializer that does less work.
08:47:42 <korvo> But I'm not golfing. Also, I'm not sure what BLC has to do with any of this either; I'm not sure why I brought it up, sorry.
08:47:48 <lisbeths> okay so first of all each of the three projection specializers could be made out of modules made out of smaller specializers
08:47:57 <lisbeths> breaking them down into modules can help make your code simpler
08:48:10 <lisbeths> second of all I believe that technology like blc can reduce the size of these specialziers
08:48:22 <lisbeths> and I believe technology like fastlisp can help reduce the size
08:48:25 <korvo> Oh. Then I guess I've not really explained this well at all, sorry.
08:48:55 <korvo> Like, yes, if we just write s, then the projections are compositions of s. It turns out that writing s is hard!
08:49:20 <lisbeths> we want to make writing s easy and we want s to be small
08:49:26 <korvo> And BLC is merely an encoding. It doesn't magically make things simpler. The actual target of the specializer is the underlying abstract syntax, LC in this case.
08:51:15 <lisbeths> are all there projections able to be written with the same s?
08:51:46 <korvo> In a framework I'm still defining, I think that I will have types [X -> Y] which are programs that take X inputs and return Y outputs, and a specializer is fundamentally something with signature [X -> Y] -> [X -> Y]. So, like, an identity function could be a specializer.
08:51:51 <korvo> But it's not a good specializer.
08:52:34 <korvo> I'm just saying that a specializer shouldn't change what types a program accepts or emits.
08:53:15 <lisbeths> can all three projections be written with teh same s?
08:53:27 <lisbeths> in otherwords can s^3 give us what we want
08:55:01 <korvo> Yes. But how efficient are the residues?
08:55:22 <lisbeths> so we want a different s for all three projections if we want to have an optimizer
08:55:51 <korvo> Not necessarily. A good s, that always optimizes its arguments, might be able to project itself.
08:56:14 <lisbeths> but until we know that we may be stuck developing s_1 s_2 and s_3 separately
08:56:25 <lisbeths> and currently we only have developed s_1 and s_2
08:58:51 <korvo> Look at what we already outlined so far. If you trace the definition of the third projection, you'll see that it passes [s] to s at runtime. This means that we need to put an entire copy of [s] into every residue!
08:59:34 <korvo> The only way to avoid this is if s can understand its own structure and remove the parts of [s] that it knows won't be needed. It has to do this before it knows what [y] is, too.
08:59:35 <lisbeths> or rather the residue that represents s has to be small
09:01:34 <lisbeths> similarly to how gcc compiles gcc
09:01:50 <korvo> Sure. Partial-evaluation folks defined the concept of *Jones-optimality* to deal with this. We say s is Jones-optimal when it doesn't leave behind any part of [s]. It does this by doing something stronger: it removes all overhead of interpreting [s], [f], or anything else at runtime.
09:02:10 <korvo> So it's okay if s is not small as long as it's Jones-optimal.
09:02:32 <lisbeths> ok so we need s to be EITHER jones-optimal or small
09:02:39 <lisbeths> for now it ie easier to target a small s
09:02:54 <lisbeths> what does building a small s_1 and s_2 entail
09:03:58 <lisbeths> what are the parts that a small s_1 and s_2 composed of? a small webasm like jit and some specialized code weaved into taht jit?
09:04:15 <korvo> They don't emit good code. Note that [s], [f], and all the other quoted programs are assumed to be in a single language. So, what if a specializer were just an interpreter for that single language?
09:04:34 <korvo> This is how practical second projections work, too. They assume that everything can be stored as some sort of bytecode somewhere.
09:05:01 <lisbeths> so do we prefer for s to be for a single language or do we prefer s to be for any language
09:05:22 <korvo> Like, RPython works by generating a JIT compiler which is generic over Python bytecode, more or less. At runtime, the compiler traces execution of that bytecode, and the bytecode is stashed as a big table in the residues.
09:05:54 <lisbeths> is that what we want or do we want s to be language agnostic?
09:06:11 <korvo> We're gonna keep saying that s is single-language. It takes programs written in some language L, it emits programs in L, and it's written in L. The question is whether L is Prolog, miniKanren, etc.
09:06:35 <lisbeths> ok so we desire for so to be language specific or thats what we choose to do at the moment
09:06:43 <lisbeths> so we must write a different s_1 and s_2 for every language
09:07:19 <korvo> Consider wanting to compile from frontend language X instead, or to machine M. Just write a little interpreter of X in L, or a compiler of L to M in L, and then use s on those.
09:08:18 <lisbeths> I think you mean taht we want to compile from X to M using L, and then we want to feed M into s
09:08:58 <korvo> No, I'm considering them as two different operations. You'd use different compositions of s, too.
09:09:33 <lisbeths> could you rephrase the consideration
09:09:36 <korvo> Like, suppose L is RPython, and suppose X is Brainfuck. Just write a little interpreter of X=Brainfuck in L=RPython: https://github.com/rpypkgs/rpypkgs/blob/main/bf/bf.py
09:11:16 <korvo> There isn't an M in that example.
09:11:48 <lisbeths> what is the residue of applying L to x called
09:12:48 <korvo> Once we write a good s in (Turing-complete) L, then we can absorb any other language X into L with an interpreter written in L. That interpreter also has to be good, but it only has to have insights about X, not about L.
09:13:22 <lisbeths> so L is our intermediate language or intermediate representation correct?
09:13:25 <korvo> In the above link, bf.py knows a lot about X=Brainfuck, including algebraic rewrites and idioms, but it doesn't know anything about optimizing L=RPython.
09:14:02 <korvo> L is our implementation language. s might have some other intermediate representation that it never exposes.
09:14:33 <lisbeths> okay so allow me to compose my own model
09:14:43 <lisbeths> we have a universal S_1 and a univerasl S_2
09:15:14 <lisbeths> s_1 takes an intermediate language IL and some source code S and it composes [R: IL(x)]
09:15:43 <lisbeths> IL includes the idea of a runtime or a tiny JIT
09:16:03 <lisbeths> this is the most optimal way I can currently imagine composing the tools youve descriebd
09:16:17 <lisbeths> and also have the model in my head be known valid and sound
09:17:07 <korvo> Sure. Part of the deep insight is that there's no real difference between "intermediate" and "source" here; there's only the intuition that one is
09:17:12 <korvo> *that one is more readable than the other.
09:17:31 <lisbeths> well the reason why I want IL is so that I dont have to write multiple versions of S
09:17:48 <lisbeths> I have an additional s called my_language_->_il
09:17:52 <korvo> Okay, let me be more blunt: Why is Prolog not an IL?
09:18:13 <korvo> So what do you mean by "universal"?
09:18:40 <korvo> ...Sorry, that was too blunt. I'm guessing that your "universal" is my "Turing-complete"? It's certainly an important qualifier.
09:18:46 <lisbeths> I am willing to make any langauge my IL if I see evidence that ist he right thing to do
09:19:00 <lisbeths> I dont know what universal will mean until I explore the whole universe I guess
09:19:14 <lisbeths> some variation on prolog coudl be a good IL but I think really big versions of prolog wouldn't do
09:19:46 <korvo> Ah, okay. Here we go. So what makes a good IL? I think that that's a great discussion topic regardless of the whole meta/Futamura perspective.
09:20:06 <lisbeths> we cah imagine a human_readable_il also HRIL
09:20:25 <lisbeths> this is more or less what llvm is
09:20:40 <lisbeths> IL itself should be optimal and resource efficient
09:21:43 <korvo> I'm gonna insist that good ILs are human-readable. Here are some examples: GIMPLE (GCC), LLVM IR, GHC Core, libfirm, QBE.
09:22:20 <lisbeths> tehre are langauges that are much more human readable than LLVM IR
09:22:32 <lisbeths> so we have a scale between very human readable at 100% and not very human readable at 0%
09:22:34 <korvo> Whether an expression in an IL is optimal is usually not cheap to decide. Have you heard of superoptimization?
09:23:19 <korvo> Basically, an optimizer is a superoptimizer when its outputs are always optimal. The way this is done is by searching all of the possible outputs, and it's very expensive.
09:23:40 <lisbeths> yeah thats why prolog makes a good optimizer on a classical computer
09:23:55 <lisbeths> but I propose to you that hte optimizer should be written in IL
09:24:03 <lisbeths> so lets break this apart into three stages
09:24:10 <korvo> This might be quite interesting to you, since we can use size for our metric, and thus superoptimize for the smallest programs.
09:24:42 <lisbeths> as the size of programs approaches their minimum size performance will go down
09:24:50 <lisbeths> once you get past a certain barrier
09:25:11 <lisbeths> an IL_performant should not desire to be read by the human. this is a high level machine language
09:25:24 <lisbeths> an il_middle is kind of like an assembler for IL_performant much like llvm ir
09:25:43 <lisbeths> then IL_human_readable is any human langauge like c or rust or prolog or c#
09:25:47 <korvo> Okay, I'm gonna propose that there isn't an objective human-readable scale. My first exhibit is Perl. My second exhibit is that you probably think "my cat is blue" or "mi gato es azul" is more readable than {lo mlatu pe mi cu blanu}, so really it's a popularity contest.
09:26:19 <lisbeths> part of my specialization includes trying to undestand how human readable code is so I ahve alot tto say on the matter
09:26:32 <lisbeths> there should be a further level benath llvm_ir
09:26:43 <lisbeths> taht is specifically for a machine and not for a human
09:26:57 <int-e> Just to add a data point, LLVM has a binary IL format too and that's not directly human readable. (But it can be converted to the text format.)
09:27:16 <int-e> (I'm not following the discussion.)
09:27:18 <lisbeths> because sometimes we dont want native machien code sometimes we want a high level machine code
09:27:39 <lisbeths> or a machien code for a high level optimal virtual machine
09:28:30 <korvo> I don't consider those sorts of isomorphisms to add to the nuance. Either they are genuine equivalences, like WASM and WAT, in which case they probably are counter-examples to whatever nuanced differance was being drawn; or they aren't, like LLVM IR, in which case they don't do what we expect of encodings.
09:29:11 <korvo> int-e: We're discussing what makes IR good. I've taken the Pirsig position that "good" is ultimately "what you like" rather than objective criteria.
09:29:35 <lisbeths> I am saying virtual machines like LLVM and like WASM and like microsoft CLR and like JVM all have their own high level machine code which is nto native code but is native to that vm
09:29:46 <lisbeths> and taht sits one layer below an intermediate representation
09:30:03 <lisbeths> because an intermediate representation has to be parsed an this parsing time can interfere with performant programs
09:30:08 <korvo> Sure. That's for cross-architecture portability. Another good example is GNU Lightning.
09:30:29 <lisbeths> yeah so we have our source code X which could be in any langauge
09:30:47 <lisbeths> then we have a specializer that interleaves x with IR
09:30:50 <korvo> Nah, code loading isn't that slow. Python's VM supports cached bytecode loading but many setups will pay a repeated parsing and compiling penalty of like 1ms/module.
09:30:57 <lisbeths> then we have a specializer that interleaves IR with a high level virtual machine code
09:31:07 <lisbeths> then we have a specializer that interleiaves high level virtual amchien code with native code
09:32:11 <korvo> Yep, you're seeing it now. Once we have a good specializer, why shouldn't we JIT?
09:32:25 <lisbeths> we should JIT that is part of the specializer
09:32:32 <lisbeths> unless we are specializing to native code in which case we might not need a jit
09:32:52 <int-e> korvo: Yeah I agree that it's subjective... and on top of that, context dependent (i.e. the same person may have different preferences depending on what they're trying to accomplish)
09:33:13 <int-e> This is not specific to IRs at all.
09:33:37 <lisbeths> so lets get our terminology straight
09:33:48 <korvo> int-e: Exactly! The top context is that I want to build self-applicable partial evaluators. So I'm looking at the classic results for languages like Prolog and imagining synthetic changes that might make them easier to specialize.
09:34:01 <lisbeths> a low level intermediate langauge is machine_IL or MIL
09:34:25 <lisbeths> so we have an s for every x whos residue is an IL
09:34:35 <lisbeths> we have an s for every IL whos residue is an MIL
09:34:45 <lisbeths> we have a s for every MIL whose residue is some specified native code
09:35:34 <korvo> Sure. GCC, at least in the olden days, was a good example of this; the frontends communicated in e.g. GIMPLE to the core, which also uses GIMPLE internally, but the machine-specific backends use machine- and kernel-specific information.
09:35:57 <lisbeths> so the first -> we can call A1
09:38:45 <lisbeths> so we can invent a new language falled foople
09:39:04 <lisbeths> first we pick or write an itermediate langauge and we write an s that foople -> IL
09:39:32 <lisbeths> then we choose or write an s that IL-> some MIL
09:39:45 <lisbeths> then we choose or write an MIL that MIL-> some native code
09:40:28 <lisbeths> do we agree or do you feel differently
09:40:58 <korvo> Well, I don't really do hierarchies. I also historically haven't found it useful to have multiple ILs.
09:41:47 <korvo> I do think that specific techniques like nanopass are fine, producing dozens of ILs, when the nanopass framework ensures that everything is type-safe and optimized away.
09:42:43 <korvo> But, having written a nanopass framework, I also don't think it's worth the effort for a specializer. The beauty of the specializer is that it can be driven by a choice of a single language L which happens to have good tools for manipulating L.
09:43:40 <lisbeths> people will attempt to write mutliple ILs
09:43:55 <lisbeths> and so there will be multiple ILs to choose from some better than others
09:44:11 <korvo> Oh, no, they'll write new Fooples.
09:44:50 <lisbeths> there arlready are multiple ILs to choose from
09:44:56 <lisbeths> denying that these exist is illogical
09:44:58 <int-e> . o O ( https://xkcd.com/927/ )
09:45:12 <lisbeths> mroeover there are already multiple MILs written and denying they exist is illogical
09:46:09 <korvo> . o O ( https://ro-che.info/ccc/20 )
09:46:10 <int-e> the "all existing attempts to do $X suck, we need a new approach" thought is very appealing, but unless you have some actual insight into the domain that the previous attempts lack, it almost certainly won't work
09:46:54 <lisbeths> saying "there are no IL's that are bad" is kind of a no true scottsman argument
09:47:01 <int-e> OTOH what you often can do is something that fits your own use case better than the existing things.
09:47:06 <lisbeths> it is more accurate to say "bad ILs dont matter and might as well not exist"
09:47:09 <korvo> Whether a language is IL or not, in terms of whether people will write languages alongside it, isn't predictive. Paraphrasing a classic joke, "do you think JavaScript knew it'd end up as a compiler target?"
09:47:20 <lisbeths> any language can be used as an IL
09:47:31 <korvo> Oh! All ILs I know of are bad.
09:47:40 <lisbeths> IL is just x used in a different way
09:47:56 <lisbeths> IL is making x a compiler target
09:47:56 <korvo> Yes! Any language can be used as an IL, so we might as well use L, the host language of specialiser s, as our IL.
09:48:20 <int-e> There's that one Stroustrup quote that I agree with... There are two kinds of programming languages, those that everybody complains about and those that nobody uses.
09:48:24 <korvo> L is what s takes as input, emits as output, and is written in.
09:48:47 <lisbeths> so what is s in this instance?
09:48:54 <int-e> I imagine that's just as true for intermediate languages.
09:49:01 <korvo> int-e: In the Pacific Northwest, we say "X sucks, use X." For example, "Nix sucks, use Nix."
09:49:28 <korvo> lisbeths: s is just a specializer that can be applied to itself to make second and third projections.
09:49:39 <int-e> I've never been in enough dependency pain to actually use Nix.
09:49:50 <lisbeths> thats kind of fishy to replace IL with an L to s
09:50:01 <lisbeths> it implies a perfect L and a perfect s
09:50:16 <korvo> Nix gives me a sort of abstractive radius. Like, I could maintain one or two RPython codebases by hand, but Nix lets me maintain an entire collection of like twenty codebases.
09:50:59 <korvo> lisbeths: Oh! So, this is why "universal" or "Turing-complete" matter so much. Any computation you can write down can be found in L, for *any choice* of L.
09:51:23 <lisbeths> yeah I have to think about this for a while
09:51:42 <korvo> L might not have arbitrary data structures, but it can have arbitrary effects as if it had those data structures. It can produce any I/O pattern you want, except for the uncomputable ones.
09:51:45 <lisbeths> I have to move from my model of thinking of x->IL->MIL->native over to some model that includes only S and L
09:52:05 <lisbeths> the differnce is that x->IL->mil-> native systems exist today and you can use them and build them
09:52:15 <lisbeths> where as S and L machines seem more theoretical unless I can know more info about S and L
09:52:51 <korvo> Your model is fine, BTW. It's the same detail as with GCC's triple of build, host, target, which is also used by Gentoo and Nix and other cross-compile-aware ports trees. It's the model needed to understand Glück 2009.
09:53:20 <korvo> It's just not what I'm currently interested in tonight. But I'm happy to bridge the knowledge gap because I think this is such a cool corner of computer science.
09:53:21 <lisbeths> it seems to me that each of thes arrows is a function
09:53:41 <lisbeths> one we can call mil->native or a3
09:53:58 <lisbeths> and it seems to be that all of those can be executed by a function compiled to native or compiled to MIL
09:54:06 <lisbeths> and I think that is what you are talking about when you talk about s and l
09:54:43 <lisbeths> the thing is there has to be at least two of them
09:54:49 <lisbeths> because sometimes we cant chose to run s natively
09:54:59 <lisbeths> other times our only choice is to run s on the native machine
09:55:12 <korvo> Sure. That's what e.g. WASM folks do with their runtimes. There's the WASM specializers running in WASM, and then there's also a browser or WasmTime or whatever.
09:56:07 <lisbeths> I dont know how to notate a specializer written in MIL that takes x and produces the residue of [y: IL(x)]
09:56:45 <korvo> No worries. I get what you're saying. The formal notation for this is called "tombstone diagrams" or "T-diagrams"; they look like T-pieces from Tetris.
09:56:58 <int-e> Are we trying to reinvent the concept of a program transformation?
09:57:11 <lisbeths> thats what korvo has opened a discussion with me on it seems
09:57:21 <korvo> They're lovely to draw on a board, but they don't fit in IRC. WP's current page on them is not bad: https://en.wikipedia.org/wiki/Tombstone_diagram
09:57:27 <lisbeths> so it seems to me wasm is already almost as performant as machine code
09:57:35 <lisbeths> so I think for MOST programs we can forget about native code
09:57:45 <int-e> I find it impossible to tell whether this is a concrete task that has become unrecognizable through premature abstraction... or whether the point is to abstract.
09:58:10 -!- tromp has joined.
09:58:11 <lisbeths> the idea that abstraction isnt useful is a meme
09:58:15 <korvo> int-e: They're coming to understand how a specializer could be associated with three different languages. I'm focused on a more concrete engineering task using only one language.
09:59:00 <korvo> In the background I've been reading this thesis about metaKanren, a miniKanren that supports metacircular access.
09:59:30 <lisbeths> I think you need to study how performant the literal smallest virutal machines are even able to be
09:59:43 <lisbeths> because the literal smalllest virtual machines arent very performant
10:00:20 <lisbeths> so we can come up with a new model
10:00:56 <lisbeths> and then some low level people worry about specializing MIL->native
10:01:02 <lisbeths> and this is a very very simple model
10:01:03 <korvo> So yes, VMs can have performace characteristics as a matter of engineering, but I think it's wrong to try to pick on VM choice here. We're talking languages, not VMs, right?
10:01:50 <lisbeths> in one lense it is useful to think about it abstractly without specifying vm
10:01:58 <lisbeths> in another lense it is more useful to talk about specific vms
10:02:10 <lisbeths> and in yet another lense it is more useful to talk about specific and already existing vms
10:02:32 <korvo> In practice, there's no interesting specialization happening at that MIL->native layer; it's all instruction selection. (I wrote two such instruction-selection tables for GPU drivers. It's boring.)
10:03:15 <lisbeths> yeah the virtual machien for a machine readable intermediate language is almost as fast as native as seen in wasm
10:03:22 <lisbeths> so we dont have to worry about MIL->native
10:03:59 <lisbeths> all we must do is pick a langauge x
10:04:27 <lisbeths> and write a specializer that takes x and -> to MIL
10:04:34 <lisbeths> and we can write that specializer in x
10:05:38 <korvo> Well, no. The winning strategy turned out to take a higher-level IL that only has a few operations, but gives those operations either parameters or polymorphism (i.e. dynamic dispatch), and then to JIT that IL based on concrete values of those parameters at runtime.
10:06:28 <korvo> By "a few", ISTR that Self's VM has eight operations. That number has ballooned, if you look at Strongtalk and Java VMs, but the original idea was that the JIT only has a few possible choices to consider at any possible time.
10:06:57 <lisbeths> please give these components acronyms
10:07:30 <korvo> Remember -- hours ago!? sheesh I should sleep soon -- that I said that we want "a few" to be like two or three. Each time we have a branch, we want the exponent controlling the size of our search to be small.
10:07:59 <lisbeths> I think part of what you are saying is that it is proven that a language can be an IL and still be as performant as an MIL
10:08:48 <korvo> There aren't any acronyms worth remembering. I'm just saying that the speed comes from a specific lineage of languages that were designed to be JIT'd: Self, Strongtalk, Java, C♯, Dart.
10:10:19 <korvo> Another VM worth mentioning (again?) is GNU Lightning, which was also designed to be JIT'd. The fastest Brainfuck interpreter on the wiki targets GNU Lightning.
10:11:29 <lisbeths> I think your answer is meant to be yes, an intermediate langauge that is humanr eadable that is evolved from a lineage of languages designed to be JIT'd can be as performant as a MIL
10:11:43 <korvo> Sure. More generally, performance isn't a property of languages!
10:11:52 <lisbeths> and so if that is true then we can remove MIL from our vocabulary and we can refer to IL from now on as being a language from a specific lineage of languages that were desigend to be jited
10:12:29 <lisbeths> so first we must pick an IL that is evolved from languages designed to be jitted
10:12:45 <lisbeths> then for every x we must write in some language a specializer from x to IL
10:13:22 <korvo> Sure. Although I'm looking right now at languages that can be designed for partial evaluation. Some JITs do partial evaluation, but not the famous lineage with the amazing JVM.
10:13:45 <lisbeths> well picking something like java or c# is going to complicated for your research
10:13:48 <korvo> I'm only half-sarcastic. Look up Azul's products, particularly Zulu, if you want to see how fast JVMs can get.
10:13:56 <lisbeths> we would obviously like a very simple language that is designed to be jited
10:14:07 <lisbeths> or rather that is designed for jit
10:14:19 <korvo> Well, yeah. Speed isn't everything! Particularly when we've only barely talked about what makes this whole process fast or slow.
10:14:45 <lisbeths> well first of all some engineers strongly prefer the word performance over speed
10:14:58 <lisbeths> so you may run into this issue in irc altohugh I do not mind if you use the word speed
10:15:10 <lisbeths> i will use the word performance
10:15:22 <korvo> I don't care about memory usage. Most practical partial evaluation uses lots of memory; PyPy takes like 12GiB of RAM to translate.
10:15:46 <korvo> But sure, I don't mind talking about generalized resource usage.
10:15:49 <lisbeths> second of all when I as saying earlier that the smallest languages are not very performant, there are some very small languages that are performant
10:16:03 <lisbeths> it is only when you get very close to the smallest of languages that you see huge drops in performance
10:16:34 <lisbeths> you can have a very performant language in under a megabate of native code or IL code
10:16:55 <korvo> Oh! Okay. We were talking past each other earlier.
10:17:12 <lisbeths> yeah so there are three kinds of virtual machines in this lense
10:17:22 <korvo> When I say "small language" I mean a small grammar of a countable (infinite) language. I'm not talking about implementation size.
10:17:24 <lisbeths> one is designed for the smallest of computers like smart dust and cellular robots for medicine
10:17:36 <lisbeths> those generally have to have real time computing
10:17:52 <lisbeths> the second is very small virtual machines that go in smaller applications like the browser tab
10:18:14 <lisbeths> then you have very big industrial virtual machines that often ask for at least a gigbyte of memory and generally are a sever for virtualization in a whole os
10:18:23 <lisbeths> such as the common language runtime or the jvm
10:19:20 <korvo> Okay, yeah, by "virtual machine" I was talking more about the abstraction than the implementation. I recognize that a software engineer is going to read "VM" and think "emulator".
10:19:56 <lisbeths> a baby virtual machine under a megabyte can ask the big server vm to do compute jobs
10:20:04 <lisbeths> and teh server vm can use the graphics card and stuff like this
10:20:09 <korvo> lisbeths: So, I want to re-introduce the entire topic with the other notion of "small": I want a language that, like Prolog, only has a few possible types of clauses that need to be analyzed by a specializer.
10:20:22 <lisbeths> so we can talk about the size of the compiled language
10:20:26 <lisbeths> and then we can talk about the size of its grammar
10:20:37 <lisbeths> a language can have a small grammar like prolog but a huge compiled program that runs it
10:20:50 <lisbeths> or a language can have a very small compiled program that runs it but be extended to a huge grammar
10:20:51 <korvo> Something like WebAssembly, though "small" in the size of an emulator which implements it, is quite large in the number of possible instructions that can occur, which means that its specializers need to cover many different possibilities.
10:21:18 <lisbeths> from what I gather about mathematics what most programmers refer to as exponential growth is often multiplicative growth
10:21:30 <lisbeths> and what most programmers refer to as a syntax is actually called a grammar
10:21:36 <lisbeths> i could be wrong about both of those though
10:21:44 <korvo> This is the sense in which Self is "small"; with only eight possible instructions, any specializer or JIT only has a few possibilities to cover.
10:22:18 <korvo> If you're searching a tree, and the number of possibilities at each branch is a constant, then the tree is exponentially large.
10:22:50 <lisbeths> we can talk in terms of bytes, tens of bites, hundreds of bies, and then kilobytes and tens of kilobytes and hundres of kilobytes, and then megabtyes and tens of megabytes and then hundreds of megabtes, and then gigabytes and then tens of gigabytes and then hundreds of gigabytes
10:23:05 <lisbeths> so the commmon language runtime is at least 1 gigabyte in terms of ram
10:23:19 <lisbeths> and I dont know how many megabytes it is in storage but it is likely at least in the hundreds or more
10:23:42 <lisbeths> whereas we know as langauge people that you could probably get most of the performance of the common language runtime in under a megabyte
10:24:12 <lisbeths> we would also like to use a language much like prolog with a small useful grammmar
10:28:10 <korvo> Sorry, I can't find a way to interpret that setup.
10:29:14 <korvo> The CLR's size probably doesn't have much to do with having a JIT. I'd guess that they have a lot of i18n. You'd be surprised how large the tables are for basic Unicode support.
10:30:07 -!- Sgeo has quit (Read error: Connection reset by peer).
10:33:19 <korvo> Okay, sleep is no longer optional. Peace.
11:29:01 <esolangs> [[UserEdited]] https://esolangs.org/w/index.php?diff=152107&oldid=152104 * PrySigneToFry * (+1406)
11:37:22 -!- wib_jonas has joined.
12:10:04 <esolangs> [[User:Gilbert189/Polymorphic quine]] N https://esolangs.org/w/index.php?oldid=152108 * Gilbert189 * (+11283) This has been in the works for quite some time...
12:10:47 <esolangs> [[User:Gilbert189]] https://esolangs.org/w/index.php?diff=152109&oldid=139872 * Gilbert189 * (+79) /* See also */
13:01:12 -!- wib_jonas has quit (Quit: Client closed).
13:32:23 -!- amby has joined.
13:47:48 -!- dawids_ has joined.
13:48:15 -!- dawids_ has quit (Client Quit).
13:52:38 -!- craigo has joined.
15:05:02 <esolangs> [[User:Anthonykozar/Notes]] N https://esolangs.org/w/index.php?oldid=152110 * Anthonykozar * (+271) New page for me to keep notes on the wiki
15:11:03 -!- ais523 has joined.
15:11:52 <ais523> <zzo38> One idea I thought of is "base zero" numbers that are stored the power of zero and the multiple. This way, you can make sizeof(x)/sizeof(*x) if x is an array even if sizeof(*x)==0 ← I think you could make that work by giving zero-sized objects an infinitesimal size?
15:17:43 <ais523> <korvo> It seems like most existing research has been analytic. Given e.g. Prolog, how few clauses are required for partial evaluation? But I think we should be synthetic: what modifications to Prolog would reduce the number of clauses? ← one obvious modification: Prolog represents the bodies of clauses using a free monoid, meaning that you need three cases (identity, generator, and other cases); if you represented them using a list instead you would only
15:17:44 <ais523> need two (empty list, nonempty list); add a map builtin (that doesn't require the creation of an extra clause to use it) and you only need one
15:18:46 <ais523> but this reasoning just makes me think that counting clauses is wrong
15:21:20 -!- tromp has quit (Read error: Connection reset by peer).
15:25:34 <ais523> actually I'm not sure the map builtin helps because then you need to implement it within the evaluator
15:25:41 <ais523> but converting clause bodies to lists does help
15:26:38 <ais523> you get something like eval([]) :- []. eval([Goal|Tail]) :- clause(Goal, Body), eval(Body), eval(Tail).
15:26:45 <ais523> eval([]) :- []. eval([Goal|Tail]) :- clause(Goal, Body), eval(Body), eval(Tail).
15:26:51 <ais523> eval([]) :- []. eval([Goal|Tail]) :- [clause(Goal, Body), eval(Body), eval(Tail)].
15:27:29 <ais523> (and you can desugar [X|Y] as '.'(X,Y), etc., as usual)
15:29:21 <ais523> <korvo> I'm gonna insist that good ILs are human-readable. ← having thought about this a while myself, I think that this isn't *quite* right, it should be "good ILs can easily/automatically be converted to and from a human-readable form", but you can create an assembly language for them for the purpose
15:34:02 -!- wib_jonas has joined.
15:37:32 <wib_jonas> I think it's neither of those. the compiler should be able to emit tracing information that lets you debug the compiler and verify that the IL is correct. but this tracing information is only needed when you're either debugging the compiler or debugging the machine that executes the IL. when you'll programming in a high-level language normally then
15:37:33 <wib_jonas> you trust the compiler, don't ask for such trace, and the IL that you get in that case alone needn't be translatable to human-readable.
15:38:56 <wib_jonas> This is how machine code works in practice. It's not easy to decompile (transform to human-readable) because the instructions are variable length so you don't know where to start disassembling, there can be unreachable code anywhere, you don't know what type most of the data that it manipulates has.
15:39:42 <wib_jonas> But if you do emit detailed debug information then you can decompile because the debug information tells which parts of the code are executed and what the registers and stack frame stores at any point.
15:42:29 <wib_jonas> Of course this is just theory. In practice the debug information could be incomplete or buggy (which was often the case back around 2000 if you used C++). And the reverse engineer folks are racing compilers close behind with their heuristics so that they can decompile machine code without debug information because this is useful for itsec.
15:47:59 <esolangs> [[User:Anthonykozar/Notes]] https://esolangs.org/w/index.php?diff=152111&oldid=152110 * Anthonykozar * (+257) Added Bespoke and new sections.
16:02:41 <ais523> wib_jonas: many machine codes do have deterministic ways to find the start of an instruction – I'm not sure whether it's more or less than half
16:05:51 <wib_jonas> ais523: yes, that could help, but that's not enough. you also need to be able to distinguish segments that contain code from other read-only segments, which is already possible on at least some machines, and even then decompiling might not be easy
16:07:14 <ais523> don't most formats for storing executables distinguish between code and other rodata? even if the processor itself doesn't?
16:08:13 <ais523> besides, the original comment was about ILs and those definitely distinguish, otherwise the compiler can't know what needs to be compiled and what needs to be left untouched
16:08:55 <wib_jonas> that's only if you're compiling the IL rather than interpreting it
16:09:33 <wib_jonas> a JIT-compiler won't know in advance which parts of the code it will have to compiler
16:10:03 <ais523> this reminds me of an idea I had a while ago: instead of storing separate unwinding tables, work them out at runtime via partially decompiling the running code – the decompiler could be very simple as it only needs to get the unwinding-related information right, and the code could be explicitly generated in a way that made the decompiler work
16:10:06 <wib_jonas> that's how qemu's non-native mode (which few people use) works for x86
16:10:45 <ais523> I think I've used non-native qemu before now, probably to run a program written for a processor architecture unrelated to the one my computer used
16:11:23 <wib_jonas> I'm saying specifically for an x86 guest; for other guests it probably does get used
16:12:20 <wib_jonas> as for that unwinding, even if it finds the stack frames, how would it know what destructors to call while unwinding?
16:12:40 <wib_jonas> or would this only be unwinding that prints a stack trace for a fatal error?
16:13:47 <ais523> my plan was to mark destructors and the like using NOPs or via the choice of equivalent instructions
16:14:20 <ais523> which is a bit like having separate unwinding tables, but more lightweight
16:14:54 <ais523> it could be something as simple as code ordering, e.g. decompile assuming forward jumps are taken but backward jumps are not taken
16:33:19 <esolangs> [[User:Anthonykozar/Notes]] https://esolangs.org/w/index.php?diff=152112&oldid=152111 * Anthonykozar * (+190) Adding links to categories to explore
16:51:46 -!- tromp has joined.
17:17:23 -!- zzo38 has quit (Ping timeout: 268 seconds).
17:20:23 -!- wib_jonas has quit (Quit: Client closed).
17:41:49 <korvo> ais523: I didn't want to pull a thread that they might not understand how to restitch. An IL should admit some sort of nice decompiler, but I thought it was more important to push against the idea that low-level machines are somehow complicated or obfuscated to the point of unreadability.
17:44:17 <korvo> ais523: The point about the monoid is good. For some reason right now it's rhyming with "lazy languages don't have sums, eager languages don't have products", probably because of the ,/2 and ;/2 functors.
17:47:14 <ais523> korvo: right, I wasn't so much trying to interfere in your conversation as to make comments inspired by it
17:47:59 <korvo> ais523: Oh, I completely see where you're coming from. I just have trouble supporting it from the opposite direction.
17:48:34 <ais523> one esolanging problem I'm working on at the moment is currently trying to construct a good IL
17:49:03 <korvo> Like, would you believe that COBOL was originally supposed to be a low-code platform? It was supposed to remove the need for debuggers and humans who could step through the machines.
17:49:12 <ais523> I pretty much know what I want (e.g. I want it to be stack-based even though the original isn't), just trying to work out the details
17:49:34 <ais523> which may have been slightly more successful at that than COBOL was, but still mostly didn't meet that goal
17:50:52 <ais523> I wonder whether people have stopped making the mistake of assuming that "writing code so that the meaning of every instruction in it is clear to typical speakers of «insert native language here» mean that those speakers will necessarily understand everything the program is doing" yet
17:51:25 <ais523> …and I also wonder whether that mistake is more likely to be made by programmers or non-programmers
17:51:50 <esolangs> [[User talk:Aadenboy]] M https://esolangs.org/w/index.php?diff=152113&oldid=151742 * Aadenboy * (+36) muahaha.
17:52:43 <ais523> it's fairly obvious to me that learning what "a = b + c" means is not the major trouble of learning how to program, and that writing it as "ADD B TO C GIVING A" will make matters worse in the long term
17:53:05 <ais523> but that doesn't seem to be obvious to everyone
17:53:45 <ais523> (at one point, my day job involved teaching people how to write Java – it really is the case that the meaning of "a = b + c" isn't obvious to everyone and has to be learned, but it really isn't difficult compared to other things that you have to learn to be able to write working programs)
17:57:53 <ais523> …and of course, there are then languages like Prolog where "A = B + C" is a legal command-equivalent but means something different, and that also catches people out
17:59:32 <esolangs> [[User:Aadenboy]] M https://esolangs.org/w/index.php?diff=152114&oldid=151911 * Aadenboy * (+668) add signature code
18:23:02 <lisbeths> https://github.com/memesmith0/mcr16_projects
18:24:31 <lisbeths> i have greatly extended the syntax of mcr
18:24:40 <lisbeths> at the cost that you dont immediately get a working shell out of it
18:41:22 -!- Sgeo has joined.
18:44:29 -!- Lord_of_Life has quit (Ping timeout: 260 seconds).
18:44:56 -!- Lord_of_Life has joined.
19:09:02 <korvo> Okay, finished reading the late-night scrollback. Something really funny in there. Let X and Y be objects in some category, let [-] be a functor on that category sending objects X to objects of quoted programs [X], and let [[X,Y]] → [[X,Y]] be the type of polymorphic specializers.
19:09:22 <korvo> ...Oh, and let [X,Y] be the type of the internal homs X → Y.
19:10:17 <korvo> Then this all snaps together for free categories, as lisbeths intuited: an identity arrow serves as a specializer. The downside is that all arrows are equivalent to identity arrows in this setup!
19:10:29 -!- nitrix has quit (Remote host closed the connection).
19:11:04 -!- nitrix has joined.
19:11:07 <lisbeths> yes in this instance when we say that x => IL or IL=> native teh -> refers to a specializer
19:11:26 <lisbeths> do tehre needs to be a specializer for every IL to every native language
19:11:36 <lisbeths> and tehre needs to be a specializer for every x to every IL
19:11:51 <korvo> So, in some sense, it's not just about finding the smallest branching factor for clauses/sums/tags/etc., but recognizing that the smallest branch factor is 1 in the case of free categories, with a trivialized model.
19:11:53 <lisbeths> and finally there is a specializer from one IL to another
19:12:01 <korvo> lisbeths: No, that's not what I'm talking about.
19:12:52 <korvo> I'm saying that, if we synthesize a basic language just for partial evaluation, then the simplest possible construction already works perfectly. It just can't do anything; it's certainly not Turing-complete.
19:14:17 <lisbeths> it seems like what you want is a universal s_1 a universal s_2 and and a universal s_3 and if we are lucky they can all be the same s
19:14:27 <korvo> Yes, and it's an identity arrow.
19:14:30 <lisbeths> part of doing that id agreeing upon an IL is it not?
19:14:40 -!- ais523 has quit (Quit: quit).
19:16:35 <korvo> lisbeths: Nah, I'm not really interested in concrete syntax today. Too many errands to take care off.
19:17:14 <lisbeths> if you dont have time to discuss speializers today we can discuss it another time
19:17:23 <lisbeths> or maybe you mean taht you arent currently willing to commit to an IL just yet
19:18:18 <korvo> No, I mean that concrete syntax is incredibly boring and discussing it is usually not a good use of time. You have to understand: I normally just shove everything into S-expressions or JSON and write code to do my manipulations. I am tired of writing parsers.
19:18:49 <lisbeths> yeah I am of a similar mindset
19:18:55 <korvo> If you have questions about specializers, then I can answer those.
19:19:29 <lisbeths> well I just dont yet understand how you plan on building an s_1 or an s_2 without comitting to a top 10 list of ILs
19:19:45 <lisbeths> are you saying s_1 and s_2 dont need an IL?
19:20:51 <korvo> In those terms, I'm talking about *designing* an IL.
19:23:31 <lisbeths> oh so you arent satisfied with the current ILs available
19:23:50 <lisbeths> or is there another reason why you want a new IL
19:24:23 <korvo> Well, yeah, all the available ILs suck.
19:25:30 <lisbeths> korvo: is there a top 3 that you could recommend to use until a better IL comes along?
19:26:19 <korvo> lisbeths: What are you trying to build?
19:27:19 <lisbeths> right now my compiler is fastlisp -> binary lambda calculus 2
19:28:59 <korvo> Write your own IL. Look up "alpha-normal form" and "continuation-passing style", often abbreviated ANF and CPS.
19:29:31 <korvo> Continuation-passing is a great tool for compiling to LC. It's also fairly good at compiling out of lambda-heavy languages like Lisps.
19:31:34 <lisbeths> binary lambda calculus 2 is my IL
19:31:43 <korvo> After reading about that, you could look up strategies for optimizing LC expressions, particularly "interaction nets" and "optimal beta-reduction". You may also find "graph reduction" fascinating, but it's a little more expensive at runtime and usually only used for lazy/non-strict languages like Haskell or Miranda.
19:31:45 <lisbeths> I am not in the business of writing my own ILs
19:31:56 <korvo> You mean that LC is your IL. BLC is an *encoding*.
19:32:28 <lisbeths> thats right LC is my IL and the universal way to represent lambda calculus is BLC
19:32:52 <lisbeths> this is because every program in fastlisp is a lambda so it makes sense for LC to be my IL
19:33:01 <korvo> And even then, there are strategies for representing LC terms. BLC uses De Bruijn indices, but there may be more efficient in-memory representations when doing lots of beta-reductions.
19:33:23 <lisbeths> I have been told common lisp is the fstest lambda calculus interpreter
19:34:07 <lisbeths> I do not write ILs but I am curious about your research as you brough it up to me last night and explained it in depth
19:34:24 <lisbeths> it is intriguing to replace compilers with more efficient proof driven systems called s
19:34:26 <korvo> The most notable strategy to look at is Elliott & Kmett's "bound" library https://hackage.haskell.org/package/bound which collects De Bruijn indices in a clever way to avoid having to substitute every index during every binding.
19:35:28 <korvo> If we're thinking of Lisp runtimes as LC interpreters, then the fastest is probably Chez Scheme, followed closely by CHICKEN Scheme and SBCL. Note that SBCL doesn't actually interpret, but it contains a JIT compiler.
19:37:46 <lisbeths> for now I am using sectorlambda
19:37:58 <lisbeths> it doesnt matter which one i use because its outputs will be the same
19:38:11 <lisbeths> except for order of evaluation
19:38:38 <korvo> Actually, you'll find that many Lisp runtimes *fail* when given large programs.
19:39:02 <lisbeths> well sectorlisp can grwo to like 2gb of memory so I think sectorlambda can probably do the same
19:39:23 <lisbeths> i may roll my own lambda calculus interpreter in posix sh
19:39:37 <korvo> For example, my Cammy language (documented on wiki) started out compiling to OCaml, but I was routinely busting its stack at runtime. Then I switched to Haskell, and then to CHICKEN Scheme, but they weren't fast enough.
19:40:13 <lisbeths> ultimately except for evaluation order it should not matter which interpreter I use for lambda calculus
19:40:23 <korvo> I'm currently running on a OCaml-like machine -- a CAM -- implemented in RPython. The stack is set up to spill to the heap. This is fast enough for my current needs.
19:40:46 <lisbeths> lambda calculus should be plug and play so if sectorlambda fails me I can just hop to another lambda calculus interpeter
19:40:56 <korvo> Sure, except for I/O.
19:41:09 <korvo> Also garbage collection.
19:41:13 <lisbeths> the binary lambda calculus way of output is returning a llinked list of booleans
19:41:53 <korvo> Yeah, BLC has an I/O convention. But it's not plug-and-play; it requires a bit of setup in the host language.
19:42:17 <lisbeths> yes this is why I am currently gonna use sctorlambda to make things easier for myself
19:42:26 <lisbeths> but i can switch if that one fails me no problem
19:45:15 <lisbeths> I am going to write some code in fastlisp that that is used to orchestrate the compilation of a subset of lambda calculus over to an IL
19:45:19 <lisbeths> and that is how fastlisp will achieve performance
19:45:47 <korvo> I think a reality check is in order. When we say that an LC evaluator is "fast" we mean that it achieves many beta-reductions/second.
19:46:12 <korvo> We don't mean that data structures encoded in LC have good wall-clock performance on today's bit-oriented hardware.
19:46:14 <lisbeths> yeah fastlisp is meant to be compiletime only for most things
19:46:21 <lisbeths> and some tasks have to be offloaded to haskell
19:46:52 <lisbeths> c++ doesnt actually run on the hardware c++ only really exists at compiletime
19:47:14 <lisbeths> machine code generated by a c++ compiler runs on the hardware not c++ itself
19:47:54 <lisbeths> whereas if you look at DSSP that is a langauge that is alot closer to actually running on the hardware itself
19:48:17 <korvo> Sure. So, double-checking, LC is really small. It only has three constructors or so. You don't really need to think much about the IL for it, at least not yet.
19:48:25 <korvo> You can just *do that* right now.
19:48:58 <lisbeths> fastlisp is going to write libraries
19:49:08 <lisbeths> and those libraries are going to orchestrate the generation of python code
19:49:17 <lisbeths> and the generation of some language evolved to go into a jit
19:50:06 <korvo> But by committing to such a heavyweight grand plan, you've now required your IL to serialize to disk, which ruins the entire point of doing abstract syntax.
19:50:23 <lisbeths> yeah i mean this is just experimental
19:50:38 <lisbeths> the idea is something like fastlisp could be developed into something nicer
19:51:11 <lisbeths> the primary objective of fastlisps design is to be easy
19:51:25 <lisbeths> no other metric is as important as easiness in my research
19:51:45 <lisbeths> so i am willing to waste many compute cycles to shave off some difficulty for the programmer
19:51:54 <korvo> Ah, okay, yeah. So, this is a common-enough fallacy that we really need a name for it. Closely related is the *Turing Tarpit*, the idea of a universal system where nothing is easy to construct.
19:52:37 <korvo> If all of our engineering problems were nicely reducible to LC in a way that executes fast enough for our needs, then we would have all switched to Lisps in the 1980s.
19:52:52 <korvo> Similarly, if Horn clauses were the right answer to everything, then we would have switched to Prologs in the 1990s.
19:53:06 <lisbeths> if my language turns out not to be easy then I will change it
19:53:15 <lisbeths> I am not worried about it being fast enough
19:53:30 <lisbeths> also I am willing for compile times to be upwards of 2 hours
19:54:02 <lisbeths> this research has purely to do with what is easy not with what is efficient
19:54:29 <korvo> Really! So why not RPython?
19:54:57 <lisbeths> I happen to believe that fastlisp is much easier than rpython but let me take a look at rpython quickly
19:55:13 <korvo> Probably because you have this "fast" goal, which I'm seeing primarily as optimizing program size, which is even more important than ease of use.
19:55:56 <korvo> No, I remember, "fast" is your living-out-of-a-bag meme. It's about size, right?
19:55:57 <lisbeths> it is named fastlisp after the fastman meme
19:56:17 <lisbeths> well everything I name I name it by gluing fast to the beginning of its proper name
19:56:25 <lisbeths> teh word fast has nothing to do with fastlisp
19:56:32 <lisbeths> even though performancen does concern me
19:56:39 <lisbeths> I am more concerned with easiness
19:57:05 <lisbeths> I have looked at rpython I think fastlisp is likely an easier language
19:58:10 <korvo> Would you write a DIVSPL interpreter in fastlisp, for comparison? I don't expect you to beat mine in terms of performance, but maybe it'll be smaller or easier to read than: https://github.com/rpypkgs/rpypkgs/blob/main/divspl/divspl.py
19:58:36 <korvo> It should read like ordinary Python 3, since I wrote it in Python 3 first and then ported to RPython later.
19:59:08 <lisbeths> but I could write it in telesial fastlisp
20:07:15 <lisbeths> fastlisp is broken up into a few categories
20:07:22 <lisbeths> first of all there is subterranian code which is not in fastlisp
20:07:39 <lisbeths> then there is fastlisp code that directly generates subterranian code in a one to one mapping of that codes syntax tree
20:07:57 <lisbeths> sorry that second category was called terrestrial
20:08:30 <esolangs> [[6A]] M https://esolangs.org/w/index.php?diff=152115&oldid=152048 * Buckets * (-2)
20:08:34 <lisbeths> the third category is telestial fastlisp which uses libraries that orchestrate the generation of terrestrial code. ideally these libraries will hide from you the fact that your code depends on subterranian code
20:08:58 <lisbeths> then there is celestial fastlisp code which is any fastlisp code that does not depend on any terrestrial or telestial fastlisp code
20:12:16 -!- zzo38 has joined.
20:12:41 <esolangs> [[User:Buckets/Sandbox]] M https://esolangs.org/w/index.php?diff=152116&oldid=152098 * Buckets * (+19)
20:13:12 <esolangs> [[User:Buckets/Sandbox]] M https://esolangs.org/w/index.php?diff=152117&oldid=152116 * Buckets * (-18)
20:24:28 -!- Lykaina has joined.
20:26:55 <Lykaina> i think i went a little too far in the current code for fungeball, defining every user-accessible command from a set of ~55 fixed commands
20:29:27 <esolangs> [[User:Buckets]] M https://esolangs.org/w/index.php?diff=152118&oldid=152093 * Buckets * (+10)
20:29:50 <esolangs> [[Language list]] M https://esolangs.org/w/index.php?diff=152119&oldid=152094 * Buckets * (+11)
20:30:07 <Lykaina> only two of those used return values, and none have local arguments.
20:30:09 <esolangs> [[S1LK]] N https://esolangs.org/w/index.php?oldid=152120 * Buckets * (+1754) Created page with "S1LK is an Esoteric programming language created by [[User:Buckets]] in 2022 about Having an Output Purely In Taste. {| class="wikitable" |- ! Commands !! Instructions |- | Set || Sets the Next variable by the Next Number, example: Set blah 1, If you are Changing The taste
20:32:05 <Lykaina> they all have access to the same 4 tick-level and all thread-level and global-level variables
20:36:29 <esolangs> [[User:Anthonykozar/Notes]] https://esolangs.org/w/index.php?diff=152121&oldid=152112 * Anthonykozar * (+217) Added some languages and people.
20:37:40 <Lykaina> this is how addition is defined: t_s(); b_t(); t_s(); a_t(); t_b(); t_at_add(); s_t();
20:38:22 <Lykaina> i modified the code to make it fit on one line
20:41:00 <Lykaina> t = stack.pop; b = t; t = stack.pop; a = t; t = b; t = t + at; stack.append(t);
20:41:54 <Lykaina> t = stack.pop; bt = t; t = stack.pop; at = t; t = bt; t = t + at; stack.append(t);
20:44:21 <Lykaina> no, it's a generalization of python
20:44:44 <korvo> Lykaina: Nice. Paraphrasing Bill Wurtz, "hey somebody could make a forth out of that".
20:45:02 <lisbeths> my first forth in javascript had very similar code
20:46:41 <Lykaina> i'm trying to merge forth and befunge
20:47:30 <esolangs> [[Sleep.]] M https://esolangs.org/w/index.php?diff=152122&oldid=152044 * Buckets * (+127)
20:48:24 <Lykaina> lisbeths: you named after the girl with the dragon tattoo?
20:48:51 <lisbeths> ive read it more times than i can count
20:49:22 <esolangs> [[Sleep.]] M https://esolangs.org/w/index.php?diff=152123&oldid=152122 * Buckets * (+79)
20:49:24 <lisbeths> I have read it via audio book multiple hundreds of times
20:51:41 <lisbeths> ive read the second book a few dozen times and the third book a few dozen times
20:51:51 <lisbeths> the new books I used to own digitally and have read about 20 times
20:52:15 <lisbeths> in every fanfiction of the girl with the dragon tattoo ever written lisebeth has a child with blomkvist
20:52:25 <lisbeths> in the new books they essentially adopt a child together
20:52:56 <lisbeths> apparently people view lisbeth very maternally
20:59:14 <esolangs> [[Sleep.]] M https://esolangs.org/w/index.php?diff=152124&oldid=152123 * Buckets * (+609)
21:04:26 <esolangs> [[Sleep.]] M https://esolangs.org/w/index.php?diff=152125&oldid=152124 * Buckets * (+159)
21:06:28 <esolangs> [[Sleep.]] M https://esolangs.org/w/index.php?diff=152126&oldid=152125 * Buckets * (+7)
21:07:02 <esolangs> [[Sleep.]] M https://esolangs.org/w/index.php?diff=152127&oldid=152126 * Buckets * (+7)
21:07:41 <esolangs> [[Sleep.]] M https://esolangs.org/w/index.php?diff=152128&oldid=152127 * Buckets * (+3)
21:33:53 <Lykaina> 27 of those 55 are not specific to befunge-93 or fungeball
21:34:48 <Lykaina> so half had to do with grids and threading
21:37:23 <Lykaina> 4 of those remaining are i/o
21:41:30 <b_jonas> Lykaina: is this for making a hardware befunge interpreter?
21:42:59 <Lykaina> no, i'm just over-complicating my code
21:43:32 <Lykaina> but i am thinking of asm-like instructions
21:44:47 <Lykaina> trying to see if i can make something forthy
21:46:34 <Lykaina> from at most 36 immutable instructions
21:48:14 <b_jonas> what size are the stack elements, what size if the two-dimensional befunge arena, and are you using the same ALU for the + builtin of befunge and for advancing the instruction pointer?
21:49:39 <Lykaina> right now, i'm moving to a 1-d unidirectional generalization of the language
21:50:09 <b_jonas> unefunge control flow sucks so I hope you have something better for it
21:53:08 <Lykaina> it's becoming closer to a forth
21:56:39 <Lykaina> (i'm not working on fungeball, but something it inspired me to work on)
22:30:02 <lisbeths> so we got a couple interesting things
22:30:19 <lisbeths> exhibit b: nmcr(){ sh|sh>&2;};mcr17(){ if [ "$1" = f ] ;then (cat "$2";cat)|nmcr;elif [ "$1" = e ] ;then (echo "$2";cat)|nmcr;else nmcr;fi;};
22:30:40 <lisbeths> exhibit b is for people who dont know how to preload some data into exhibit a
22:30:54 <lisbeths> if you know the shell well all you need is exhibit a
22:35:22 <lisbeths> now I realize the cat command is useless because I can call cat from the e option
22:41:40 <lisbeths> eh this is a little nicer mcr17(){ if [ "$1" ] ;then sh -e "$1"|sh>&2;else sh|sh>&2;fi;};
22:43:37 -!- ais523 has joined.
22:53:48 -!- molson_ has joined.
22:56:21 -!- molson has quit (Ping timeout: 248 seconds).
23:20:36 <lisbeths> mcr17(){ if [ "$1" ] ;then sh -e "$1"|sh|sh>&2;else sh|sh|sh>&2;fi;};
23:51:27 <lisbeths> mcr17(){ (echo "$1";cat)|sh|sh|sh>&2;}; this one is superior to that one by far
23:57:51 <esolangs> [[User:Anthonykozar/Notes]] https://esolangs.org/w/index.php?diff=152129&oldid=152121 * Anthonykozar * (+69) More languages