kex docs Standard Library 0.4.0-alpha kex.run ↗

Kex.AST

module Kex.AST

Parses Kex source code into a structured AST, at run time.

Opt-in: nothing here is in scope until using Kex.AST.

This is the entry point for tools that read Kex source: linters, formatters, documentation generators, code search. The AST includes module definitions, function signatures, type/record definitions, traits, make blocks, and the doc-comments extracted from # lines, which is how the standard library's own documentation is generated.

using Kex.AST

main do
  match Kex.AST.parseFile("src/main.kex") do
    Ok(program) => IO.printLine("${program.items.count} top-level items")
    Error(e)    => IO.printError(e.message)
  end
end

Everything answers a Result, so a source file that does not parse is a value you handle rather than an exception.

record Location

Where in a source file something appeared.

Line and column are 1-based, for reporting to a person; the offsets are 0-based byte positions, for slicing the source.

Fields

file
String
line
Integer
column
Integer
startOffset
Integer
endOffset
Integer

record Program

A parsed source file: its schema version, and its top-level items.

Fields

schemaVersion
Integer
items
[Node]

record ParseError

Why a source file could not be parsed.

Fields

message
String
location
Location?

function parse

Parses Kex source text into a structured AST.

Pass filename when you have one: it is what appears in every Location and in the error message, so diagnostics can point at a real file.

parse(source) : String -> Result<Program, ParseError>
parse(source) : String -> String -> Result<Program, ParseError>
Parameters
source String
the Kex source text
filename String
the name to report locations against; optional

Returns: Result<Program, ParseError> — the parsed program, or why it failed

Examples
Kex.AST.parse("let double(n: Integer) -> Integer = n * 2\n")
# => Ok(Program { schemaVersion: 2, items: [...] })
Kex.AST.parse("let x =").error?   # => true

Counting a file's top-level items

Kex.AST.parse(source, "main.kex").map { |p| p.items.count }

function parseFile

Reads a file and parses it, reporting locations against its path.

A file that cannot be read is an Error like one that cannot be parsed.

parseFile(path) : FS.FilePath -> Result<Program, ParseError>
Parameters
path FS.FilePath
the file to read and parse

Returns: Result<Program, ParseError> — the parsed program, or why it failed

Examples
match Kex.AST.parseFile("src/main.kex") do
  Ok(program) => IO.printLine("${program.items.count} items")
  Error(e)    => IO.printError(e.message)
end

Parsing every source in a directory

FS.Directory.files(dir)
  .or([])
  .filter { |f| FS.Path.extension(f) == ".kex" }
  .map { |f| Kex.AST.parseFile(FS.Path.join(dir, f)) }

function parseType

Parses a type expression on its own, without a surrounding program.

Use it to read a type written in data: a signature in a config file, a type named on a command line. typeRefText renders the result back.

parseType(source) : String -> Result<TypeRef, ParseError>
Parameters
source String
the type expression

Returns: Result<TypeRef, ParseError> — the parsed type, or why it failed

Examples
Kex.AST.parseType("[Integer]").map { |t| Kex.AST.typeRefText(t) }
# => Ok("[Integer]")
Kex.AST.parseType("Map<String, Integer>").map { |t| Kex.AST.typeRefText(t) }
# => Ok("Map<String, Integer>")

function parseExpression

Parses a single expression on its own, without a surrounding program.

This gives you the expression's SHAPE. To evaluate one instead, use Evaluator.runExpression.

parseExpression(source) : String -> Result<Expression, ParseError>
Parameters
source String
the expression text

Returns: Result<Expression, ParseError> — the parsed expression, or why it failed

Examples
Kex.AST.parseExpression("1 ` 2").ok?   # => true
Kex.AST.parseExpression("1 `").ok?     # => false

type TypeRef

A type as it was written in source.

typeRefText renders one back to the source spelling.

Variants

  • NamedType(String, [TypeRef])
  • FunctionType([TypeRef], TypeRef)
  • TupleType([TypeRef])
  • ListType(TypeRef)
  • MapType(TypeRef, TypeRef)
  • UnionType([TypeRef])
  • IntersectionType([TypeRef])
  • RecordType([(String, TypeRef)])
  • NullableType(TypeRef)
  • BlockType(TypeRef)
  • AtomType(String)
  • TypeQuery(String, Expression)
  • TypeVar(String)
  • AnyType
  • NoneType

function typeRefText

Renders a TypeRef back to the way it is written in source.

A list reads as [Integer], a map as {String: Integer}, an optional as String?: the spelling a reader would recognise, not the constructor tree behind it.

typeRefText(NamedType(name, []))
Parameters
typeRef TypeRef
the parsed type

Returns: String — the type, as source

Examples
Kex.AST.parseType("[Integer]").map { |t| Kex.AST.typeRefText(t) }
# => Ok("[Integer]")
Kex.AST.parseType("String?").map { |t| Kex.AST.typeRefText(t) }
# => Ok("String?")

type PatternRef

Structured representation of patterns.

Pattern nodes describe what a declaration or match arm accepts; they do not contain runtime values. A linter can distinguish a wildcard from a binding, for example, without reparsing source text.

Variants

  • BindPattern(String)
  • LiteralPattern(String)
  • ConstructorPattern(String, [PatternRef])
  • TuplePattern([PatternRef])
  • ListPattern([PatternRef], PatternRef?)
  • RecordPattern(String?, [PatternField])
  • RangePattern(PatternRef, PatternRef)
  • ThisPattern(PatternRef)
  • WildcardPattern

record PatternField

One field inside a record or map-shaped pattern.

pattern is None for shorthand such as { name }. stringKey keeps {"name": value} distinct from the atom-key spelling { name: value }.

Fields

name
String
pattern
PatternRef?
stringKey
Bool

function patternRefText

Renders a PatternRef back to the way it is written in source.

patternRefText(BindPattern(name))
Parameters
patternRef PatternRef
the parsed pattern

Returns: String — the pattern, as source

Examples
Kex.AST.patternRefText(WildcardPattern)             # => "_"
Kex.AST.patternRefText(BindPattern("n"))            # => "n"

function patternFieldText

patternFieldText(PatternField { name, pattern, stringKey })

function referenceText

Renders either a type or a pattern back to source.

The one call to reach for when a node may carry either: it dispatches to typeRefText or patternRefText as appropriate.

referenceText(NamedType(name, args))
Parameters
reference TypeRef | PatternRef
the parsed node

Returns: String — the node, as source

Examples
Kex.AST.referenceText(WildcardPattern)   # => "_"
Kex.AST.referenceText(AnyType)           # => "Any"

type Expression

Structured representation of expression AST nodes.

Expressions retain syntax-level distinctions that matter to tools: a method call is not flattened into a generic call, var is distinct from let, and a trailing if remains recognizable. Walk these constructors when writing a linter or code search; use Evaluator when the goal is to execute an expression rather than inspect it.

Variants

  • LitInt(Int)
  • LitFloat(Float)
  • LitChar(Int)
  • LitString(String)
  • InterpolatedString([String], [Expression])
  • LitBool(Bool)
  • LitAtom(String)
  • LitNone
  • Identifier(String)
  • This
  • BinaryOp(Expression, String, Expression)
  • UnaryOp(String, Expression)
  • Call(Expression, [Expression], [NamedArgument], Expression?)
  • TaggedLiteral(String, [String], [Expression])
  • MethodCall(Expression, String, [Expression], [NamedArgument], Expression?, Bool, Bool, TypeRef?)
  • If(Expression, PatternRef?, [Expression], [ElseIf], [Expression]?)
  • Match(Expression, String?, [MatchArm])
  • Receive(String?, [MatchArm], Expression?, Expression?)
  • ListLit([Expression], Expression?)
  • MapLit([MapItem])
  • RecordLit(String, [RecordField])
  • TupleLit([Expression])
  • Block([Expression])
  • Lambda([LambdaParam], [Expression], TypeRef?, RescueInfo?)
  • Let(PatternRef, TypeRef?, Expression)
  • Var(String, TypeRef?, Expression)
  • Assign(String, Expression)
  • Return(Expression)
  • Break
  • Next
  • Spawn([Expression])
  • Try(Expression)
  • Spread(Expression)
  • TrailingIf(Expression, Expression)
  • ThenElse(Expression, Expression, Expression)
  • ShorthandLambda(String, [Expression], Bool)
  • CurryPlaceholder
  • Curry(String, String?, Bool, [[Expression]])
  • Using(String, String?, [String], [String], [Expression])
  • With(String, Expression, [Expression])
  • GeneratedDeclaration(Expression, GeneratedTemplate)
  • ErrorExpression(String)
  • Trying([Expression], RescueInfo)
  • While(Expression, [Expression])
  • Loop([String], [Expression])
  • RangeLit(Expression, Expression)

record NamedArgument

One name: value argument at a call site.

Fields

name
String

record MatchArm

One arm of match, receive, or rescue.

Multiple patterns are the comma-separated alternatives on the left of the arrow. guard is absent when the arm has no when condition.

Fields

patterns
[PatternRef]

record LambdaParam

One lambda parameter and its optional source annotation.

Fields

name
String
type
TypeRef?

record RescueInfo

The structured recovery clauses attached to a function or expression.

Named rescue arms live in arms; a catch-all rescue keeps its optional binding and body separately. inlineReturn represents the compact rescue form rather than inventing a synthetic block.

Fields

arms
[MatchArm]
catchAllName
String?
catchAllBody
[Expression]
inlineReturn
Expression?

record ElseIf

One elif branch, in source order.

Fields

condition
Expression

type MapItem

One entry in a map literal: either a key/value pair or ...spread.

Variants

  • MapEntry(Expression, Expression)
  • MapSpread(Expression)

record RecordField

One explicitly initialized field in a record literal.

Fields

name
String

type GeneratedTemplate

A declaration template whose name (and, for a make block, target) is computed by a compiled do expression.

Tools normally encounter this only while inspecting metaprogramming code. After expansion, generated declarations appear as ordinary Nodes.

Variants

  • GeneratedNode(Node)
  • GeneratedMake(GeneratedMakeInfo)

record GeneratedMakeInfo

The fixed portion of a generated make declaration.

Fields

isFinal
Bool
implements
[TypeRef]
location
Location

record MainInfo

The program entry point, including documentation and recovery clauses.

Fields

doc
String?
params
[ParamInfo]
rescueInfo
RescueInfo?
location
Location

record ParamInfo

One declared function parameter.

name is absent for a destructuring parameter; pattern preserves that destructuring shape. hasDefault records whether an initializer appeared.

Fields

name
String?
pattern
PatternRef?
type
TypeRef?
hasDefault
Bool

record ClauseInfo

One clause of a function, including its patterns and body.

Multi-clause functions place all clauses in one FunctionInfo, preserving source order so tooling can reason about which pattern is tried first.

Fields

params
[ParamInfo]
returnType
TypeRef?
rescueInfo
RescueInfo?
hasParamList
Bool

record FunctionInfo

A named function and all of its pattern-matching clauses.

doc contains the normalized # comment immediately attached to the declaration. Documentation generators can therefore share the same parsed structure as linters instead of scanning comments independently.

Fields

name
String
doc
String?
isFoul
Bool
predicate
Bool
clauses
[ClauseInfo]
location
Location

record AnnotationInfo

A standalone function or method type signature.

implicitThis distinguishes :> methods from module-level : functions without making a tool inspect punctuation in the original source.

Fields

name
String
doc
String?
implicitThis
Bool
location
Location

record VariantInfo

One constructor of an algebraic data type.

Fields

name
String
fields
[TypeRef]

record TypeInfo

A type alias or algebraic data type declaration.

variants is present for an ADT and absent for an alias or abstract type. parents preserves declared bounds and inherited type relationships.

Fields

name
String
doc
String?
typeParams
[String]
parents
[TypeRef]
variants
[VariantInfo]?
location
Location

record FieldInfo

One field declared by a record type.

Fields

name
String
hasDefault
Bool

record RecordInfo

A record declaration with fields in source order.

Fields

name
String
doc
String?
typeParams
[String]
fields
[FieldInfo]
location
Location

record TraitInfo

A trait declaration and the signatures or default methods in its body.

Fields

name
String
doc
String?
typeParams
[String]
body
[Node]
location
Location

record MakeInfo

A make implementation block.

target is the receiver type, implements lists explicit traits, and body retains methods and visibility sections in declaration order.

Fields

target
TypeRef
doc
String?
isFinal
Bool
implements
[TypeRef]
body
[Node]
location
Location

record PragmaInfo

A compiler pragma and its optional value.

Fields

name
String
value
String?
location
Location

record ModuleInfo

A module and its declarations in source order.

Fields

name
String
doc
String?
items
[Node]
location
Location

record ConstantInfo

A named constant declaration. The AST reader never evaluates its value.

Fields

name
String
doc
String?
type
TypeRef?
location
Location

record VisibilityInfo

A public or private section and the declarations it contains.

Fields

isPublic
Bool
items
[Node]
location
Location

record UsingInfo

A using import, including aliasing, filters, and an optional scoped body.

Fields

moduleName
String
alias
String?
onlyNames
[String]
exceptNames
[String]
location
Location

record ExportInfo

An export declaration and its public-name filters.

Fields

moduleName
String
alias
String?
onlyNames
[String]
exceptNames
[String]
location
Location

type CompiledItem

One item inside a compiled do block before expansion.

Variants

  • CompiledNode(Node)
  • CompiledExpression(Expression)

record CompiledInfo

A compile-time block and its declarations or expressions in source order.

Fields

location
Location

type Node

Any top-level or declaration-level AST node.

A source tool can match only the declarations it understands and leave the rest alone. The program's schemaVersion lets persisted consumers reject a tree whose possible node shapes have changed.

Variants

  • ModuleDef(ModuleInfo)
  • FunctionDef(FunctionInfo)
  • TypeAnnotation(AnnotationInfo)
  • TypeDef(TypeInfo)
  • RecordDef(RecordInfo)
  • TraitDef(TraitInfo)
  • MakeDef(MakeInfo)
  • PragmaDef(PragmaInfo)
  • ConstantDef(ConstantInfo)
  • MainDef(MainInfo)
  • Visibility(VisibilityInfo)
  • UsingDef(UsingInfo)
  • ExportDef(ExportInfo)
  • Compiled(CompiledInfo)

make TypeRef | PatternRef

Source-like conversion through the standard to(String) spelling.

Useful in diagnostics: a tool can interpolate the type or pattern it found without manually dispatching between the two reference families.

to

to(String)