News for hackers. Stuff that matters.
Re:Teaching Compilers Backward by smasher164 on Tuesday February 23, 2021 @09:58AM (#26238007)
Much to the chagrin of a lot of educators, I think this approach is the way to go. Too many compilers classes get bogged down in grammar classifications and parsing.

Some argue that parsing is a microcosm of the rest of the compiler, since it requires one to transform a program from one representation to another. However, this message doesn't really come across when you're operating on highly unstructured input, and not doing any simplification passes.

I think execution is really important for visualizing the effects of your work.

Re:Teaching Compilers Backward by todd8 on Tuesday February 23, 2021 @01:12PM (#26240591)
Absolutely.

I became interested in compilers while in graduate school in the 70's and I spent many many hours studying Aho and Ulman's two volumes work on compilers that preceded their Dragon book [1]. The first volume was all about parsing, mostly LR (bottom-up) parsing and it's variations. These books resembled math books more than CS books. A few years before, Knuth had invented LR parsing [2] and I think that CS departments were still enthralled by the fascinating formal theory discovered around parsing. Aho and Ulman's Dragon Books on compiling are much more balanced.

I was fascinated by the formal methods that could be used to specify a language's grammar and then the automated generation of a parser from the grammar. I even went so far as to write a LR parser generator in Fortran IV back then.

Once I got into industry and was working in a group doing real-world compiler development I realized that there is a lot more than just lexical scanning and parsing going on in a compiler, it's tool chain, and runtime.

Teaching compilers backwards sounds like a really good approach for students learning compilers.

On a slightly broader but related topic, many programmers have never been exposed to assembly language, parameter passing mechanisms or how a program turns into a process. Anyone interested in system level programming in the real-world could benefit from Bryant and O'Hallaron's Computer Systems: A Programmer's Perspective [3]. This is not an easy book, but it is excellent and suitable for undergraduate CS students in their 3rd or 4th year.

[1] Aho and Ulman, Compiling (Theory of Parsing, Translation and Compiling), Vol 1 (1972) & Vol 2 (1973), Prentice Hall.

[2] https://en.wikipedia.org/wiki/LR_parser

[3] https://www.amazon.com/Computer-Systems-Programmers-Perspect...

Re:Teaching Compilers Backward by WalterBright on Wednesday February 24, 2021 @01:17AM (#26247158)
> Once I got into industry and was working in a group doing real-world compiler development I realized that there is a lot more than just lexical scanning and parsing going on in a compiler, it's tool chain, and runtime.

Lexing and parsing is less than 1% of the job of building a compiler. (Completely ignoring tool chain and runtime.)

Re:Teaching Compilers Backward by lisper on Tuesday February 23, 2021 @11:59AM (#26239642)
> Too many compilers classes get bogged down in grammar classifications and parsing.

Oh so very this.

This has repercussions far beyond students who can't write compilers. It infects the entire culture of software engineering with people who think that syntax is everything, and who spend their lives designing grammars and writing parsers for them. The problem with that is for every new grammar, it's not just that you need a new parser, but some human needs to learn that grammar too if it's going to do you any good at all. So we have this proliferation of zillions of grammars, not just in programming languages, but in config files, data formats, etc. Two examples: XML and JSON are bad re-inventions of S-expressions. And the sieve language (which I am currently dealing with because I'm working on a new spam filter) is just an abomination from top to bottom.

Re:Teaching Compilers Backward by slaymaker1907 on Tuesday February 23, 2021 @03:19PM (#26242360)
I agree about XML, but I don't think JSON is a reinvention of S-expression. JSON is great if you are representing a lot of (string) key/value data since it has a canonical way of representing string keyed dictionaries. I guess you can represent these as a list of pairs, but that obviously is ambiguous to a a list of pairs... JSON doesn't have this problem since if you see {"name": ...} you know that you are reading an object which has a 1-1 mapping to a dictionary with string keys.

While this seems like an innocent change, it simplifies serialization a lot. A generic S-expression deserializier can't make nearly as many assumptions as a JSON deserializer can.

S-expressions have first class support for primitives (i.e. strings, numbers, etc.) and lists but nothing else. On the other hand, JSON has first class support for the same plus string keyed dictionaries. It is no coincidence that most other generic serialization formats have included at least support for string dictionaries if not other key types as well.

Re:Teaching Compilers Backward by lisper on Tuesday February 23, 2021 @03:37PM (#26242556)
Sure, but 1) s-expressions also have native symbols whereas JSON has only strings, and 2) it is trivial to extend standard s-expression syntax to include a native dictionary serialization, and to extend existing s-expression parsers to parse that extension. It is much, much harder to add symbols to JSON. JSON is also very profligate with its use of punctuation, with tons of unnecessary commas and colons all over the place. So I stand by my initial characterization.

Also, Common Lisp s-expressions include a standard syntax for structures, which are essentially dictionaries. Extending that to a generic dictionary (using, say, #D(key value key value ...), which is actually available) takes about three lines of code.

Re:Teaching Compilers Backward by munificent on Tuesday February 23, 2021 @04:10PM (#26242933)
> 1) s-expressions also have native symbols whereas JSON has only strings,

This is inconsistent with the claim that s-exprs are better because of their simplicity. Having two very similar string-like things is unnecessarily complex for little (no?) benefit in return.

2) > it is trivial to extend standard s-expression syntax to include a native dictionary serialization

Sure, and when you do you get something at about the level of complexity of JSON, so it's not clear what the value proposition is here.

> JSON is also very profligate with its use of punctuation, with tons of unnecessary commas and colons all over the place. So I stand by my initial characterization.

JSON uses a richer set of delimiters, which provides:

1. Greater brevity. Basic information theory says that it takes fewer characters to encode a given piece of data if your character set is larger.

2. Some level of redundancy. This isn't necessary for data transmission for JSON, but it does make it much easier for parsers to provide good localized error reporting.

3. Easier visual parsing. Most humans have functional eyeballs connected to optical processing neurons dedicated to detecting different shapes. Using characters with a greater variety of shapes to encode structure takes advantage of that.

Don't get me wrong, I like Lisps and s-exprs. But it seems like any time any notation comes up for discussion, a lisper appears to claim how s-exprs are clearly superior. This despite the fact that that notation is decades older than almost every other syntax out there and yet still lost the popularity contest.

Re:Teaching Compilers Backward by tikhonj on Tuesday February 23, 2021 @08:03PM (#26245287)
I mean, greater brevity in theory, but having used both s-expressions and JSON for config files, I can tell you that the s-expression version ends up noticeably less verbose and noisy in practice.

> This despite the fact that that notation is decades older than almost every other syntax out there and yet still lost the popularity contest.

Beyond some minimal level, quality and popularity aren't all that heavily correlated; something not becoming popular tells us almost nothing about it.

Re:Teaching Compilers Backward by tomjakubowski on Tuesday February 23, 2021 @08:39PM (#26245566)
> Having two very similar string-like things is unnecessarily complex for little (no?) benefit in return.

Using symbols (or :keywords) and strings together offers many benefits:

1. Like with JSON's richer syntax for aggregates, omitting the "" makes for much easier visual parsing. Especially if symbols are usually used for keys.

2. Symbols may be suitable for interning, perhaps into a set used to validate input data. Strings usually aren't.

3. Most importantly, with this distinction, symbols can be imbued with particular semantics: they can be commands, references, lookup keys, whatever the program needs. Strings are just data, usually to be displayed somewhere to be read by someone, or to be parsed by something nasty like an interpreter.

The most human-readable data notation I know of is EDN. It combines the best of JSON and s-expressions.

Re:Teaching Compilers Backward by dragonwriter on Tuesday February 23, 2021 @04:37PM (#26243216)
> s-expressions also have native symbols whereas JSON has only strings

I'm not sure “native symbols” are a good thing in an interchange format. If you are serializing constructs from a language (Lisp, Erlang, Ruby) where that's a fundamental type, sure, it's convenient, but largely that’s a language implementation detail, from an interchange perspective there's not a lot of reason to distinguish symbols from (possibly format-constrained) strings. That they are immutable (in languages where strings are either wise mutable) and/or interned doesn't mean anything at the interchange level.

Re:Teaching Compilers Backward by lisper on Wednesday February 24, 2021 @01:48AM (#26247317)
> I'm not sure “native symbols” are a good thing in an interchange format.

"Try", "writing", "a", "sentence", "in", "JSON", "syntax", "some", "time", "and", "I", "guarantee", "you", "will", "change", "your", "mind"

Re:Teaching Compilers Backward by deckard1 on Tuesday February 23, 2021 @04:27PM (#26243094)
> 1) s-expressions also have native symbols whereas JSON has only strings

The only standardization effort of generalized s-expressions that I know of is http://people.csail.mit.edu/rivest/Sexp.txt, which makes strings and symbols/tokens equivalent.

Most languages do not have a runtime symbol table or the concept of a symbol as a data atom. In languages outside Lisp, what would a symbol even mean?

> extend existing s-expression parsers to parse that extension. It is much, much harder to add symbols to JSON

This sounds like a form of "No True Scotsman" argument. If you're extending S-Exp parsing via Lisp, then you can extend JSON parsing too. Once you add code, then it's not a format. It's whatever you want it to be.

> Extending that to a generic dictionary (using, say, #D(key value key value ...), which is actually available) takes about three lines of code.

Three lines of code in what language? C? C++? Java? It should be obvious you're conflating two things here. Generalized formats vs. a full Lisp ecosystem.

Re:Teaching Compilers Backward by touisteur on Tuesday February 23, 2021 @01:05PM (#26240508)
And you need the gazillion things on top of a grammar. Error recovery, IDE, language server, formatter, all the memory bugs, all the semantics that's not described in a formal language (and you can't auto-generate code to check or request it), all the binding generators for other languages and linking conventions... Ugh I wish we had a standard tool for that, like a much much much expanded yacc + interpreter generator + batteries included... There's something with libadalang and its language-agnostic tooling langkit (https://github.com/AdaCore/lang kit) that is very seducing (write once generate much code).
Re:Teaching Compilers Backward by touisteur on Tuesday February 23, 2021 @01:23PM (#26240727)
Previous discussion on automatic tool chain + interpreter generation : https://news.ycombinator.com/item?id=21917927
Re:Teaching Compilers Backward by mingodad on Wednesday February 24, 2021 @06:31AM (#26248882)
I think that the now defunct dotGNU http://www.dotgnu.org/ was trying to do it, one of the nice things it left us is libjit https://www.gnu.org/software/libjit/
Re:Teaching Compilers Backward by touisteur on Monday March 01, 2021 @04:36PM (#26308761)
Sorry I'm trying to find out more but the project is a bit confusing. I found http://www.dotgnu.org/treecc_essay.html that looks of historical value (nowadays using java code generation / bytecode engineering quite often with amazing success). And of course libjit, but I'm at a loss finding out about semantic attributes and functions & typechecking and others.
Re:Teaching Compilers Backward by peteretep on Tuesday February 23, 2021 @07:06PM (#26244800)
> Two examples: XML and JSON are bad re-inventions of S-expressions.

What? This sounds like you read something that was true but you’ve misunderstood and regurgitated.

XML is absolutely S-expressions, JSON is absolutely not. How in the heck is JSON a reinvention of an S-expression?

Re:Teaching Compilers Backward by lisper on Tuesday February 23, 2021 @08:08PM (#26245338)
How is it not? Both are serialization formats for trees with strings and numbers at the leaves.
Re:Teaching Compilers Backward by peteretep on Tuesday February 23, 2021 @09:33PM (#26245938)
Is there a serialization format you don't consider to be a bad re-invention of S-expressions?
Re:Teaching Compilers Backward by lisper on Tuesday February 23, 2021 @09:46PM (#26246029)
Of course. There are many. Any binary format. Any ASN.1 format. DEF and LEF for hardware descriptions. The output of mysqldump.

Here's another example:

https://github.com/rongarret/tweetnacl/blob/master/ratchet.l...

starting at line 82. (That's one that I designed.)

Re:Teaching Compilers Backward by konjin on Tuesday February 23, 2021 @08:32PM (#26245525)
>XML is absolutely S-expressions

You need a lot of predefined structure to capture attributes using brackets, much more than you do for dictionaries - which are just ordered pairs in a list when serialized.

Re:Teaching Compilers Backward by peteretep on Tuesday February 23, 2021 @09:35PM (#26245948)
(apologies, ninja deleted, I do not wish to continue this discussion)
Re:Teaching Compilers Backward by konjin on Tuesday February 23, 2021 @09:37PM (#26245965)
There isn't a difference when it's serialized.
Re:Teaching Compilers Backward by megameter on Tuesday February 23, 2021 @02:58PM (#26242102)
As an informally trained writer of compilers, I believe parsing could be reduced to just these concepts:

1. Greedy matching

2. Minimal matching

3. Tokenization

Regular expressions and implementation of a subset of their operators are a good way to introduce and discuss each, and recursive descent is the elaboration on that, the graduation to a customized mechanism. The last is to generalize it all to a form of constraint logic and introduce other forms of backtracking(e.g. pathfinding algorithms). Discussion of types follows from discussion of constraints and explains "smartness" in compilers, so it might be the last thing if I were teaching the course.

What I really think is at issue with our vast number of grammars is just the reliance on text as the interface. If we discuss parsing as a thing applicable to arbitrary data streams we can start asking "well, what if we don't serialize it to characters, but to some other token format?" That is way more interesting today, since we seem to have dispensed with the premise of natural language being the way to program computers, that really got the whole parsing thing started.

Re:Teaching Compilers Backward by umanwizard on Wednesday February 24, 2021 @03:02PM (#26254968)
I have a basic Sieve interpreter in Rust here, if you're interested: https://crates.io/crates/libsieve

It's not very featureful or well-tested, but it does work for my own use (personal e-mail server).

Re:Teaching Compilers Backward by Jtsummers on Tuesday February 23, 2021 @10:56AM (#26238739)
Yeah. I got really good at parsing to an AST and various semantic analysis steps. One course got too bogged down there and we never went further. Another got to the point of emitting machine code, but no optimizations. Only one, in grad school, actually went the whole way (prof could assume knowledge of parsing so that step was fast) with anything on optimizations.

Given that parsing is also a critical part of many CS theory courses (or parsing theory), it was somewhat redundant to have spent so much time on it again in the compilers class given the overall time constraint, and frustrating to start on it and run past the planned time repeatedly in courses.

Re:Teaching Compilers Backward by kazinator on Tuesday February 23, 2021 @12:41PM (#26240242)
Optimizing work requires wrangling fairly complex, multi-faceted data structures like augmented graphs. Unless you do that in a very high level language in which that is as easy as possible, it's largely intractable for undergrad.

When I did this stuff in school, it was C on Unix. Nobody was going to get to a debugged data flow analysis of basic blocks with all the liveness info, optional register allocation, DAG-driven CSE, and whatever topics out of the Dragon Book. Not in one or even two semesters, with undergrad-level C skills, and a full load of other courses.

I think that working in Java wouldn't help much. You don't have premature free problem in Java, but in a batch compiler written in C, you can just avoid calling free.

Re:Teaching Compilers Backward by Jasper_ on Tuesday February 23, 2021 @12:47PM (#26240306)
The overemphasis on parsing is ridiculous, with way too much theory that has little practical application. Parsing is boring, IMHO -- production compilers basically all use hand-written recursive descent, it's boring but it works just fine and is plenty readable, no need to replace it.

The rest of the compiler is far more interesting, but a few people in the 60s got caught up on parsing theory based on limitations of their computers at the time, so there's a lot more formalism and theory and of course that's what academia teaches.

Re:Teaching Compilers Backward by todd8 on Tuesday February 23, 2021 @01:21PM (#26240698)
After working with real-world compilers in industry I was surprised to hear CS professors that taught the compiler class say that no one should be writing parsers by hand because compiler writers should just build a table driven parser using YACC.

The error messages are so much better coming out of recursive descent parsers. (I know that there are all sorts of mechanisms for better error messages, but back when I heard this statement there was nothing that really worked well. Does any compiler with good error messages today really use LR parsing?)

Re:Teaching Compilers Backward by PartiallyTyped on Tuesday February 23, 2021 @02:50PM (#26241996)
A professor in gradschool insisted on us writing hand-written parsers to better understand associativity, operant ordering and so on and identify useful patterns, then implementing ASTs and interpreters directly ontop of the parsers. It was a tough class, but to be honest it was one of the most fun ones as well.

In undergrad, I asked the professor assigned the compilers class whether he would offer it during fall, but he said that unless he managed to completely revamp the class into more real-world and practical stuff like using LLVM backend instead of wasting time on parsers like in the dragon book and the tiger book, he wouldnt offer it.

Re:Teaching Compilers Backward by hctaw on Tuesday February 23, 2021 @01:38PM (#26240975)
This has been my experience as well, but I'd extend it to parsing in production. There are a million reasons why you need to write custom parsing code and 99% of them are faster and better implemented by hand than using a generator.
Re:Teaching Compilers Backward by CalChris on Tuesday February 23, 2021 @04:51PM (#26243366)
Moreover, buggy parsing code is massive security hole.
Re:Teaching Compilers Backward by hctaw on Tuesday February 23, 2021 @06:19PM (#26244393)
well anything that takes untrusted input that might need to be validated with parsing is a massive security hole. Parsing generators don't fix this class of bug, they just change how it manifests.
Re:Teaching Compilers Backward by tester756 on Tuesday February 23, 2021 @05:02PM (#26243492)
why?
Re:Teaching Compilers Backward by not2b on Tuesday February 23, 2021 @03:44PM (#26242630)
gcc ripped out its bison-generated parsers in favor of recursive descent parsers long ago, for exactly this reason (also, because C++ isn't LR-n for any n, so to get bison to work as well a third pass called "spew" sat between the lexer and the Bison parser so it could do arbitrary lookahead to figure out what the tokens were).
Re:Teaching Compilers Backward by smasher164 on Tuesday February 23, 2021 @01:40PM (#26241015)
I think if schools want to give a taste of the parsing->execution flow, they should have students implement an NFA based regular expression engine. No fancy features like captures and named character classes, just the primitive operations will do.

Regular expression syntax is context-free anyways, so they could use grammars if they wanted. Then again, you have to wonder if all of this should be covered by a theory or PL class instead.

Re:Teaching Compilers Backward by JoelMcCracken on Tuesday February 23, 2021 @10:42AM (#26238545)
This is what happened in my compilers class. We spent, like, the whole thing talking about grammars etc. Which is mind-numbingly boring (to me), and especially given a significant number of industry parsers are hand-rolled/recursive descent style, its not terribly useful information.
Re:Teaching Compilers Backward by ahartmetz on Tuesday February 23, 2021 @12:59PM (#26240442)
Same here, at FU Berlin. We spent several weeks on LR and LALR parsers and such and, IIRC, even more than a week on regular expressions. Somehow we talked about two-address and three-address instructions, but never seemed to do any code generation, and certainly no optimization. It was very disappointing.
Re:Teaching Compilers Backward by Nohortax on Tuesday February 23, 2021 @01:29PM (#26240834)
I agree
Re:Teaching Compilers Backward by JoelMcCracken on Tuesday February 23, 2021 @11:13AM (#26238993)
At the moment, some of us in the PGH FP group are working through https://www.cs.cmu.edu/~rwh/pfpl/, and so far I vastly prefer it. It is math heavy, which I like for various personal reasons which are irrelevant here, but it also skips parsing!
Re:Teaching Compilers Backward by pklausler on Tuesday February 23, 2021 @01:47PM (#26241125)
I've worked on production compilers for the bulk of my 40-year career. I prefer optimizers and code generators, but recently had to build a parser for modern Fortran for LLVM, and just used parser combinators to construct a recursive descent recognizer over a normalized contiguous source string in memory. The theory of formal languages is interesting but I think that the whole project of "compiler-compilers" from the 70's and 80's was working toward a solution that's inferior to where we are today with better tooling and less theory.
Re:Teaching Compilers Backward by krueger71 on Wednesday February 24, 2021 @03:29AM (#26247868)
I remember back in the late 90's when I was studying Computer Science at Lund University, Sweden. They had a research focus in compilers and had their own Simula-compiler if I remember correctly. When they taught compilers, students first had to take the low level programming course where you needed to build a compiler back-end for an in-house IL. The first compiler course you could take after that was very focused on the practical aspects of building a front-end for the back-end you already had. Theory was pretty minimalistic at this point if I remember correctly. You got the hang of basic operator precendence parsing with a recommendation to use if for the expressions in our toy language and recursive decent for the rest. Of course this was almost like throwing someone at the deep end of the pool and se what happens. A grueling course that was renowned by students to be one of the more work intensive in the whole curriculum at that time. A lot of late nights in the computer lab for sure.

Afterwards, when I had the second more theoretical compiler course, I did feel that all that practical hard work to make a fully functioning compiler with mostly elbow grease gave an appreciation of the theoretical constructs that could make this more tractable.

Re:Teaching Compilers Backward by hinkley on Tuesday February 23, 2021 @03:04PM (#26242173)
I wanted to write a computer language when I was still young and did not quite realize what a commitment that was. Like buying a parrot instead of a hamster.

Every compiler compiler description I could find rankled. Because I thought about how a code review works, how the human breaks down a block of code to figure out ah, this comma does not belong here. Then how to unpack that information for the tired intern (or classmate) so they understand why the compiler keeps saying "unexpected 'if' on line <five lines later>".

Compiler grammars, it turns out, have absolutely no compassion for humans, their stupid opinions, or their squishy little language cortex. I found that quite offputting. Revolting, even, so I put it down and came back later.

SGLR got close to "YES, I am not crazy!" but at the time I still thought 'write a PL' there was only one and it was not very good.

Re:Teaching Compilers Backward by pjmlp on Tuesday February 23, 2021 @10:39AM (#26238509)
Agreed, we did it all the way, but that was just in the course of a 5 years degree there was room to spend three semesters having compiler design related lectures, split between parser theory, denotational semantics, programming language history and implementing our own toy compiler.
Re:Teaching Compilers Backward by whateveracct on Tuesday February 23, 2021 @12:27PM (#26240039)
the best PL/compilers classes i took were using Scheme, with a simple pattern matching macro [1]

so there was no parsing. it was just s-exps. But you still got to write interpreters with different semantics & compilers.

[1] https://gist.github.com/cbrooks90/125393006ec7bd137ff6364a9f...

Re:Teaching Compilers Backward by Animats on Tuesday February 23, 2021 @02:00PM (#26241323)
That's a good point. Students get bogged down in parsing, which is a solved problem but a fussy one with way too much theory. Then the course glosses over optimization and code generation, which is where all the real work takes place.
Re:Teaching Compilers Backward by waynesonfire on Tuesday February 23, 2021 @11:31AM (#26239226)
And, it seems to be is a really understood problem that has efficient solutions.
Re:Teaching Compilers Backward by smasher164 on Tuesday February 23, 2021 @01:03PM (#26240487)
Yes and no. The traditional goal of a parser that accepts valid inputs, and rejects invalid inputs is well understood.

A more relevant goal of error-tolerant parsers that can respond quickly to incremental changes is still a wide research problem.