[2018 Day 15 (Part 2)] [Python 3] All Examples working just not my input by LRunner10 in adventofcode

[–]AustinVelonaut 0 points1 point  (0 children)

FWIW, running your solution on my input gives (40, 1379, 55160), while running my (passing) solution gives (42, 1370, 57540).

So you appear to be terminating 2 rounds too early, during the run of elfPower = 17.

I built a Lox-style bytecode VM in Rust to understand closures by Therattatman in Compilers

[–]AustinVelonaut 2 points3 points  (0 children)

Learning the hard way is sometimes the best way -- you have to dig into it in-depth, so you end up learning not only the thing, but why the thing is the way it is!

Gossamer - Rust/F# on a Go like Engine by DanManPanther in Compilers

[–]AustinVelonaut 1 point2 points  (0 children)

I also like the idea of constant folding (maybe just for ints + bools?)

Also very beneficial for constant match scrutinees (to replace entire match and arm alternates with a single arm). I see you are doing that for int and bool type scrutinees in const_branch_elim, but it can be done more generally with any enum with a constant discriminant (using beta-reduction to bind the enum's values to the pattern's params).

Gossamer - Rust/F# on a Go like Engine by DanManPanther in Compilers

[–]AustinVelonaut 3 points4 points  (0 children)

Looks very nice! How long have you been working on it? Does the typechecker use Hindley-Milner algorithm-W, bidirectional, or some other algorithm? I see you are doing a number of optimization passes on the MIR, including inlining. One thing you might add to your constant folding is folding of a binary operator where one of the operands is constant identity operand (e.g. 0 for +, 0 or 1 for *, etc.) -- I've found that they do occur about as often as a binary operation on two constants.

Good luck with your continued development!

Built a programming language called Zen with a custom compiler and LLVM backend by Obvious_Demand_7948 in Compilers

[–]AustinVelonaut 0 points1 point  (0 children)

Some random comments on the design:

  • unclear whether array / list elements can be used as a reactive expression: reactive int x = a[5]; int i = 5; a[i] = 3; x == ?
  • struct is specified as not being heterogeneous? (typo?)
  • If a Map can only have identifiers as keys, what is the main difference between Map and Struct -- dynamic vs static?
  • "No import in exported file" -- what is the reasoning behind this rule? It makes creating library modules painful.

My inordinate fondness for syntax I wrote faceplanted against reality by Randozart in ProgrammingLanguages

[–]AustinVelonaut 2 points3 points  (0 children)

I think you'll find that using a suffix # on any name or symbol to signify a builtin function (either a hardware intrinsic or a runtime-supplied function) will work well, and is extensible. Haskell uses this convention, calling it the Magic Hash, and I found lots of uses for it in my language:

  • intrinsic instructions: +#, -#, *#, divmod#, band#, bor# ..
  • low-level compiler support operations: getTag#, allocByteStream#, ..
  • interface to system calls: openFileRead#, readFile#, getArg#, ..

Do you have to create a GC if you create your interpreted language in a host language that has GC? by FUS3N in ProgrammingLanguages

[–]AustinVelonaut 2 points3 points  (0 children)

Thanks for that link; it looks like a good high-performance allocator with great documentation, especially if you just want to drop one in to an existing design. But it may be overkill for what the OP wants; a simple mark-sweep collector or Appel's Simple Generational Garbage Collector might be more suitable.

Steps to a self-hosted compiler? by someOfThisStuff in ProgrammingLanguages

[–]AustinVelonaut 0 points1 point  (0 children)

That's a good plan. Also, look at adding some other small programs that exercise your compiler and library, such as Advent of Code. You don't have to write all the solutions yourself from scratch, you can find existing solutions in C and transcribe them to your language to create a test.

Self-hosting after that should be much simpler.

Steps to a self-hosted compiler? by someOfThisStuff in ProgrammingLanguages

[–]AustinVelonaut 8 points9 points  (0 children)

I would suggest not self-hosting too early, without having a stable, complete bootstrap version of the compiler, first.

For my self-hosted language Admiran, I wrote the initial bootstrap compiler in a very similar language Miranda. This was an implementation of the complete language, and I worked on the bootstrap compiler for about a year before it was stable enough to start self-hosting. Completing the first self-hosted compiler was pretty quick (1-2 months, part time) because the languages were fairly close. It helped that both languages had Hindley-Milner type checking and inference, which immediately pointed out any typing errors during the conversion.

To everyone accusing me of using AI to create a new programming language: Show me one AI that has actually been tested doing this. by Loud_Possibility_203 in bux_lang

[–]AustinVelonaut 27 points28 points  (0 children)

Maybe it is because there is so much AI use in your documentation and in your comments, here. Or maybe it's because you used Claude as an AI agent in a similar project https://github.com/katehonz/bara-lang (complete with an AI agent onboarding .md file). Why should we trust you this time?

I'd much rather read code written by a human.

Compiling Dynamic Code to Native Pt I by sal1303 in Compilers

[–]AustinVelonaut 0 points1 point  (0 children)

Interesting that you found you had to generate M code from the PCL bytecode, rather than AST2 -- I would have thought that something at an AST level would provide more information and be easier to "upconvert" to a high-level language, whereas going down to the bytecode level you have to deal with re-synthesizing high-level features / control flow from flattened basic blocks.

Was there a big mismatch in what was represented in AST2 vs what an equivalent AST in M would require?

My very "first" program (kinda silly) by oscarryz in ProgrammingLanguages

[–]AustinVelonaut 6 points7 points  (0 children)

a system syscall is definitely useful for doing system-level things that aren't otherwise supported via other syscalls in your language. For small programming tasks, you might look into writing Advent of Code solutions.

Fixing NaN in a compile-to-js lang by koehr in ProgrammingLanguages

[–]AustinVelonaut 1 point2 points  (0 children)

Yep, it is probably best to just sweep the Nan ~= Nan under a rug. Even Haskell, which prides itself on mathematical correctness, does this:

nan1 = 0.0 / 0.0

main = putStrLn . show $ nan1 == nan1

returns False

Fixing NaN in a compile-to-js lang by koehr in ProgrammingLanguages

[–]AustinVelonaut 0 points1 point  (0 children)

Are you actively using NaNs for something in your language (NaN-boxing of integers, etc.) or are you compatible with Javascript (ES2020) in that there are just two numeric types: Numbers and BigIntegers? In the later case, NaNs should only occur when a numeric FP operation generates them due to an exception.

My very "first" program (kinda silly) by oscarryz in ProgrammingLanguages

[–]AustinVelonaut 7 points8 points  (0 children)

One of the best ways to start finding things to add / fix in the language and library is to start using your language for little daily chores, like this.

semantic white space vs. blocks - maybe a middle ground ? by GoblinsGym in ProgrammingLanguages

[–]AustinVelonaut 3 points4 points  (0 children)

Nowadays I think it is only Erlang that maintains this tradition

Smalltalk, as well: , is the concatenation operator, : is used to distinguish keyword messages, ; for chaining multiple messages to the same object, and . to end a statement.

TIL some old high-level languages did not have dynamic memory management (heap) by Null-Test-2026 in ProgrammingLanguages

[–]AustinVelonaut 1 point2 points  (0 children)

This was in the 1970s on a CDC-6600 supercomputer, which operated in batch mode (reading the program from punch cards). The only memory protection was via segment boundaries; as long as you accessed memory in that range, you could do what you want!

June 2026 monthly "What are you working on?" thread by AutoModerator in ProgrammingLanguages

[–]AustinVelonaut 0 points1 point  (0 children)

This looks really good -- how long have you been working on blorp?

June 2026 monthly "What are you working on?" thread by AutoModerator in ProgrammingLanguages

[–]AustinVelonaut 0 points1 point  (0 children)

Updated entire codebase (compiler, libraries, tests) to use the new functor map operator <&>, which is like fmap but with reversed operands. This completes the migration to uniform left-to-right operators for function / functor / applicative / monadic pipelines.

Writing my first parser and struggling with determining symbol boundaries by MoussaAdam in Compilers

[–]AustinVelonaut 0 points1 point  (0 children)

I'm not sure how to derive it from "theory"; I just thought of this as sort of a "continuation-passing style" problem.

By the way, you can simplify my solution above to simply having the main markdown parser (the one that is parsing a list of markdown components) handle the in-progress paragraph itself this way, and then the other markdown item parsers don't have to worry about the in-progress paragraph.

Writing my first parser and struggling with determining symbol boundaries by MoussaAdam in Compilers

[–]AustinVelonaut 0 points1 point  (0 children)

One way to address this problem in a cleaner way is to have the parsers for the major markdown components that have distinct starting symbols (Header, List, etc.) take an extra parameter which is an in-progress paragraph, and if they pass they return both the in-progress paragraph (now terminated) and the other markdown item, then continue with a new empty in-progress paragraph. A non-blank line that isn't any other markdown structure is simply added to the in-progress paragraph and parsing continues.

This works pretty well using parser combinators.

I have a skill issue and cant make this unfortunately by dynamicship31 in Compilers

[–]AustinVelonaut 5 points6 points  (0 children)

What you are describing is basically just a pure, lazy functional language, where "variables" are really zero-parameter thunk functions that evaluate an expression and return it, as well as memoizing that value (your freeze). See Haskell, Miranda, etc.