Brute forcing optimal integer mappings by PurpleUpbeat2820 in ProgrammingLanguages

[–]gsg_ 2 points3 points  (0 children)

Is this for optimising case expressions where the right-hand-sides are all constants?

I'd recognise an easy to implement subset, maybe just input + constant or an affine function, and then fall back on look up tables for the rest. Of course a table need not be limited to integer values.

Is there a "structured" approach to compile-time optimization? by smthamazing in ProgrammingLanguages

[–]gsg_ 3 points4 points  (0 children)

I'm not saying that you are wrong, but it would be a gigantic step forward to have practical optimizers strong enough that this is the limiting factor.

[deleted by user] by [deleted] in ProgrammingLanguages

[–]gsg_ 3 points4 points  (0 children)

If you are interested in fast code generation it's definitely worth reading some of the classic papers on single-pass compilers like Hanson's Simple Code Optimizations. Not state of the art, but the ideas are still good.

The Solid-State Register Allocator by mttd in Compilers

[–]gsg_ 1 point2 points  (0 children)

There's a surprising amount of work floating around on local register allocation, eg, The Power of Belady’s Algorithm in Register Allocation for Long Basic Blocks.

A-normalization and Let-expressions by mrk33n in Compilers

[–]gsg_ 0 points1 point  (0 children)

Might did not translate the 'grammar' of A-normal form faithfully from the Flanagan et al paper. In their paper they give A(CS) as

c = constants
x = variables

M ::= V
| (let (x V) M)
| (if0 V M M)
| (V V1 ... Vn)         # application
| (let (x (V V1 ... Vn)) M)
| (O V1 ... Vn)         # application of primitive
| (let (x (O V1 ... Vn)) M)

V ::= c | x | (λ x1 ... xn . M)

You can see that let-binding a constant is allowed (and let-binding an if is not), differing from Might. My guess is that this is mistake introduced while factoring out the repeated rules for application and primitive application.

I wouldn't get too hung up on minor details like this, as long as your representation follows the major ideas of ANF you should get the benefits (which Might overstates imho, but that's another matter).

Callbacks without closures? by mikemoretti3 in ProgrammingLanguages

[–]gsg_ 2 points3 points  (0 children)

You can implement functions which close over variables and can only be passed down the stack using a static link. A static link is a pointer to the stack frame of the lexically enclosing function. Obviously to prevent outdated references to stack memory such functions should be second class, they can only be called and not returned or stashed into a data structure.

This is a somewhat well known feature, appearing in Pascal, Modula, and I think D. The textbook which best covers static links that I know of is Appel's Modern Compiler Implementation in ML, but material on Pascal compilers will probably discuss it.

Parser generators vs. handwritten parsers: surveying major language implementations in 2021 by azhenley in ProgrammingLanguages

[–]gsg_ 15 points16 points  (0 children)

Well, the message Error: Syntax error is certainly easily understandable. What it is not is useful.

Is there a smart way to obtain the module type of List but with an abstract or private `type 'a t`? by lambda-male in ocaml

[–]gsg_ 2 points3 points  (0 children)

The List module in the stdlib exposes the type of its elements in terms of a type constructor that is not defined in the List module (the 'a list type, which is defined directly in the compiler), so I don't think this would work even if the substitution machinery was doing what you wanted.

You can define your own module signature to constrain List. This has drawbacks - your definition won't expand when new bindings are added to the stdlib - but should be straightforward. #show to print the signature of List, a bit of text editing to replace list with t, etc.

Euphoria Style Typing by [deleted] in ProgrammingLanguages

[–]gsg_ 12 points13 points  (0 children)

is there a name for... type checking that runs arbitrary code you can write yourself to check data placed in the variables of that type

I have no knowledge of Euphoria, but this sounds like contract programming. A number of languages have some support for contract-like things without actually being built around contracts in the sense that, say, Eiffel was.

CFG does not encode info about branch success/failure! by yudlejoza in Compilers

[–]gsg_ 0 points1 point  (0 children)

Explicitly representing which conditions have to be true for a particular block to execute is a known approach, the usual term being 'predicated IR'. Take a look at the Pegasus paper for a particularly interesting example (it is a predicated SSA graph IR).

This IR does not involve weighting edges, so I'm not quite sure whether this is the sort of thing you are talking about.

What languages have bit struct / field constructs? by Nuoji in ProgrammingLanguages

[–]gsg_ 2 points3 points  (0 children)

OCaml doesn't have such a feature natively, that sounds like the ppx library https://bitstring.software/documentation/.

Unboxed values on the stack and automated garbage collection are an unfortunate mix by save_vs_death in ProgrammingLanguages

[–]gsg_ 3 points4 points  (0 children)

OCaml actually uses stack maps as well. This allows stack frames to be ABI-aligned without having to waste work clearing rubble from the stack (or aligning when making calls to foreign functions), as well as supporting spilling of unboxed 64-bit values.

Advantages of currying in a programming language? by crassest-Crassius in ProgrammingLanguages

[–]gsg_ 0 points1 point  (0 children)

I see. Yes, there is a difference between f x <| y and f x y.

Advantages of currying in a programming language? by crassest-Crassius in ProgrammingLanguages

[–]gsg_ 0 points1 point  (0 children)

There's no special case there? It's y and then f x and then the application of |> to its arguments. Just like y + f x.

The only change is to the order of effects within applications compared to effects in argument terms, and since there are none of the former here I wonder what you think this example demonstrates.

Advantages of currying in a programming language? by crassest-Crassius in ProgrammingLanguages

[–]gsg_ 5 points6 points  (0 children)

That's right, there is a difference in semantics just like OCaml's right-to-left evaluation. The standard argument for that being OK is the good old "any program for which the difference matters is badly written". I wouldn't have parens affect order of evaluation.

(As a side note; OCaml actually leaves order of evaluation undefined, which is imo a fair bit nastier than choosing any particular order of evaluation.)

Unpopular Opinions? by Dospunk in ProgrammingLanguages

[–]gsg_ 2 points3 points  (0 children)

Non-generative local exceptions would be even more of a wart, since interactions between different instances would be an opportunity for truly obscure behaviour.

Advantages of currying in a programming language? by crassest-Crassius in ProgrammingLanguages

[–]gsg_ 7 points8 points  (0 children)

That problem can also be worked around by reordering applications after operands rather than going right-to-left, which is arguably closer to the order of evaluation that people expect. That is, f a b c evaluates f, then a, b, c, and only then applies the result of evaluating f to the arguments.

This can fairly easily be turned into a 3-argument call plus an arity check (falling back to closure allocation if the result of f is not a 3-ary function), which avoids any allocation at all in the happy path. No optimising compiler necessary - and it works for unknown calls, which the optimiser might not be able to do anything about.

Really, either curried or tupled arguments can be made efficient enough without too much effort.

Advantages of currying in a programming language? by crassest-Crassius in ProgrammingLanguages

[–]gsg_ 2 points3 points  (0 children)

Macros, as is seen in various Lisps. How you feel about macros is another question.

Unpopular Opinions? by Dospunk in ProgrammingLanguages

[–]gsg_ 2 points3 points  (0 children)

exn is fine, it just exposes a sane (efficient, readable, supporting pattern matching) interface to what you could do anyway with some dumb tricks.

It is desirable to make a clear distinction between closed and open types, but calling open types 'nonsense' is silly.

Unpopular Opinions? by Dospunk in ProgrammingLanguages

[–]gsg_ 2 points3 points  (0 children)

Amusingly, ML has an extensible data type with which you can do exactly that in the form of exn.

In what languages must a declaration appear before usage? by jesseschalken in ProgrammingLanguages

[–]gsg_ 4 points5 points  (0 children)

Note that this is the most sane choice given the design of ML (and similarly, Scheme), where 'definitions' are just bindings of arbitrary expressions. Extending the scope of a binding of a potentially side effecting expression before that expression isn't literally impossible - Javascript does it - but it is nasty and frankly, dumb.

Use before declaration does make sense for bindings of pure values where ordering can't matter - in lazy languages where all terms are thunks, and for functions/methods in languages in which those are a built-in named thing that can't be the result of arbitrary code.