Skip to content

Commit

Permalink
Ast: name
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanjermakov committed Jun 16, 2023
1 parent 14f584b commit 0a4eda7
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 31 deletions.
2 changes: 1 addition & 1 deletion data/features.no
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// imports
// TODO: imports
// use std::Display
// use std::io::{println}
// use std::Option::*
Expand Down
53 changes: 29 additions & 24 deletions src/ast/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { buildStatement, Statement } from './statement'
import { buildPattern, Pattern } from './match'
import { ParseNode, ParseTree, treeKinds } from '../parser/parser'
import { lexerDynamicKinds } from '../lexer/lexer'
import { buildIdentifier, Identifier } from './operand'
import { buildIdentifier, buildName, Identifier, Name } from './operand'
import { buildExpr, Expr } from './expr'

export interface AstNode<T extends AstNodeKind> {
Expand All @@ -29,7 +29,7 @@ export type AstNodeKind
| 'list-expr'
| 'param'
| 'type'
| 'type-param'
| 'generic'
| 'if-expr'
| 'while-expr'
| 'for-expr'
Expand All @@ -39,6 +39,7 @@ export type AstNodeKind
| 'field-pattern'
| 'hole'
| 'identifier'
| 'name'
| 'string-literal'
| 'char-literal'
| 'int-literal'
Expand Down Expand Up @@ -88,8 +89,10 @@ export interface Type extends AstNode<'type'> {
typeParams: TypeParam[]
}

export interface TypeParam extends AstNode<'type-param'> {
identifier: Identifier
export type TypeParam = Type | Generic

export interface Generic extends AstNode<'generic'> {
name: Name
bounds: Type[]
}

Expand All @@ -115,12 +118,11 @@ export const buildType = (node: ParseNode): Type => {
export const buildTypeParam = (node: ParseNode): TypeParam => {
const nodes = filterNonAstNodes(node)
if (nodes[0].kind === 'type-expr') {
const { identifier } = buildType(nodes[0])
return { type: 'type-param', parseNode: node, identifier, bounds: [] }
return buildType(nodes[0])
} else {
const identifier = buildIdentifier(nodes[0])
const name = buildName(nodes[0])
const bounds = filterNonAstNodes(nodes[1]).map(buildType)
return { type: 'type-param', parseNode: node, identifier, bounds }
return { type: 'generic', parseNode: node, name, bounds }
}
}

Expand All @@ -137,28 +139,31 @@ export const buildParam = (node: ParseNode): Param => {
}

export interface FieldInit extends AstNode<'field-init'> {
identifier: Identifier
name: Name
expr: Expr
}

export const buildFieldInit = (node: ParseNode): FieldInit => {
const nodes = filterNonAstNodes(node)
const identifier = buildIdentifier(nodes[0])
const name = buildName(nodes[0])
const expr = buildExpr(nodes[1])
return { type: 'field-init', parseNode: node, identifier, expr }
return { type: 'field-init', parseNode: node, name, expr }
}

export const compactAstNode = (node: AstNode<any>): any => Object.fromEntries(
Object.entries(node)
.filter(([p,]) => p !== 'parseNode')
.map(([p, v]) => {
if (Array.isArray(v)) {
return [p, v.map(compactAstNode)]
}
if (typeof v === 'object' && 'parseNode' in v) {
return [p, compactAstNode(v)]
}
return [p, v]
})
)
export const compactAstNode = (node: AstNode<any>): any => {
if (typeof node !== 'object') return node
return Object.fromEntries(
Object.entries(node)
.filter(([p,]) => p !== 'parseNode')
.map(([p, v]) => {
if (Array.isArray(v)) {
return [p, v.map(compactAstNode)]
}
if (typeof v === 'object' && 'parseNode' in v) {
return [p, compactAstNode(v)]
}
return [p, v]
})
)
}

8 changes: 4 additions & 4 deletions src/ast/match.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { buildExpr, buildOperandExpr, Expr } from './expr'
import { AstNode, filterNonAstNodes } from './index'
import { ParseNode } from '../parser/parser'
import { buildIdentifier, buildOperand, Identifier } from './operand'
import { buildIdentifier, buildName, buildOperand, Identifier, Name } from './operand'
import { buildUnaryOp, SpreadOp } from './op'
import { Block, buildBlock } from './statement'

Expand Down Expand Up @@ -63,7 +63,7 @@ export const buildConPattern = (node: ParseNode): ConPattern => {
}

export interface FieldPattern extends AstNode<'field-pattern'> {
identifier: Identifier
name: Name
pattern?: Pattern
}

Expand All @@ -72,9 +72,9 @@ export const buildFieldPattern = (node: ParseNode): FieldPattern | SpreadOp => {
if (nodes[0].kind === 'spread-op') {
return { type: 'spread-op', parseNode: node }
}
const identifier = buildIdentifier(nodes[0])
const name = buildName(nodes[0])
const pattern = nodes.at(1) ? buildPattern(nodes[1]) : undefined
return { type: 'field-pattern', parseNode: node, identifier, pattern }
return { type: 'field-pattern', parseNode: node, name, pattern }
}

export interface Hole extends AstNode<'hole'> {
Expand Down
16 changes: 14 additions & 2 deletions src/ast/operand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,21 @@ export const buildFloatLiteral = (node: ParseNode): FloatLiteral => {
}

export interface Identifier extends AstNode<'identifier'> {
value: string
scope: Name[]
name: Name
}

export const buildIdentifier = (node: ParseNode): Identifier => {
return { type: 'identifier', parseNode: node, value: (<ParseToken>node).value }
const names = filterNonAstNodes(node).map(buildName)
const scope = names.slice(0, -1)
const name = names.at(-1)!
return { type: 'identifier', parseNode: node, scope, name }
}

export interface Name extends AstNode<'name'> {
value: string
}

export const buildName = (node: ParseNode): Name => {
return { type: 'name', parseNode: node, value: (<ParseToken>node).value }
}

0 comments on commit 0a4eda7

Please sign in to comment.