An intent-first language that closes complex behavior into executable units and derives the rest of the structure from purpose.
한국어 · Intent-First Design · Syntax Reference · Grammar · Naming Convention · All Documentation
Current Status: Executable experimental alpha, currently in a late-stage alpha / beta-closure sprint. The remaining beta work is not about widening the language surface; it is about freezing a narrower stable subset and aligning
syntax -> semantic -> runtime -> C -> LLVM -> diagnostics -> regression -> docson that subset. Stable subset being frozen for beta: generics (exact/ability/multi-boundplus implemented default type argument actual resolution),own/refanchored slot-handle boundaries with generalized provenance/escape diagnostics, collections (List<T>,Set<T>,HashMap<String, T>,HashMap<Int, T>,HashMap<Long, T>,HashMap<Bool, T>), and runtime observability (last / history / active / recent). Explicit reject / beta-out-of-scope: unsupported map key kinds, broader generic generalization, richer multi-instance observability queries, the full quantum resource model, and any ownership combination that still escapes the current semantic contract.QubitSlot/ClaimQubit/Measure/Entangleremain a partialv2 / experimentalsurface.
Pergyra documents every major surface with one of these labels:
stable subset- implemented end-to-end enough to be part of the beta contract
explicit reject- parser may accept nearby syntax, but unsupported semantic combinations must fail explicitly
beta-out-of-scope- a real future direction, but not promised as part of beta closure
Current classification snapshot:
- language identity / core
- stable beta core:
intent,world,zone,subject,relation,effect,projection,authority,handoff, runtime observability, anchored ownership boundaries, the generic contract system, module visibility/export contracts, andparallel - generic contracts are core, not a compatibility feature: exact generics, ability bounds, multi-bounds, implemented default type argument resolution, and supported module/export consumers define the domain contract language
parallelis the core execution primitive; it is separate fromintent, which remains the orchestration contract core
- stable beta core:
- foundation layer
- stable subset: primitive values,
func,let, control flow, basic callable values,Option/Result, and the collection implementations needed by the core contract language - purpose: make the core executable without becoming the language identity
- stable subset: primitive values,
- execution family / compatibility surface
spawn,async,await,select,channel, cancellation, coroutine/fiber machinery, OOP-style class convenience, and FP combinator libraries are support/style surfaces unless explicitly promoted- fiber / coroutine support is runtime machinery for suspension and scheduling; it is not the same layer as the
parallelexecution primitive - beta support may smoke-test these surfaces, but beta identity and blocker status are anchored on
pgy.core + pgy.foundation;pgy.executionkeeps theparallelfamily explicit without promoting fiber/coroutine to core identity - source of truth: docs/99_language_module_taxonomy.md, docs/language_module_manifest.json, and docs/language_module_cases.json
- generics
- stable subset: exact/ability/multi-bound baseline plus implemented default type argument resolution on supported declaration/call/module-consumer paths
- beta-out-of-scope: broader generic generalization, higher-kinded types, Functor /
fmap-style abstraction (soft-no — see docs/04_generic_design.md)
- own/ref
- stable subset: anchored slot-handle boundaries plus generalized provenance/escape diagnostics on the currently-closed consumer paths
- explicit reject: any general own/ref combination that still falls outside the current semantic contract
- beta-out-of-scope: full universal ownership system
- collections
- stable subset:
List<T>,Set<T>,HashMap<String, T>,HashMap<Int, T>,HashMap<Long, T>,HashMap<Bool, T> - explicit reject: unsupported map key kinds
- beta-out-of-scope: arbitrary key-universal collection contracts
- stable subset:
- runtime observability
- stable subset:
last / history / active / recent - beta-out-of-scope: richer multi-instance timeline and deeper provenance query surface
- stable subset:
This policy exists to prevent partial surfaces from being described as complete.
Pergyra is a compiled language with C and LLVM backends. It distinguishes who acts, where they act, and what qualifies them at the language level.
.pgy → Lexer → Parser → Semantic Typed AST → HIR → DIR → RIR → MIR
├→ LLVM Backend → Binary
└→ C Backend → GCC → Binary
HIRnormalizes language structure and pass-friendly program shapeDIRlocks domain contracts such as role/ability, zone/world, intent-step relationsRIRlocks slot/resource/projection/authority/lifecycle semanticsMIRlocks CFG/SSA/cleanup/resource-flow before backend emission- Backends consume
MIR, notRIR
Pergyra is intent-first in teaching order, even though subject remains the core host in lowering/runtime terms.
Use this reading order for docs, tutorials, and canonical examples:
teaching / reading order: intent -> world -> zone -> subject
host / lowering order: subject-core
Rules:
- read the
intentfirst: what contract is being executed - then read the
worldandzone: where the contract is allowed to run - only then read the
subject: who carries the host state and actions
This distinction is deliberate:
- compile-order and host semantics are not the same as teaching-order
- if examples start from
subject, readers mislearn Pergyra as a subject-first authoring language - canonical docs therefore explain the system from
intentoutward, then show the supporting declarations
# Build
make all
# Run
./bin/pgy examples/hello.pgy --run -v
# Inspect IR layers
./bin/pgy examples/hello.pgy --hir
./bin/pgy examples/hello.pgy --dir
./bin/pgy examples/hello.pgy --rir
./bin/pgy examples/hello.pgy --mir
# LLVM backend (optional)
make LLVM_ENABLED=1 all
./bin/pgy examples/hello.pgy --emit-llvm -o hello.llRequires GCC (C11) and GNU Make. LLVM 14+ optional.
Recent regression entrypoints:
make test-transpile
make test-abi
make llvm-test-backend-compare
make example-test-smoke
make ir-pipeline-test-smoke
make fmt-test-smokePropagation parity is currently locked through world_fixpoint_abi, projection_chain_abi, zone_frontier_abi, intent_authority_snapshot_abi, handoff_projection_frontier_abi, handoff_world_state_frontier_abi, handoff_layer_state_frontier_abi, world_embedded_projection_abi, world_embedded_method_projection_abi, world_embedded_branch_projection_abi, world_embedded_action_frontier_abi, and world_embedded_action_pool_frontier_abi in make test-abi, with zone lifecycle bounded frontier emission and C/LLVM runtime parity checked again in make llvm-test-backend-compare.
Current beta-readiness audit: docs/98_beta_closure_readiness_report.md
Current CI support matrix:
- Linux: C backend + LLVM backend regression coverage
- Windows: C backend regression coverage always; LLVM smoke + backend compare run when the Windows LLVM toolchain is present (
make ci-windowsnow capability-detects LLVM instead of forcingLLVM_ENABLED=0)
Official build/runtime paths:
- Linux
- official path: native Linux toolchain via
make ci-linux
- official path: native Linux toolchain via
- Windows
- official path: GitHub Actions
windows-latest+msys2/setup-msys2with a native MSYS2/MinGW runtime make ci-windowsintentionally rejects plain Linux-hostedgcc- local non-MSYS2 / non-MinGW setups are best-effort only, not the release acceptance line
- official path: GitHub Actions
Failure policy snapshot:
- recoverable failure: intent/authority/boundary/timeout/remote failures should surface as
Bool,Result<T>, or queryable runtime state - contract violation: released slot, invalid token, ownership-boundary misuse, and similar invariant breaks remain hard-fail territory
- internal compiler/runtime bug: immediate internal error or panic, never presented as a normal user-code failure
Hard-fail boundary snapshot:
- released slot / invalid token / ownership invariant misuse
Unwrap(result)onErrUnwrapOption(option)onNone- array / slice bounds violation
- runtime invariant guard failure such as null self / null participant
Recent backend hygiene snapshot:
- LLVM declaration-side helper cleanup now shares implicit-self detection, host decl/method lookup, and pointer-self classification instead of repeating the same logic across declaration/intent/MIR-expression paths
- negative-path memory tests now suppress expected panic/tracing stderr so CI logs reflect regressions instead of deliberate failure probes
- frontend/transpile regression helpers no longer leak ad-hoc debug stderr on successful runs, so
make test-alloutput stays signal-first - semantic builtin diagnostics were tightened to remove Windows-native MinGW format-string drift
- world derived-state chains, zone lifecycle sync, and relation/effect/zone projection chains now use bounded recompute/frontier loops on both C and LLVM, so runtime propagation no longer depends on declaration order for those closed paths
- ABI smoke now includes
projection_chain_abi,zone_frontier_abi,intent_authority_snapshot_abi,handoff_projection_frontier_abi,handoff_world_state_frontier_abi,handoff_layer_state_frontier_abi,world_embedded_projection_abi,world_embedded_method_projection_abi,world_embedded_branch_projection_abi,world_embedded_action_frontier_abi, andworld_embedded_action_pool_frontier_abi, and current direct regression checks aretest-semantic 2146 passed,test-transpile 670 passed,make test-abi, ABI pipeline integration (196 passed),make test-all,make llvm-test-smoke, andmake llvm-test-backend-compare(43/43backend-compare cases)
Stable example guidance:
- smoke-covered examples: see docs/65_stable_example_surface_board.md
- current stable entry examples include:
examples/logistics_intent_probe/examples/resource_scheduler_async_probe/examples/order_analytics/examples/battle_simulator/examples/biome_simulator/
- contract compression canonical pairs:
examples/intent_contract_pair_minimal.pgyexamples/authority_contract_pair_minimal.pgyexamples/transfer_contract_pair_minimal.pgy
- design-sketch examples such as
examples/party_system_demo.pgyandexamples/world_roster_city.pgyare not stable syntax references
Authoring-surface references:
- compression overview: docs/61_surface_compression_examples.md
- pain-point board: docs/58_keyword_authorship_pain_points.md
- compression plan: docs/59_authoring_surface_compression_plan.md
let x: Int = 10;
let name: String = "Alice";
// := shorthand (type inferred)
count := 0;
msg := "hello";
func Add(a: Int, b: Int) -> Int
{
return a + b;
}
func main()
{
let result := Add(3, 4);
PrintInt(result);
}
if hp > 0
{
Print("alive");
}
else
{
Print("dead");
}
while i < 10
{
PrintInt(i);
i = i + 1;
}
Pergyra uses 6 keywords to declare types. Each keyword carries intended distinct semantics.
| Keyword | Role | Memory | Behavior | Implementation |
|---|---|---|---|---|
subject |
Active entity (protagonist) | Reference (ptr self) | action + func | ✅ Full |
class |
Passive thing (tool) | Value | func only | ✅ Full |
struct |
Pure data | Value | None | ✅ Full |
vessel |
Internal state (inside subject) | Value | None | ✅ Semantic + codegen surface |
object |
Internal projection/view contract | Value | func only | ✅ Distinct projection contract |
tobject |
Transfer/export boundary contract | Value | func only | ✅ Distinct transfer contract |
현재 구현 상태:
subject와class는 시맨틱/코드젠 수준에서 분리되어 있다.object와tobject는 선언 키워드와 계약이 모두 distinct하며,object는 local/internal projection contract,tobject는 publish/transfer/export boundary contract로 고정되어 있다.
subject Player
{
let name: String;
let hp: Int;
vessel stats: PlayerStats;
}
class Weapon
{
let name: String;
let damage: Int;
func DamageText(self) -> String
{
return self.name;
}
}
struct Position
{
let x: Int;
let y: Int;
}
vessel PlayerStats
{
let level: Int;
let xp: Int;
}
object PlayerView
{
let name: String;
let hp: Int;
}
tobject PlayerReceipt
{
let name: String;
let hp: Int;
}
Rule of thumb:
- use
objectfor internal projection/read models - use
tobjectfor publish/transfer/export boundaries - observing an embedded zone projection from
worldstill counts asobject-style projection observation, not automatic boundary publication
ability Combatable
{
func CanFight(self) -> Bool;
}
role Combatable for Player
{
func CanFight(self) -> Bool
{
return self.hp > 0;
}
}
subject Player
{
let hp: Int;
action Attack(self, target: Player)
within BattleZone
authorized by self
{
target.hp = target.hp - 10;
}
}
zone BattleZone
{
subject slot attacker: Player;
subject slot defender: Player;
authority attacker;
}
action은subject내부에 선언합니다. zone은 subject slot과 authority만 정의합니다.
world GameServer
{
zone battle: BattleZone;
}
relation Alliance between subject, subject
{
let trust: Int;
}
effect Poison for bearer: subject
{
let damage_per_tick: Int;
let remaining: Int;
}
relation is not a plain struct. It declares shared state between endpoints, and the compiler can validate that zone links satisfy the declared endpoint contract.
Intents declare why a subject moves. They are callable, drive subjects through zone-bound steps, and provide built-in observability.
intent DriveCar(cockpit: CockpitZone, driver: Driver)
{
exclusive;
priority: 3;
step Ignite
{
where: CockpitZone;
using: cockpit;
who: driver;
on: driver.Ignite();
compensate: driver.RollbackIgnite();
pre: true;
post: driver.started;
}
success: true;
failure: false;
}
func Main() -> Void
{
let d = Driver(0, false);
let cockpit = CockpitZone(Driver(99, true));
let ok = DriveCar(cockpit, d); // call intent like a function
Log("ok=" + ToString(ok));
Log("trace:");
Log(IntentLastTrace()); // built-in observability
}
Features:
exclusive/concurrent— conflict policypriority— numeric priority for schedulingon:— event trigger (action call)compensate:— rollback action on failurepre/post/guard/invariant/expect— conditionsIntentLastTrace(),IntentHistoryCount()— runtime observabilityintent:inside a step — sub-intent orchestration
Example:
intent Charge(checkout: CheckoutZone, buyer: Buyer)
{
step verify
{
where: CheckoutZone;
using: checkout;
who: buyer;
expect: true;
}
}
intent Checkout(checkout: CheckoutZone, buyer: Buyer)
{
step pay
{
intent: Charge(checkout, buyer);
expect: true;
}
}
Available without import:
let map: Map<String, Int> = Map();
MapSet(map, "key", 42);
let val: Int = MapGet(map, "key");
let list: List<Int> = List();
ListPush(list, 10);
let item: Int = ListGet(list, 0);
let queue: Queue<Int> = Queue();
QueuePush(queue, 1);
let front: Int = QueuePop(queue);
Set<T>은 현재SetNew,SetAdd,SetHas,SetRemove,SetSize표면이 semantic/C/LLVM 경로에 연결되어 있다.Array<T>는 리터럴[1, 2, 3]과ArrayPush/ArrayPop/ArrayLength함수로 사용한다.
use fsm;
use timer;
use cooldown;
let state := FsmNew();
FsmAddState(state, 0, "idle");
FsmAddState(state, 1, "attack");
FsmTransition(state, 0, 1);
let t := TimerNew(100);
TimerTick(t, 16);
let cd := CooldownNew(60);
CooldownTrigger(cd);
| Target | Style | Example |
|---|---|---|
| Keywords | lowercase | let, func, subject |
| Types / Built-in functions | PascalCase | Player, ToString, MapSet |
| Local variables | camelCase | playerHp, eventCount |
| Constants | UPPER_SNAKE | MAX_HP, TILE_SIZE |
| File names | snake_case | battle_zone.pgy |
Full details: Naming Convention
PergyraLang/
src/
lexer/ # Tokenizer
parser/ # AST generation
semantic/ # Type checking, slot analysis
codegen/ # C / LLVM backends
compiler/ # Compilation driver
runtime/ # Runtime library
examples/ # .pgy examples
docs/ # Design documents
editor/ # VS Code extension
assets/branding/ # Gyri the Nautilus
Not every example has the same contract strength.
compile-smoke covered: the example is exercised by current regression smoke and is the recommended reference surfacedesign sketch: the example may intentionally show future or aspirational syntax and should not be used as a stable reference
Source of truth:
Recommended stable examples to start from:
examples/logistics_intent_probe/— IR/domain pipeline probeexamples/resource_scheduler_async_probe/— async/parallel/resource probeexamples/order_analytics/— larger compile-smoke covered application exampleexamples/subject_object_tobject/— nominal/projection baselineexamples/ownership_forwarding_probe/— currentown/refanchored-slot boundary subset
Design-sketch examples:
examples/party_system_demo.pgyexamples/world_roster_city.pgy
make test-all # All tests
make test-semantic # Semantic analysis
make test-transpile # C backend
make llvm-test-backend-compare # C/LLVM parity
make rebuild # Force clean + full rebuild (use when stale)If a build looks stale ("Nothing to be done" while sources changed), see Build Troubleshooting.
- File extension:
.pgy - TextMate scope:
source.pergyra - VSCode extension: editor/vscode-pergyra/ (marketplace publication pending)
- tree-sitter / Vim / Emacs: not yet provided
Pergyra is not yet registered with github-linguist/linguist,
so GitHub's Language bar currently classifies .pgy as "Other". The
.gitattributes at the repo root forward-declares
linguist-language=Pergyra; it is a no-op until the Linguist entry is merged
and then activates automatically.
The submission checklist (sample selection, TextMate grammar extraction, color candidates, "in use" adoption strategy) is tracked in docs/96_linguist_submission.md.
- Syntax Reference
- Grammar Definition
- Naming Convention
- Compiler Pipeline
- Language Status
- Stable Example Surface Board
- Design Vision
- Linguist Submission Checklist
- 한국어 README
BSD 3-Clause License. See LICENSE.
