{"id":16862403,"url":"https://github.com/dave/forky","last_synced_at":"2025-04-11T08:57:22.600Z","repository":{"id":143254194,"uuid":"141519867","full_name":"dave/forky","owner":"dave","description":"A tool to automate forking and modifying codebases","archived":false,"fork":false,"pushed_at":"2019-12-16T09:42:53.000Z","size":62,"stargazers_count":8,"open_issues_count":5,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-25T06:23:51.811Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dave.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-19T03:29:21.000Z","updated_at":"2024-04-18T17:12:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"e7152efb-ceeb-479d-be32-311e5cfa2a05","html_url":"https://github.com/dave/forky","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dave%2Fforky","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dave%2Fforky/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dave%2Fforky/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dave%2Fforky/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dave","download_url":"https://codeload.github.com/dave/forky/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248363521,"owners_count":21091375,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-13T14:35:23.863Z","updated_at":"2025-04-11T08:57:22.581Z","avatar_url":"https://github.com/dave.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"I'll give you a little update on my project to turn the Go compiler into a library... I've made a lot of progress but it still seems like an impossible task to get it working. Here's some of the details as of today:\n\n* https://github.com/dave/forky is a library assisting making bulk changes to any large codebase (at some point I'll tidy it up and release as a generic tool)  \n* https://github.com/dave/forky/tree/master/forkgo is the script that uses forky to modify and make changes to the go compiler codebase\n* https://github.com/dave/golib is the output it produces right now (doesn't compile yet)\n\nIt reads from `$GOPATH/src/go.googlesource.com/go` (I'll probably change this later because having a copy of the whole stdlib in my gopath is playing havoc with my editor code completion). It performs the mutations listed [here](https://github.com/dave/forky/blob/ex1/forkgo/main.go#L39), then saves the output at `$GOPATH/src/dave/golib`.\n\nFirst [here](https://github.com/dave/forky/blob/ex1/forkgo/main.go#L40-L64) it deletes all the code that we don't need... I'll probably make this a bit more intelligent at some point so you just have to list so many items. \n\nNext [here](https://github.com/dave/forky/blob/ex1/forkgo/main.go#L65-L73) is changes all references to the package paths we're forking - this works great and operates on all string literals in the codebase - not just import statements. \n\nNext [here](https://github.com/dave/forky/blob/ex1/forkgo/main.go#L74-L91) we disable a bunch of tests that don't work (for various reasons). \n\nNext [here](https://github.com/dave/forky/blob/ex1/forkgo/main.go#L92-L103) there's a little kludge to delete a node that is relying on a go1.11 feature... I think I can remove this kludge when 1.11 drops.\n\nIf you stop at this point and save the codebase, then all the tests pass! But we really haven't done that much. Next [here](https://github.com/dave/forky/blob/ex1/forkgo/main.go#L107-L112) is the `Libify` step which is where most of the juicy stuff happens.\n\nLibify does a bunch of things. The most obvious is that it collects all the package level vars and adds them to a `PackageSession` struct. So [this]( https://github.com/dave/golib/blob/before/src/cmd/compile/internal/x86/ssa.go#L790-L805) becomes [this](https://github.com/dave/golib/blob/after/src/cmd/compile/internal/x86/package-session.go#L20-L23) and [this](https://github.com/dave/golib/blob/after/src/cmd/compile/internal/x86/package-session.go#L38-L53).\n\nNext it scans the bodies of all functions and methods, and works out which need access to the `PackageSession`. Any function that needs access gets a receiver added and becomes a method of the `PackageSession` type, so [this](https://github.com/dave/golib/blob/before/src/cmd/compile/internal/gc/dcl.go#L20) becomes [this](https://github.com/dave/golib/blob/after/src/cmd/compile/internal/gc/dcl.go#L12). Any reference to one of these functions (or vars) gets converted into a selector using the local `psess` variable, like [this](https://github.com/dave/golib/blob/after/src/cmd/compile/internal/gc/alg.go#L286-L287).\n\nAny method of another type that needs access to `PackageSession` has it added as a parameter, like [this](https://github.com/dave/golib/blob/after/src/cmd/compile/internal/gc/bimport.go#L202). This needs a re-think, because changing the signature of methods means we stop satisfying interfaces (more about this later). \n\nCalling a public function or accessing a public variable in another package is accomplished by keeping the `PackageSession` for all imported packages in the local `PackageSession`, like [this](https://github.com/dave/golib/blob/after/src/cmd/compile/internal/gc/package-session.go#L17-L26). Any time they are accessed, the are wired up like [here](https://github.com/dave/golib/blob/after/src/cmd/internal/obj/x86/asm6.go#L1947) and [here](https://github.com/dave/golib/blob/after/src/cmd/compile/main.go#L15).\n\nThere's plenty more work needed before this will even compile. As I mentioned, we can't rely on injecting the `PackageSession` into methods because we break interfaces. See [this issue](https://github.com/dave/forky/issues/2) for more details.\n\nOne big optimization that I'm currently missing... Most of these package-level variables are never modified after initialisation. If we're sure they're never modified after initialisation, they can stay as package-level and don't need to be stored in the PackageSession. This is something that could possible be detected using the ssa/pointer analysis packages... Not something I've used before so would love some help. I posted a stackoverflow question about this yesterday [here](https://stackoverflow.com/questions/51393995/go-static-analysis-find-read-only-package-level-vars). If you have any input, discuss in [this issue](https://github.com/dave/forky/issues/3).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdave%2Fforky","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdave%2Fforky","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdave%2Fforky/lists"}