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.
parse
parse(source: String) -> Result<Program, ParseError>
parse(source: String, filename: String) -> Result<Program, ParseError>
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.
Parameters
source- the Kex source text
filename- the name to report locations against; optional
Returns 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 }
parseFile
parseFile(path: FS.FilePath) -> Result<Program, ParseError>
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.
Parameters
path- the file to read and parse
Returns 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)) }
parseType
parseType(source: String) -> Result<TypeRef, ParseError>
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.
Parameters
source- the type expression
Returns 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>")
parseExpression
parseExpression(source: String) -> Result<Expression, ParseError>
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.
Parameters
source- the expression text
Returns the parsed expression, or why it failed
Examples
Kex.AST.parseExpression("1 + 2").ok? # => true
Kex.AST.parseExpression("1 +").ok? # => false
typeRefText
typeRefText(typeRef: TypeRef) -> String
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.
Parameters
typeRef- the parsed type
Returns 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?")
patternRefText
patternRefText(patternRef: PatternRef) -> String
Renders a PatternRef back to the way it is written in source.
Parameters
patternRef- the parsed pattern
Returns the pattern, as source
Examples
Kex.AST.patternRefText(WildcardPattern) # => "_"
Kex.AST.patternRefText(BindPattern("n")) # => "n"
patternFieldText
patternFieldText(name, _, _) -> String
referenceText
referenceText(reference: TypeRef | PatternRef) -> String
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.
Parameters
reference- the parsed node
Returns the node, as source
Examples
Kex.AST.referenceText(WildcardPattern) # => "_"
Kex.AST.referenceText(AnyType) # => "Any"
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
record Program
A parsed source file: its schema version, and its top-level items.
Fields
schemaVersionIntegeritems[Node]
record ParseError
Why a source file could not be parsed.
Fields
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)AnyTypeNoneType
type PatternRef
Structured representation of patterns.
Variants
BindPattern(String)LiteralPattern(String)ConstructorPattern(String, [PatternRef])TuplePattern([PatternRef])ListPattern([PatternRef], PatternRef?)RecordPattern(String?, [PatternField])RangePattern(PatternRef, PatternRef)ThisPattern(PatternRef)WildcardPattern
record PatternField
Fields
nameStringpatternPatternRef?stringKeyBool
type Expression
Structured representation of expression AST nodes.
Variants
LitInt(Int)LitFloat(Float)LitChar(Int)LitString(String)InterpolatedString([String], [Expression])LitBool(Bool)LitAtom(String)LitNoneIdentifier(String)ThisBinaryOp(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)BreakNextSpawn([Expression])Try(Expression)Spread(Expression)TrailingIf(Expression, Expression)ThenElse(Expression, Expression, Expression)ShorthandLambda(String, [Expression], Bool)CurryPlaceholderCurry(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
Fields
nameStringvalueExpression
record MatchArm
Fields
patterns[PatternRef]guardExpression?bodyExpression
record LambdaParam
Fields
record RescueInfo
Fields
arms[MatchArm]catchAllNameString?catchAllBody[Expression]inlineReturnExpression?
record ElseIf
Fields
conditionExpressionbody[Expression]
type MapItem
Variants
MapEntry(Expression, Expression)MapSpread(Expression)
record RecordField
Fields
nameStringvalueExpression
type GeneratedTemplate
A declaration template whose name (and, for a make block, target) is computed by a compiled do expression.
Variants
GeneratedNode(Node)GeneratedMake(GeneratedMakeInfo)
record GeneratedMakeInfo
Fields
isFinalBoolimplements[TypeRef]body[CompiledItem]locationLocation
record MainInfo
Fields
docString?params[ParamInfo]body[Expression]rescueInfoRescueInfo?locationLocation
record ParamInfo
Fields
nameString?patternPatternRef?typeTypeRef?hasDefaultBool
record ClauseInfo
Fields
params[ParamInfo]body[Expression]returnTypeTypeRef?rescueInfoRescueInfo?hasParamListBool
record FunctionInfo
Fields
record AnnotationInfo
Fields
record VariantInfo
Fields
record TypeInfo
Fields
record FieldInfo
Fields
record RecordInfo
Fields
record TraitInfo
Fields
record MakeInfo
Fields
record PragmaInfo
Fields
record ModuleInfo
Fields
record ConstantInfo
Fields
record VisibilityInfo
Fields
record UsingInfo
Fields
record ExportInfo
Fields
type CompiledItem
Variants
CompiledNode(Node)CompiledExpression(Expression)
record CompiledInfo
Fields
items[CompiledItem]locationLocation
type Node
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)
type TypeRef | PatternRef
Source-like conversion through the standard .to(String) spelling.
to
to(_) -> String?