skills/code-analysis/pseudocode-to-java-code/SKILL.md
Translates pseudocode into idiomatic Java, inferring types, choosing collection classes, and handling exceptions per Java conventions. Use when implementing an algorithm from a paper or spec, when the user hands you pseudocode and wants Java, or when realizing a verified-pseudocode artifact.
npx skillsauth add santosomar/general-secure-coding-agent-skills pseudocode-to-java-codeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Pseudocode is under-specified on purpose. The Java you produce has to commit to everything pseudocode leaves open: types, nullability, error handling, mutability, collection implementations.
| Pseudocode says | Java must decide |
| --------------------- | ------------------------------------------------------------------- |
| let S be a set | HashSet? TreeSet? LinkedHashSet? (Does order matter?) |
| x ← lookup(k) | Returns null on miss? Optional<V>? Throws? |
| list of numbers | int[]? List<Integer>? IntStream? (Boxed vs primitive matters.)|
| error: ... | Checked Exception? RuntimeException? Return sentinel? |
| for each x in S | Enhanced for? Stream? (Mutation during iteration → ConcurrentModificationException.) |
| procedure f(x) | Static method? Instance method? What class does it live on? |
Default choices (absent a reason to deviate):
HashSet/HashMap unless order is mentioned; LinkedHash* if insertion order matters; Tree* if sorted iteration is used.Optional for new code, null if matching an existing API.List<Integer> for flexibility, int[] if the pseudocode indexes and size is fixed.IllegalArgumentException for bad inputs, IllegalStateException for bad state, checked only if the caller can meaningfully recover.Pseudocode variables are used before typed. Infer from usage:
| Usage in pseudocode | Inferred Java type |
| -------------------------- | -------------------------------------------- |
| x ← 0; x ← x + 1 | int (or long if values look big) |
| x ← []; x.append(y) | List<typeof(y)> (ArrayList) |
| x ← {}; x[k] ← v | Map<typeof(k), typeof(v)> |
| x ← ∅; x ← x ∪ {y} | Set<typeof(y)> |
| for i ← 1 to n | int i (1-indexed — watch off-by-one) |
| x ← head(list); rest(list) | Consider Deque or LinkedList |
Pseudocode (Dijkstra, textbook style):
function shortest_paths(G, source):
dist ← map with dist[source] = 0, all others = ∞
visited ← ∅
Q ← priority queue of all vertices, keyed by dist
while Q is not empty:
u ← extract-min(Q)
visited ← visited ∪ {u}
for each neighbor v of u where v ∉ visited:
alt ← dist[u] + weight(u, v)
if alt < dist[v]:
dist[v] ← alt
decrease-key(Q, v, alt)
return dist
Java:
import java.util.*;
public final class Dijkstra {
private Dijkstra() {}
public record Edge(int to, int weight) {}
/**
* Computes shortest distances from {@code source} to all reachable vertices.
* @param adj adjacency list: adj.get(u) is the outgoing edges from u
* @param source starting vertex
* @return map from vertex to shortest distance; unreachable vertices absent
* @throws IllegalArgumentException if source is not in adj
*/
public static Map<Integer, Integer> shortestPaths(
Map<Integer, List<Edge>> adj, int source) {
if (!adj.containsKey(source)) {
throw new IllegalArgumentException("source vertex not in graph");
}
Map<Integer, Integer> dist = new HashMap<>();
dist.put(source, 0);
Set<Integer> visited = new HashSet<>();
// Java's PriorityQueue has no decrease-key. Standard workaround:
// insert duplicates, skip stale entries on poll.
PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[1]));
pq.offer(new int[]{source, 0});
while (!pq.isEmpty()) {
int[] top = pq.poll();
int u = top[0], d = top[1];
if (visited.contains(u)) continue; // stale entry — already settled
visited.add(u);
for (Edge e : adj.getOrDefault(u, List.of())) {
if (visited.contains(e.to())) continue;
int alt = d + e.weight();
Integer cur = dist.get(e.to());
if (cur == null || alt < cur) {
dist.put(e.to(), alt);
pq.offer(new int[]{e.to(), alt}); // "decrease-key" = insert new, ignore old
}
}
}
return dist;
}
}
Decisions made (and why):
∞ → absent from map. dist.get(v) == null means infinity. Avoids Integer.MAX_VALUE overflow when adding weights.decrease-key → Java's PQ doesn't have it. Lazy deletion: insert duplicates, skip visited on poll. O((V+E) log V) — same asymptotic.int[]{vertex, dist} in PQ instead of a record — cheap, no boxing. Comment explains.adj.getOrDefault(u, List.of()) — graph might have vertices with no outgoing edges.containsKey.If the pseudocode came from → verified-pseudocode-extractor, it has // PRE:, // POST:, // INV: annotations. Keep them as Javadoc and comments:
PRE → @throws IllegalArgumentException if ... or @param ... must be ...POST → @return clauseINV → comment at the loop head (don't delete — it's why the loop is correct)Integer.MAX_VALUE for infinity without guarding additions. MAX_VALUE + weight overflows to negative. Use absent-from-map, or Long, or check before adding.ConcurrentModificationException. Use an explicit iterator with .remove(), or iterate over a copy.for i ← 1 to n → for (int i = 0; i < n; i++) and every a[i] stays a[i] (not a[i-1]) — or keep 1-indexed loops and adjust all accesses. Pick one, consistently.## Type decisions
| Pseudocode var | Java type | Why |
| -------------- | --------- | --- |
## Code
<java>
## Deviations from pseudocode
<decrease-key workaround, ∞ encoding, index base — anything where the Java isn't a direct reading>
## Javadoc
<pre/post conditions translated>
development
Extracts human-readable pseudocode from a verified formal artifact (Dafny, Lean, TLA+) while preserving the verified properties as annotations, so the proof-carrying logic can be reimplemented in a production language. Use when porting verified code to an unverified target, when documenting what a formal spec actually does, or when handing a verified algorithm to an implementer.
development
Translates natural-language or pseudocode descriptions of concurrent and distributed systems into TLA+ specifications ready for the TLC model checker. Identifies state variables, actions, type invariants, safety properties, and liveness properties from the description. Use when formalizing a protocol, when the user describes a distributed algorithm to verify, when designing a consensus or locking scheme, or when starting formal verification of a concurrent system.
testing
Reduces a TLA+ model so TLC can actually check it — shrinks constants, adds state constraints, abstracts data, or applies symmetry — when the state space is too large to enumerate. Use when TLC runs out of memory, when checking takes hours, or when a spec works at N=2 and you need confidence at larger scale.
development
TLA+-specific instance of model-guided repair — reads a TLC error trace, identifies the enabling condition that should have been false, strengthens the corresponding action, and maps the fix to source code. Use when TLC reports an invariant violation or deadlock and you have the code-to-TLA+ mapping from extraction.