Skip to content

Latest commit

 

History

History
116 lines (69 loc) · 6.39 KB

File metadata and controls

116 lines (69 loc) · 6.39 KB

Aver Decisions - decisions/architecture.av

Generated by aver context --decisions-only

selection: mode: auto, budget: 10kb, included_depth: 0, selected: 11/11, truncated: false, used: 6539b

HostLanguage (2024-01-10)

Chosen: "Rust" Rejected: "Python", "Go", "Haskell" Impacts: "Lexer", "Parser", "Interpreter", "Checker"

Rust provides memory safety without a garbage collector, which matters for a language runtime. Its algebraic types (enum, Result, Option) map directly onto Aver concepts and kept the implementation honest. The rich ecosystem (clap, colored, thiserror) let us ship a polished CLI without boilerplate.

Author: Aver core team

SignificantIndentation (2024-01-20)

Chosen: "Indentation" Rejected: "Braces", "BeginEnd", "Keywords" Impacts: "Lexer", "Parser", "AllModules"

Braces are syntactic noise that adds no meaning and forces style debates. Indentation is already how humans read code, so making it structural removes a class of inconsistency. The lexer emits explicit INDENT and DEDENT tokens, keeping the parser context-free and easy to extend.

Author: Aver core team

ResultOverExceptions (2024-01-15)

Chosen: "Result" Rejected: "Exceptions", "Nullable", "Panic" Impacts: "Calculator", "Interpreter", "Checker"

Exceptions hide control flow: a function that throws is indistinguishable from one that does not at the call site. Result types make every error path visible in the signature, which is essential when an AI reads code without running it. The match expression and the ? operator together give ergonomic error handling without sacrificing explicitness.

Author: Aver core team

ColocatedVerify (2024-01-25)

Chosen: "ColocatedVerifyBlocks" Rejected: "SeparateTestFiles", "ExternalTestFramework" Impacts: "Checker", "AllFunctions"

Tests that live in a separate directory rot faster because nobody reads them when changing the function. A verify block immediately below its function is the minimum viable specification: it says what the function must do. Co-location also makes it trivial for an AI to regenerate or extend tests without searching the repository.

Author: Aver core team

DecisionBlocksAsLanguageFeature (2024-02-01)

Chosen: "FirstClassDecisions" Rejected: "MarkdownADR", "Comments", "ExternalWiki" Impacts: "Lexer", "Parser", "Checker", "AIDeveloperExperience"

Architecture Decision Records written in markdown files are invisible to the language tooling and decay silently. Making decisions a first-class parse node means they can be indexed, searched, and rendered by any tool that reads Aver. When an AI resumes work on a codebase, it can run aver context with --decisions-only to reconstruct the design rationale without reading prose.

Author: Aver core team

HybridExecutionModel (2026-03-01)

Chosen: "InterpreterPlusVMPlusTranspiler" Rejected: "InterpreterOnly", "VMOnly", "TranspilerOnly" Impacts: "Interpreter", "VM", "Transpiler", "CLI", "Performance"

Interpreter keeps feedback loop fast for language work (run/check/verify/context). Bytecode VM gives a real runtime path for run/verify/replay without leaving Aver source or its effect model. Transpilation gives a deployment path to native projects without shipping the Aver runtime. These three paths solve different problems, so they should coexist instead of replacing each other.

Author: Aver core team

RecordsAreDataMethodsInModules (2026-02-25)

Chosen: "DataOnlyRecords" Rejected: "RecordMethods", "ImplicitThis" Impacts: "TypeSystem", "RecordModel", "ModuleNamespaces"

Keeping records as data-only keeps the object model small and predictable. Module namespaces already provide a clear place for behavior via Module.fn(record, ...). This avoids introducing two parallel styles too early: methods on records and module functions.

Author: Aver core team

EffectContractsAreTransparentAcrossModules (2026-02-25)

Chosen: "TransparentAcrossModules" Rejected: "OpaqueModuleContracts", "ImplicitModuleCapabilities" Impacts: "ModuleSystem", "Effects", "TypeChecker", "RuntimeGate"

Current Aver model keeps module imports and capability effects as two explicit contracts. depends [X] controls which module code is visible, while ! [Effect] controls which side effects a function may use. Effect requirements propagate through cross-module calls, so callers must declare the effects required by imported functions.

Author: Aver core team

ConstructorContract (2026-02-26)

Chosen: "UpperCamelCalleeContract" Rejected: "TypeAscriptionBased", "KeywordConstructors", "UniformParens" Impacts: "Parser", "Interpreter", "TypeChecker", "AllModules"

Constructors need a single, unambiguous parsing rule that does not conflict with function calls or type annotations. UpperCamel callee distinguishes constructors from functions at parse time with one token of lookahead. Records use named args (=), variants use positional args. Zero-arg constructors are bare singletons without parens. This removes the need for TypeAscription and all cross-cutting heuristics in the parser.

Author: Aver core team

FunctionBodiesUseIndentationOnly (2026-03-06)

Chosen: "IndentedBodiesOnly" Rejected: "EqShorthand", "EqOnlyForPassthroughs", "DualBodyForms" Impacts: "Parser", "REPL", "Formatter", "Docs", "Examples", "AllFunctions"

Aver block bodies already return their last expression, so = expr duplicated an existing body model without adding semantics. Using syntax to hint 'this is probably a trivial wrapper' blurred the boundary between surface syntax and checker heuristics. One body form is easier for humans to scan, easier for AI to emit consistently, and cheaper to maintain across parser, REPL, formatter, docs, and tests.

Author: Aver core team

ListBranchingStaysInMatch (2026-03-06)

Chosen: "MatchOwnsListBranching" Rejected: "FunctionClauses", "ListSpecificFunctionSyntax", "ErlangStyleHeads" Impacts: "Parser", "PatternMatching", "TypeChecker", "Docs", "AllListFunctions"

List cases are pattern matching, not a separate kind of function definition. Pulling list patterns into function clauses would create a second branching notation next to match, weakening one of Aver's core simplifications. Keeping list branching inside match preserves one place for exhaustiveness, one place for pattern syntax, and one mental model for recursive case splits.

Author: Aver core team