Skip to content

Commit

Permalink
Build ast
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanjermakov committed Jun 14, 2023
1 parent 4c7aff3 commit aca9ee7
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 23 deletions.
21 changes: 18 additions & 3 deletions src/ast/expr.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { BinaryOp, UnaryOp } from './op'
import { AstNode } from './index'
import { VarDef } from './statement'
import { ParseNode } from '../parser/parser'
import { todo } from '../todo'
import { Operand } from './operand'

export type Expr = UnaryExpr | BinaryExpr
export type Expr = OperandExpr | UnaryExpr | BinaryExpr

export const buildExpr = (node: ParseNode): VarDef => {
export const buildExpr = (node: ParseNode): Expr => {
return todo()
}

export interface OperandExpr extends AstNode<'operand-expr'> {
operand: Operand
}

export const buildOperandExpr = (node: ParseNode): OperandExpr => {
return todo()
}

Expand All @@ -16,8 +23,16 @@ export interface UnaryExpr extends AstNode<'unary-expr'> {
operand: Operand
}

export const buildUnaryExpr = (node: ParseNode): UnaryExpr => {
return todo()
}

export interface BinaryExpr extends AstNode<'binary-expr'> {
binaryOp: BinaryOp
lOperand: Operand
rOperand: Operand
}

export const buildBinaryExpr = (node: ParseNode): BinaryExpr => {
return todo()
}
7 changes: 5 additions & 2 deletions src/ast/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export type AstNodeKind
| 'field-def'
| 'type-con'
| 'return-stmt'
| 'spread-op'
| 'operand-expr'
| 'unary-expr'
| 'binary-expr'
| 'block'
Expand All @@ -32,6 +34,7 @@ export type AstNodeKind
| 'match-expr'
| 'match-clause'
| 'con-pattern'
| 'field-pattern'
| 'hole'
| 'identifier'
| 'string-literal'
Expand All @@ -55,7 +58,7 @@ export const buildModule = (node: ParseNode): Module => {
}

export interface Type extends AstNode<'type'> {
name: Identifier
identifier: Identifier
typeParams: Type[]
}

Expand All @@ -66,7 +69,7 @@ export const buildType = (node: ParseNode): Type => {
return {
type: 'type',
parseNode: node,
name: buildIdentifier(nameNode),
identifier: buildIdentifier(nameNode),
typeParams: paramsNode
? (<ParseTree>paramsNode).nodes
.filter(n => n.kind === 'type-params')
Expand Down
44 changes: 40 additions & 4 deletions src/ast/match.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,63 @@
import { Expr } from './expr'
import { buildOperandExpr, Expr } from './expr'
import { Block } from './statement'
import { AstNode } from './index'
import { AstNode, filterIndependent } from './index'
import { ParseNode } from '../parser/parser'
import { todo } from '../todo'
import { buildOperand, Identifier } from './operand'
import { buildUnaryOp, SpreadOp } from './op'

export type Pattern = ConPattern | Expr | Hole

export const buildPattern = (node: ParseNode): Pattern => {
return todo()
const nodes = filterIndependent(node)
if (nodes[0].kind === 'con-pattern') {
return buildConPattern(nodes[0])
}
if (nodes[0].kind === 'hole') {
return buildHole(nodes[0])
}
if (nodes[0].kind === 'prefix-op') {
const unaryOp = buildUnaryOp(nodes[0])
const operand = buildOperand(nodes[1])
return { type: 'unary-expr', parseNode: node, unaryOp, operand }
}
return buildOperandExpr(nodes[0])
}

export interface ConPattern extends AstNode<'con-pattern'> {
// TODO
identifier: Identifier
fieldPatterns: (FieldPattern | SpreadOp)[]
}

export const buildConPattern = (node: ParseNode): ConPattern => {
return todo()
}

export interface FieldPattern extends AstNode<'field-pattern'> {
identifier: Identifier
fieldPatterns: FieldPattern[]
}

export const buildFieldPattern = (node: ParseNode): FieldPattern | SpreadOp => {
return todo()
}

export interface Hole extends AstNode<'hole'> {
}

export const buildHole = (node: ParseNode): Hole => {
return { type: 'hole', parseNode: node }
}

export interface MatchExpr extends AstNode<'match-expr'> {
expr: Expr
clauses: MatchClause
}

export const buildMatchExpr = (node: ParseNode): MatchExpr => {
return todo()
}

export interface MatchClause extends AstNode<'match-clause'> {
pattern: Pattern
block: Block
Expand Down
14 changes: 14 additions & 0 deletions src/ast/op.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
import { AstNode } from './index'
import { ParseNode } from '../parser/parser'
import { todo } from '../todo'

export type UnaryOp = 'todo'

export const buildUnaryOp = (node: ParseNode): UnaryOp => {
return todo()
}

export type BinaryOp = 'todo'

export const buildBinaryOp = (node: ParseNode): BinaryOp => {
return todo()
}

export interface SpreadOp extends AstNode<'spread-op'> {
}
104 changes: 95 additions & 9 deletions src/ast/operand.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { MatchExpr, Pattern } from './match'
import { AstNode, Param, Type } from './index'
import { Block } from './statement'
import { Expr } from './expr'
import { buildMatchExpr, buildPattern, MatchExpr, Pattern } from './match'
import { AstNode, buildParam, buildType, filterIndependent, Param, Type } from './index'
import { Block, buildBlock } from './statement'
import { buildExpr, Expr } from './expr'
import { ParseNode } from '../parser/parser'
import { todo } from '../todo'
import { ParseToken } from '../lexer/lexer'

export type Operand =
IfExpr
export type Operand
= IfExpr
| WhileExpr
| ForExpr
| MatchExpr
Expand All @@ -19,55 +19,141 @@ export type Operand =
| FloatLiteral
| Identifier

export const buildOperand = (node: ParseNode): Operand => {
const t = filterIndependent(node)[0]
switch (t.kind) {
case 'if-expr':
return buildIfExpr(t)
case 'while-expr':
return buildWhileExpr(t)
case 'for-expr':
return buildForExpr(t)
case 'match-expr':
return buildMatchExpr(t)
case 'closure-expr':
return buildClosureExpr(t)
case 'expr':
return buildExpr(t)
case 'list-expr':
return buildListExpr(t)
case 'string':
return buildStringLiteral(t)
case 'char':
return buildCharLiteral(t)
case 'int':
return buildIntLiteral(t)
case 'float':
return buildFloatLiteral(t)
case 'identifier':
return buildIdentifier(t)
}
throw Error('expected operand')
}

export interface IfExpr extends AstNode<'if-expr'> {
condition: Expr
thenBlock: Block
elseBlock?: Block
}

export const buildIfExpr = (node: ParseNode): IfExpr => {
const nodes = filterIndependent(node)
const condition = buildExpr(nodes[0])
const thenBlock = buildBlock(nodes[1])
const elseBlock = nodes.at(2) ? buildBlock(nodes[1]) : undefined
return { type: 'if-expr', parseNode: node, condition, thenBlock, elseBlock }
}

export interface WhileExpr extends AstNode<'while-expr'> {
condition: Expr
block: Block
}

export const buildWhileExpr = (node: ParseNode): WhileExpr => {
const nodes = filterIndependent(node)
const condition = buildExpr(nodes[0])
const block = buildBlock(nodes[1])
return { type: 'while-expr', parseNode: node, condition, block }
}

export interface ForExpr extends AstNode<'for-expr'> {
pattern: Pattern
expr: Expr
block: Block
}

export const buildForExpr = (node: ParseNode): ForExpr => {
const nodes = filterIndependent(node)
const pattern = buildPattern(nodes[0])
const expr = buildExpr(nodes[1])
const block = buildBlock(nodes[2])
return { type: 'for-expr', parseNode: node, pattern, expr, block }
}

export interface ClosureExpr extends AstNode<'closure-expr'> {
name: Identifier
identifier: Identifier
typeParams: Type[]
params: Param[]
block: Block
returnType?: Type
}

export const buildClosureExpr = (node: ParseNode): ClosureExpr => {
const nodes = filterIndependent(node)
const identifier = buildIdentifier(nodes[0])
const typeParams = filterIndependent(nodes[1]).filter(n => n.kind === 'type-expr').map(n => buildType(n))
const params = filterIndependent(nodes[2]).filter(n => n.kind === 'param').map(n => buildParam(n))
const block = buildBlock(nodes[3])
const returnType = nodes.at(4) ? buildType(nodes[4]) : undefined
return { type: 'closure-expr', parseNode: node, identifier, typeParams, params, block, returnType }
}

export interface ListExpr extends AstNode<'list-expr'> {
exprs: Expr[]
}

export const buildListExpr = (node: ParseNode): ListExpr => {
const nodes = filterIndependent(node)
const exprs = filterIndependent(nodes[0]).filter(n => n.kind === 'expr').map(n => buildExpr(n))
return { type: 'list-expr', parseNode: node, exprs }
}

export interface StringLiteral extends AstNode<'string-literal'> {
value: string
}

export const buildStringLiteral = (node: ParseNode): StringLiteral => {
return { type: 'string-literal', parseNode: node, value: (<ParseToken>node).value }
}

export interface CharLiteral extends AstNode<'char-literal'> {
value: string
}

export const buildCharLiteral = (node: ParseNode): CharLiteral => {
return { type: 'char-literal', parseNode: node, value: (<ParseToken>node).value }
}

export interface IntLiteral extends AstNode<'int-literal'> {
value: string
}

export const buildIntLiteral = (node: ParseNode): IntLiteral => {
return { type: 'int-literal', parseNode: node, value: (<ParseToken>node).value }
}

export interface FloatLiteral extends AstNode<'float-literal'> {
value: string
}

export const buildFloatLiteral = (node: ParseNode): FloatLiteral => {
return { type: 'float-literal', parseNode: node, value: (<ParseToken>node).value }
}

export interface Identifier extends AstNode<'identifier'> {
value: string
}

export const buildIdentifier = (node: ParseNode): Identifier => {
return todo()
return { type: 'identifier', parseNode: node, value: (<ParseToken>node).value }
}
10 changes: 7 additions & 3 deletions src/ast/statement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const buildVarDef = (node: ParseNode): VarDef => {

export interface FnDef extends AstNode<'fn-def'> {
type: 'fn-def'
name: Identifier
identifier: Identifier
typeParams: Type[]
params: Param[]
block?: Block
Expand All @@ -54,7 +54,7 @@ export const buildFnDef = (node: ParseNode): VarDef => {
}

export interface KindDef extends AstNode<'kind-def'> {
name: Identifier
identifier: Identifier
kindParams: Type[]
block: Block
}
Expand All @@ -64,7 +64,7 @@ export const buildKindDef = (node: ParseNode): VarDef => {
}

export interface ImplDef extends AstNode<'impl-def'> {
name: Identifier
identifier: Identifier
implParams: Type[]
forKind?: Type
block: Block
Expand All @@ -85,3 +85,7 @@ export const buildReturnStmt = (node: ParseNode): VarDef => {
export interface Block extends AstNode<'block'> {
statements: Statement[]
}

export const buildBlock = (node: ParseNode): Block => {
return todo()
}
4 changes: 2 additions & 2 deletions src/ast/type-def.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { todo } from '../todo'
import { Identifier } from './operand'

export interface TypeDef extends AstNode<'type-def'> {
name: Identifier
identifier: Identifier
typeParams: Param[]
variants: TypeCon[]
}
Expand All @@ -19,7 +19,7 @@ export interface TypeCon extends AstNode<'type-con'> {
}

export interface FieldDef extends AstNode<'field-def'> {
name: Identifier
identifier: Identifier
fieldType: Type
}

0 comments on commit aca9ee7

Please sign in to comment.