AI News HubLIVE
サイト内リライト5 分で読了

翻訳待ち:DripSharp: Building a Java-to-C# source converter with AI

AI サービスが一時的に利用できないため、復旧後に翻訳を補完します。ソース概要:DripSharp: Building a Java-to-C# source converter with AI - Isak Sky's blog A few months ago, Jarred Sumner ported Bun from Zig to Rust with AI, largely processing one file a time. While it was a cool thing to try, and…

ソースHacker News AI著者: i_s

AI サービスが一時的に利用できないため、復旧後に翻訳を補完します。

DripSharp: Building a Java-to-C# source converter with AI - Isak Sky's blog A few months ago, Jarred Sumner ported Bun from Zig to Rust with AI, largely processing one file a time. While it was a cool thing to try, and I’m sure there are many reasons why this made sense for him to do it this way, it didn’t strike me as a great general way to tackle this kind of problem. I am definitely for using AI where possible, but my instinct was that a better way to do this is to just create a program that walks the syntax tree of the source and applies a bunch of rules to transform it node by node. A few reasons why this is better: You get not only the converted code, but also a reusable converter you can use again later for other projects, without an LLM having to be involved. Each transformation rule gets more and more battle-tested. If a rule has transformed 5,000 string operation call sites across multiple projects with tests passing, we can trust it more than a single call site vibe-transformation. You can add optimization / beautification layers later, and run it again and get better outputs almost for free. In general, determinism and verifiability are stronger. There is less chance of a costly AI hallucination, or a particular model having a blind spot. Not quite as stark as the difference between asking AI to manually sum a thousand numbers versus having it write code to do that, but along those lines. Lower token costs. More on this below. I decided to let AI (ChatGPT 5.5 and later 5.6) have a go at this. For my day job, a lot of my work is in the .NET ecosystem, and we saw that some problems are better solved in the JVM open source ecosystem. I went for a Java to C# code converter, using Clojure as the implementation language, since that is the JVM language I use the most. To get started, I set up the main dependencies needed (e.g., Spoon for Java parsing), and wrote documentation for the project goals and architecture with AI assistance. For issue tracking I used beads_rust. At first, I tried a more elaborate workflow. It went like this: Select a Java project. Create a JVM feature inventory (e.g., Java switch, myMap.put(...), etc.) list of the project, and put it in a database (Datomic). Implement/fix handlers for every missing feature. Try converting the project. If it fails, throw the incomplete result away, and create beads for the bugs, then go back to 3. If it succeeds, go back to 1. This ended up not working, and I had to throw away more than 1,000 commits. The agent went with a regex/string conversion engine, and iteratively narrowed the project goals down to almost nothing and declared victory. A large part of why that failed may be that I tried Codex’s /goal mode for this, which at least in my case seemed to keep doubling down on poor decisions, and never “taking a deep breath” and reconsidering whether the direction it was taking was working out. After throwing that out, I did a few sessions interactively on extra-high reasoning to get it started further in the right direction. ChatGPT 5.6 also dropped around this time, which appeared to help power through the initial logic-heavy work of handling each Java statement/expression type. The workflow that ended up working was a loop orchestrated by a small Babashka script: Are there any tasks ready in beads? If so, have the agent do that task. No tasks ready? If so, examine the documentation (architecture and project goals), and plan (with extra-high reasoning) the next epic bead with subtasks. If the project is done, signal that. The script harness will stop the loop. Towards the end, I switched to doing the planning interactively to make sure it wasn’t wasting time on things that did not matter. After about two months of cranking on this with Codex, mostly unattended, it can now convert multiple non-trivial projects (PDFBox, Pkl, JSqlParser) and run tests successfully. I think PDFBox is especially valuable. At work, we cobbled together 3 open-source .NET libraries to approximate the feature set we needed, and we were still missing some parts available in PDFBox, like working with PDF forms. In the ported version, PdfCarton, all 232 upstream test files for the modules I targeted have been ported, and my latest run had all 2,243 runnable tests passing. The remaining 8 were skipped for the same reasons as upstream. Not all of the projects worked out that cleanly yet. For example, while the core of Pkl is written in Java, it had tests written in Kotlin, which this project cannot (yet?) handle. For now, the mechanically ported coverage is incomplete, but there are extensive LLM-authored tests, leveraging the existing .pkl test files as much as possible. All in all, it came out to about 110 KLOC of Clojure, and used up most of my budget for a personal OpenAI 20x Pro plan ($200/mo) for two months, so $400. Even if you multiply it by 10 for API pricing, that is still quite a bit cheaper than the $165,000 needed for the Bun port. To be fair to the Bun port, I was not also fixing bugs, and this strategy can’t be parallelized as much. If I had given this my full attention it probably could have been done much faster and with even fewer tokens. For people in smaller software ecosystems without unlimited token budgets, I think this is a promising direction. The converter lives on GitHub here: https://github.com/dripsharp/dripsharp The converted projects live in separate repos under the DripSharp organization: https://github.com/dripsharp/pdfcarton (PDFBox) https://github.com/dripsharp/brine (Pkl) https://github.com/dripsharp/sqltrellis (JSqlParser) Here is an example of one method converted from Java to C#: As you can see, it is a pretty conservative translation, with Java compatibility function calls in some places. There are more compatibility wrappers than I expected, but the cases I’ve examined actually have good reasons, like different behavior when it comes to null, or slightly different behavior. For example, Java’s Map.put returns the old value, but the closest C# method does not return anything. In some cases, it is a little too conservative, like adding global:: everywhere, but I’d rather solve that later with a Roslyn-based (the C# compiler/parser library) beautification layer. I’ll also fess up and note that I cheated a little and formatted the C# code above, which is not yet actually done for the outputs, but easily done with CSharpier or similar tools. If you plan on trying them out, keep in mind it is still early days, and there may be more work needed to get them production-ready. A few questions people might have: Q: Will they be released on NuGet? A: Yes, PdfCarton is already on NuGet as an alpha package. The rest are coming soon. Q: Why not just use IKVM? A: IKVM seems like a great project, but is limited to Java 8, which was released more than 12 years ago. Some interesting projects, like Pkl, have moved to higher Java versions. IKVM also works on bytecode, which isn’t good for taking advantage of .NET’s strengths like real generics, or creating idiomatic APIs. IKVM also discourages publishing ported packages on NuGet, which isn’t great for adoption. Q: What’s with the name? A: First of all, naming is hard, and a lot of the great names are already taken. That said, there is some logic in the name: Another word for Java is coffee. A way to prepare coffee is drip. What we want to emit here is C-Sharp. Q: Will you manually maintain each project? A: No, I don’t have the bandwidth. But I will maintain DripSharp, and try to ensure it is able to port at least stable versions of the source projects - bug for bug. Q: What about JVM library X? A: Create an issue on the DripSharp repo and make a case for it, or just try converting it yourself. For my part, I want to limit this to high-value projects that do not already have a best-in-class offering on the .NET side. Q: Will this work on any Java library without LLM help? A: No. The JVM and .NET standard libraries have differences, so if a project uses a part of the Java standard library that is not available in .NET, alternatives have to be found or created. That said, as more projects are added and mapped, the chances of that being possible for pure Java projects increase.