# Code Interoperability Guide
This guide explains how to use Nasty's bidirectional conversion between natural language and code.
## Overview
Nasty provides two-way interoperability:
- **NL → Code**: Convert natural language descriptions to executable code
- **Code → NL**: Generate natural language explanations from code
Currently supported: English ↔ Elixir
## Natural Language to Code
### Basic Usage
```elixir
# Simple operations
Nasty.to_code("Sort the list",
source_language: :en,
target_language: :elixir)
# => {:ok, "Enum.sort(list)"}
# Filtering
Nasty.to_code("Filter users where age is greater than 18",
source_language: :en,
target_language: :elixir)
# => {:ok, "Enum.filter(users, fn item -> item > 18 end)"}
# Mapping
Nasty.to_code("Map numbers to double each",
source_language: :en,
target_language: :elixir)
# => {:ok, "Enum.map(numbers, fn item -> item * 2 end)"}
```
### Supported Patterns
#### List Operations
**Sorting**:
```elixir
"Sort the list" → "Enum.sort(list)"
"Sort numbers" → "Enum.sort(numbers)"
```
**Filtering**:
```elixir
"Filter X where Y > Z" → "Enum.filter(x, fn item -> item > z end)"
"Filter X where Y < Z" → "Enum.filter(x, fn item -> item < z end)"
"Filter X where Y == Z" → "Enum.filter(x, fn item -> item == z end)"
```
**Multiple constraints** (AND logic):
```elixir
"Filter users where age > 18 and score > 50"
→ "Enum.filter(users, fn item -> item > 18 and item > 50 end)"
```
**Mapping**:
```elixir
"Map X" → "Enum.map(x, fn item -> item end)"
"Map X to uppercase" → "Enum.map(x, fn item -> String.upcase(item) end)"
```
**Reducing**:
```elixir
"Sum numbers" → "Enum.sum(numbers)"
"Count items" → "Enum.count(items)"
```
#### Arithmetic Operations
```elixir
"Add X and Y" → "x + y"
"X plus Y" → "x + y"
"Subtract Y from X" → "x - y"
"Multiply X by Y" → "x * y"
"Divide X by Y" → "x / y"
```
#### Assignments
```elixir
"X is 5" → "x = 5"
"Set X to Y" → "x = y"
"Let result equal sum" → "result = sum"
```
#### Conditionals
```elixir
"If X then Y" → "if x, do: y"
"If X > 5 then ok" → "if x > 5, do: :ok"
```
### Pipeline Architecture
The NL → Code pipeline:
```mermaid
flowchart TD
A[Natural Language Text]
B["Parse to AST (Nasty.parse)"]
C["Intent Recognition (Nasty.Interop.IntentRecognizer)"]
C1["- Analyze sentence structure<br/>- Extract action (sort, filter, map, etc.)<br/>- Identify target (list, users, etc.)<br/>- Extract arguments<br/>- Identify constraints"]
D["Intent AST (%Nasty.AST.Intent{})"]
E["Code Generation (Nasty.Interop.CodeGen.Elixir)"]
E1["- Match intent pattern<br/>- Build Elixir AST using quote<br/>- Generate function calls<br/>- Handle constraints"]
F["Validation (Code.string_to_quoted)"]
G[Elixir Code String]
A --> B
B --> C
C -.-> C1
C --> D
D --> E
E -.-> E1
E --> F
F --> G
```
### Intent Structure
Intents are intermediate representations:
```elixir
%Nasty.AST.Intent{
type: :action, # :action, :query, :definition, :conditional
action: "filter", # Action verb
target: "users", # Target variable/collection
arguments: [], # Additional arguments
constraints: [ # Filtering/conditional constraints
{:comparison, :greater_than, 18}
],
metadata: %{}
}
```
Intent types:
- `:action` - Perform operation (sort, filter, map)
- `:query` - Ask question (is X equal to Y?)
- `:definition` - Define/assign (X is Y)
- `:conditional` - Conditional logic (if X then Y)
### Advanced Examples
**Complex filtering**:
```elixir
# Multiple AND constraints
Nasty.to_code(
"Filter employees where salary greater than 50000 and age less than 40",
source_language: :en,
target_language: :elixir
)
# => "Enum.filter(employees, fn item -> item > 50000 and item < 40 end)"
```
**Nested operations** (future):
```elixir
"Filter users then sort by age"
→ "users |> Enum.filter(...) |> Enum.sort_by(&(&1.age))"
```
## Code to Natural Language
### Basic Usage
```elixir
# Simple function calls
Nasty.explain_code("Enum.sort(list)",
source_language: :elixir,
target_language: :en)
# => {:ok, "Sort list"}
# Pipelines
Nasty.explain_code("list |> Enum.map(&(&1 * 2)) |> Enum.sum()",
source_language: :elixir,
target_language: :en)
# => {:ok, "Map list to double each element, then sum the results"}
# Assignments
Nasty.explain_code("x = 5",
source_language: :elixir,
target_language: :en)
# => {:ok, "X is 5"}
```
### Supported Patterns
#### Enum Operations
```elixir
"Enum.sort(x)" → "Sort X"
"Enum.filter(x, fn i -> i > 5 end)" → "Filter X where item is greater than 5"
"Enum.map(x, fn i -> i * 2 end)" → "Map X to double each element"
"Enum.sum(x)" → "Sum X"
"Enum.count(x)" → "Count X"
"Enum.find(x, fn i -> i == 5 end)" → "Find item in X where item equals 5"
```
#### Pipelines
```elixir
"a |> b" → "A, then B"
"list |> Enum.sort() |> Enum.reverse()" → "List, then sort, then reverse"
```
#### Arithmetic
```elixir
"x + y" → "X plus Y"
"x - y" → "X minus Y"
"x * y" → "X times Y"
"x / y" → "X divided by Y"
```
#### Assignments
```elixir
"x = 5" → "X is 5"
"result = x + y" → "Result equals X plus Y"
```
#### Conditionals
```elixir
"if x, do: y" → "If X, return Y"
"if x > 5, do: :ok, else: :error" → "If X is greater than 5, return ok, otherwise error"
```
### Pipeline Architecture
The Code → NL pipeline:
```mermaid
flowchart TD
A[Elixir Code String]
B["Parse to Elixir AST (Code.string_to_quoted)"]
C["Traverse AST (Nasty.Interop.CodeGen.Explain)"]
C1["- Match AST patterns<br/>- Recognize Enum calls<br/>- Identify operators<br/>- Handle pipelines<br/>- Extract variables"]
D[Natural Language Fragments]
E[Combine & Format]
F[Natural Language Text]
A --> B
B --> C
C -.-> C1
C --> D
D --> E
E --> F
```
### Explanation Styles
Two styles supported via `:style` option:
**Concise** (default):
```elixir
Nasty.explain_code("Enum.sort(list)", style: :concise)
# => "Sort list"
```
**Verbose**:
```elixir
Nasty.explain_code("Enum.sort(list)", style: :verbose)
# => "Sort the list in ascending order"
```
## Use Cases
### 1. Code Documentation
Generate documentation from code:
```elixir
defmodule MyModule do
def process(data) do
data
|> Enum.filter(&(&1.active))
|> Enum.sort_by(&(&1.priority))
|> Enum.map(&transform/1)
end
end
# Generate doc
{:ok, explanation} = Nasty.explain_code(
get_function_body(:process),
source_language: :elixir,
target_language: :en
)
# => "Filter data where active, then sort by priority, then map to transform"
```
### 2. Natural Language Queries
Allow users to query data using natural language:
```elixir
defmodule DataQuery do
def query(collection, nl_query) do
case Nasty.to_code(nl_query,
source_language: :en,
target_language: :elixir) do
{:ok, code_string} ->
# Safely evaluate with collection
safe_eval(code_string, collection: collection)
{:error, reason} ->
{:error, reason}
end
end
end
# Usage
DataQuery.query(users, "Filter users where age greater than 25")
```
### 3. Interactive Learning
Explain code to learners:
```elixir
defmodule CodeTutor do
def explain_to_learner(code) do
{:ok, explanation} = Nasty.explain_code(code,
source_language: :elixir,
target_language: :en,
style: :verbose
)
IO.puts("This code: #{explanation}")
end
end
```
### 4. Code Generation from Specs
Generate code from natural language specifications:
```elixir
specs = [
"Filter products where price less than 100",
"Sort by name",
"Map to uppercase"
]
pipeline = Enum.map_join(specs, " |> ", fn spec ->
{:ok, code} = Nasty.to_code(spec,
source_language: :en,
target_language: :elixir)
code
end)
# => "Enum.filter(products, fn item -> item < 100 end) |>
# Enum.sort_by(&(&1.name)) |>
# Enum.map(fn item -> String.upcase(item) end)"
```
## Limitations
### Current Limitations
1. **Single language pair**: Only EN ↔ Elixir supported
2. **Limited patterns**: Not all Elixir constructs supported
3. **Simple constraints**: Complex boolean logic not fully supported
4. **No type inference**: Cannot infer types from context
5. **Limited variable scope**: Doesn't track variable definitions
6. **No side effects**: Cannot handle IO, state mutations, etc.
### Future Enhancements
1. **More language pairs**: EN ↔ JavaScript, EN ↔ Python
2. **Advanced patterns**: Pattern matching, guards, comprehensions
3. **Context awareness**: Track variable types and scope
4. **Bidirectional pipelines**: Full round-trip NL ↔ Code ↔ NL
5. **Code understanding**: Infer intent from existing code
6. **Multi-statement programs**: Handle complete modules/functions
## API Reference
### `Nasty.to_code/2`
Convert natural language to code.
```elixir
@spec to_code(String.t(), keyword()) :: {:ok, String.t()} | {:error, term()}
```
**Options**:
- `:source_language` (required) - Natural language (`:en`)
- `:target_language` (required) - Programming language (`:elixir`)
**Returns**:
- `{:ok, code_string}` - Generated code
- `{:error, reason}` - Error
### `Nasty.explain_code/2`
Convert code to natural language.
```elixir
@spec explain_code(String.t() | Macro.t(), keyword()) :: {:ok, String.t()} | {:error, term()}
```
**Options**:
- `:source_language` (required) - Programming language (`:elixir`)
- `:target_language` (required) - Natural language (`:en`)
- `:style` - Explanation style (`:concise` or `:verbose`)
**Returns**:
- `{:ok, explanation}` - Natural language explanation
- `{:error, reason}` - Error
## Implementation Details
### Intent Recognition
Located in `lib/interop/intent_recognizer.ex`:
```elixir
defmodule Nasty.Interop.IntentRecognizer do
@doc """
Recognizes intent from parsed NL AST.
"""
def recognize(%Document{} = doc) do
# Extract clauses, identify action verbs
# Build Intent struct
end
end
```
### Code Generation
Located in `lib/interop/code_gen/elixir.ex`:
```elixir
defmodule Nasty.Interop.CodeGen.Elixir do
@doc """
Generates Elixir AST from Intent.
"""
def generate(%Intent{} = intent) do
# Pattern match on intent type
# Use quote to build Elixir AST
# Validate and return
end
end
```
### Code Explanation
Located in `lib/interop/code_gen/explain.ex`:
```elixir
defmodule Nasty.Interop.CodeGen.Explain do
@doc """
Explains Elixir code in natural language.
"""
def explain_code(code_string) do
# Parse to Elixir AST
# Traverse and explain patterns
# Generate NL text
end
end
```
## See Also
- [API Documentation](API.md)
- [Architecture](ARCHITECTURE.md)
- [User Guide](USER_GUIDE.md)