h = hash(to_canonical_form(AST))
Preferably, there should be one-and-only-one way to perform or compute things, but modern PLs plagued by flexibility syndrome.
Also, the same should be done for the binaries, since the same AST may produce different binaries, unless you take into account all the compiler options, and runtime differences.
Determining if two programs are equivalent is generally as hard as running the programs for every input and comparing them.
Some practical solutions:
- reduce code variability, by removing similar/alternative programming constructs / flexibility syndrome
- stick to a single programming paradigm
- remove syntactic sugar, or provide a clear rules to reduce it to a sugarless canonical form
- use a rich standard library (to avoid reimplementing the same functionality in different ways)
- use rich standard data types (to avoid definition of the similar types in different ways)
- sort every unordered construct, similarly how AWS signature sorts the keys before calculating the API call signature
- reduce the use of macros, custom eDSLs, or highly personalized code (by making writing this kind of code inconvinient)
- etc.
In what sense?
I mean, in the following code
# version 0
name = "bob"
I branch and change to # version 1
name = "alice"
And you update the main branch to # version 2
name = "clair"
Then I'll still have a merge conflict right?How does a content addressed AST solve the problem of having a different intent?
https://www.unison-lang.org/learn/usage-topics/workflow-how-...
This video is a little old but I remember finding it really interesting and I think dives into it a bit.