Skip to main content

dingo-developer

Generates and reviews Dingo meta-language code with Go boundary handling. Use when the user mentions Dingo, .dingo files, or Dingo-to-Go transpilation.

Quellinformationen

Repository
MadAppGang/magus
Letzte Quellaktivität
26. September 2026 um 14:36
Erkannte Sprache von SKILL.md
Englisch
Sterne
11
Forks
4

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
2 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
dingo-developer
description
Generates and reviews Dingo meta-language code with Go boundary handling. Use when the user mentions Dingo, .dingo files, or Dingo-to-Go transpilation.
# Dingo Developer ## Overview Dingo is a meta-language for Go that transpiles `.dingo` files to idiomatic `.go` files. It provides modern language features — Result/Option types, sum types (enums), pattern matching, error propagation, safe navigation, null coalescing, lambdas, generics, and tuples — while maintaining 100% Go ecosystem compatibility. **Repository:** https://github.com/MadAppGang/dingo **Key philosophy:** Dingo is syntax sugar over Go, not a new type system. The transpiled Go code is clean and idiomatic. All Go syntax remains valid in `.dingo` files. **When to use Dingo:** - You want concise error handling with the `?` operator - You need sum types (enums) and pattern matching - You prefer functional patterns with lambdas - You want `Option[T]` and `Result[T, E]` types - You need safe navigation (`?.`) and null coalescing (`??`) **CLI commands:** ```bash dingo build ./cmd/app # Transpile + compile; explicit packages only, not ./... dingo run main.dingo # Transpile + run directly dingo go ./... # Generate .go files only, into build/ (no go.mod there) ``` Build directory, checking a project, CI, editor setup and transpile errors: `references/build-and-tooling.md` (relative to this file). --- ## Error Handling ### The `?` Operator — Three Variants **Decision tree — pick the first that applies:** 1. Just propagate the error unchanged → plain `?` 2. Add lightweight string context → `? "message"` 3. Build a custom error type or capture variables → `? |e| expr` 4. Need side effects or multi-statement logic → `guard` (see below) 5. Absence is expected, not an error → use `Option[T]` + `guard` --- #### Variant 1: Plain Propagation ```go // BEFORE (Go) user, err := getUser(id) if err != nil { return nil, err } ``` ```dingo // AFTER (Dingo) user := getUser(id)? ``` --- #### Variant 2: String Context Generates `fmt.Errorf("message: %w", err)`. ```go // BEFORE (Go) config, err := loadConfig(path) if err != nil { return nil, fmt.Errorf("load config: %w", err) } ``` ```dingo // AFTER (Dingo) config := loadConfig(path) ? "load config" ``` --- #### Variant 3: Lambda Transform Captures local variables and builds custom error types. Both Rust-style (`|e|`) and TypeScript-style (`e =>`) are valid. ```go // BEFORE (Go) resp, err := httpClient.Get(url) if err != nil { return nil, &NetworkError{URL: url, Err: err} } ``` ```dingo // AFTER — Rust-style resp := httpClient.Get(url) ? |e| &NetworkError{URL: url, Err: e} // AFTER — TypeScript-style (identical semantics) resp := httpClient.Get(url) ? e => &NetworkError{URL: url, Err: e} ``` --- ### Function Signature Compatibility | Return type | `?` works? | Notes | |---|---|---| | `(T, error)` | YES | Most common | | `(T1, T2, error)` | YES | Extracts last value | | `Result[T, E]` | YES | Unwraps to T | | `error` only (void success) | YES | Propagates error directly | | `(T, bool)` | NO | Use `Option[T]` + guard | | `T` only (no error) | NO | Nothing to propagate | **`?` in void functions is a compile error.** If you need to propagate from a void-returning call, acknowledge explicitly: ```dingo // WRONG — compile error when function returns void validateInput(data)? // CORRECT _ = validateInput(data)? ``` --- ### `guard` Statement `guard` provides early-return logic for `Result[T, E]` and `Option[T]` values. It is the idiomatic way to flatten a "pyramid of doom" into a sequential happy path. **CRITICAL CONSTRAINT:** `guard` ONLY works with `Result[T, E]` or `Option[T]` return types. It does NOT work on plain booleans, integers, or other types. ```dingo // WRONG — guard on boolean generates invalid Go (compile error) guard user.Active else { return "inactive" } // CORRECT — guard on Option[T] guard profile := getProfile(userID) else { return "no profile" } // CORRECT — guard on Result[T, E] guard user := findUser(id) else |err| { return fmt.Errorf("find user: %w", err) } ``` #### Guard Syntax Reference ```dingo // Result: bind error value with |err| guard user := findUser(id) else |err| { return Err(fmt.Errorf("find user: %w", err)) } // Option: no |err| binding (None has no error value) guard theme := getTheme(id) else { return "default" } // Reassignment: use = not := when variable already declared guard user = refreshUser(ctx, user.ID) else |err| { return Err(err) } // Tuple destructuring guard (lat, lng) := getCoords(address) else |err| { return Err(fmt.Errorf("coords: %w", err)) } ``` #### Pyramid of Doom → Flat Guard Chain ```go // BEFORE (Go) — nested error ladder user, err := findUser(id) if err != nil { return "", fmt.Errorf("find user: %w", err) } profile, err := loadProfile(user.ID) if err != nil { return "", fmt.Errorf("load profile: %w", err) } settings, err := loadSettings(profile.ID) if err != nil { return "", fmt.Errorf("load settings: %w", err) } ``` ```dingo // AFTER (Dingo) — flat guard chain guard user := findUser(id) else |e| { return "", fmt.Errorf("find user: %w", e) } guard profile := loadProfile(user.ID) else |e| { return "", fmt.Errorf("load profile: %w", e) } guard settings := loadSettings(profile.ID) else |e| { return "", fmt.Errorf("load settings: %w", e) } ``` --- ### `?` in Goroutines The `?` operator cannot propagate errors from inside goroutines (there is no enclosing function to return to). Use channels or `sync.WaitGroup` + error collection instead. ```dingo // WRONG — ? inside goroutine has no propagation target go func() { result := fetch()? // compile error or logic error }() // CORRECT — explicit error handling inside goroutines errCh := make(chan error, 1) go func() { result, err := fetch() if err != nil { errCh <- err return } process(result) errCh <- nil }() if err := <-errCh; err != nil { return nil, err } ``` --- ## Result & Option Types ### Result[T, E] Use for operations that can fail when callers need to act on the error type. **Constructors:** `Ok[T, E](value)` and `Err[T, E](err)` **Methods (complete list):** | Method | Description | |---|---| | `.IsOk()` | Returns true if Ok variant | | `.IsErr()` | Returns true if Err variant | | `.MustOk()` | Returns value; panics if Err | | `.MustErr()` | Returns error; panics if Ok | | `.OkOr(default)` | Returns value or default if Err | **NOT available:** `.Unwrap()`, `.Map()`, `.FlatMap()`, `.UnwrapErr()` — these do not exist in the dgo package. Do not use them. ```dingo func divide(a, b int) Result[int, string] { if b == 0 { return Err[int, string]("division by zero") } return Ok[int, string](a / b) } result := divide(10, 2) if result.IsOk() { fmt.Println(result.MustOk()) // 5 } // Safe extraction with default value := divide(10, 0).OkOr(0) // 0 ``` #### Result in Service Layer ```dingo func (s *UserService) FindByID(ctx context.Context, id string) Result[User, error] { guard user := s.repo.FindByID(ctx, id) else |err| { if errors.Is(err, sql.ErrNoRows) { return Err[User, error](NotFoundError("user")) } return Err[User, error](InternalError(err)) } return Ok[User, error](user) } ``` --- ### Option[T] Use when absence is expected and normal — not an error condition. **Constructors:** `Some(value)` and `None[T]()` **Methods (complete list):** | Method | Description | |---|---| | `.IsSome()` | Returns true if Some variant | | `.IsNone()` | Returns true if None variant | | `.MustSome()` | Returns value; panics if None | | `.SomeOr(default)` | Returns value or default | | `.SomeOrElse(fn)` | Returns value or calls fn() for default | **NOT available:** `.Unwrap()`, `.Map()`, `.FlatMap()` — these do not exist in the dgo package. Do not use them. ```dingo func findUser(id string) Option[User] { user, err := db.FindByID(id) if err != nil { return None[User]() } return Some(user) } user := findUser("123") if user.IsSome() { fmt.Println(user.MustSome().Name) } // Safe extraction with default name := findUser("123").SomeOr(User{Name: "Anonymous"}).Name // Lazy default (only computed when None) name := findUser("123").SomeOrElse(func() User { return buildDefaultUser() }).Name ``` --- ### Result vs Option — When to Use Which | Situation | Use | |---|---| | Absence is expected and normal ("not found") | `Option[T]` | | Absence needs explanation to the caller | `Result[T, E]` | | Infrastructure/stdlib calls | `(T, error)` + `?` | | Domain API with typed errors | `Result[T, DomainError]` | | "Find" queries on collections | `Option[T]` | | "Create/Update" domain operations | `Result[T, error]` | **Rule:** If absence is the expected outcome (e.g., cache miss, optional config), use `Option[T]`. If absence would surprise the caller and they need to know why, use `Result[T, E]`. Do NOT mix: a function should return either `Result[T, E]` or `(T, error)` — not both. `func f() (Result[User, string], error)` is always wrong. --- ## Enums & Sum Types ### Enum Declaration ```dingo // Simple variants (no data) enum Status { Pending Active Done } // Variants with data enum Event { UserCreated { userID: int, email: string } UserDeleted { userID: int } EmailChanged { userID: int, oldEmail: string, newEmail: string } } // Mixed enum APIResponse { Success { transactionID: string, amount: float64 } NotFound Error { code: int, reason: string } } ``` ### Constructor Naming Constructors are auto-generated as `New{EnumName}{VariantName}(fieldValues...)`. ```dingo // Simple variants (no constructor call needed — use as value) status := Status.Pending // Variants with data — use generated constructor event := NewEventUserCreated(42, "user@example.com") deleted := NewEventUserDeleted(42) resp := NewAPIResponseSuccess("TXN-123", 99.99) notFound := NewAPIResponseNotFound() ``` ### What Enums Generate Each enum declaration generates: - A Go interface with a marker method - One struct per variant containing the variant's fields - Constructor functions `New{Enum}{Variant}(...)` ```go
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen