Skip to content

Commit 95ccecd

Browse files
committedMar 16, 2025·
Update ast helpers
1 parent 88a93af commit 95ccecd

File tree

7 files changed

+89
-46
lines changed

7 files changed

+89
-46
lines changed
 

‎src/cse-machine/interpreter.ts

+2
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,7 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
602602
command.loc
603603
)
604604
],
605+
'const',
605606
command.loc
606607
),
607608
ast.blockStatement(
@@ -614,6 +615,7 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
614615
command.loc
615616
)
616617
],
618+
'const',
617619
command.loc
618620
),
619621
command.body

‎src/modules/preprocessor/index.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -96,21 +96,21 @@ const preprocessFileImports = async (
9696
context,
9797
options?.importOptions
9898
)
99+
100+
const program = bundler(programs, entrypointFilePath, topoOrder, context)
101+
return {
102+
ok: true,
103+
program,
104+
files: linkerResult.files,
105+
verboseErrors: linkerResult.verboseErrors
106+
}
99107
} catch (error) {
100108
context.errors.push(error)
101109
return {
102110
ok: false,
103111
verboseErrors: linkerResult.verboseErrors
104112
}
105113
}
106-
107-
const program = bundler(programs, entrypointFilePath, topoOrder, context)
108-
return {
109-
ok: true,
110-
program,
111-
files: linkerResult.files,
112-
verboseErrors: linkerResult.verboseErrors
113-
}
114114
}
115115

116116
export default preprocessFileImports

‎src/modules/preprocessor/linker.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ export default async function parseProgramsAndConstructImportGraph(
139139
let statement: es.Node | null = null
140140

141141
if (!programs[entrypointFilePath]) {
142-
if (entrypointFileText == undefined) {
142+
if (entrypointFileText === undefined) {
143143
// non-existent entrypoint
144144
return false
145145
}

‎src/utils/ast/astCreator.ts

+14-16
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ import {
88
type StatementSequence
99
} from '../../types'
1010

11-
export const getVariableDeclarationName = (decl: es.VariableDeclaration) =>
12-
(decl.declarations[0].id as es.Identifier).name
13-
1411
export const locationDummyNode = (line: number, column: number, source: string | null) =>
1512
literal('Dummy', { start: { line, column }, end: { line, column }, source })
1613

@@ -85,18 +82,18 @@ export const declaration = (
8582
kind: AllowedDeclarations,
8683
init: es.Expression,
8784
loc?: es.SourceLocation | null
88-
): es.VariableDeclaration => ({
89-
type: 'VariableDeclaration',
90-
declarations: [
91-
{
92-
type: 'VariableDeclarator',
93-
id: identifier(name),
94-
init
95-
}
96-
],
97-
kind,
98-
loc
99-
})
85+
) =>
86+
variableDeclaration(
87+
[
88+
{
89+
type: 'VariableDeclarator',
90+
id: identifier(name),
91+
init
92+
}
93+
],
94+
kind,
95+
loc
96+
)
10097

10198
export const constantDeclaration = (
10299
name: string,
@@ -376,10 +373,11 @@ export const arrowFunctionExpression = (
376373

377374
export const variableDeclaration = (
378375
declarations: es.VariableDeclarator[],
376+
kind: es.VariableDeclaration['kind'] = 'const',
379377
loc?: es.SourceLocation | null
380378
): es.VariableDeclaration => ({
381379
type: 'VariableDeclaration',
382-
kind: 'const',
380+
kind,
383381
declarations,
384382
loc
385383
})

‎src/utils/ast/helpers.ts

+42-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type es from 'estree'
33
import assert from '../assert'
44
import { simple } from '../walkers'
55
import { ArrayMap } from '../dict'
6-
import { isImportDeclaration, isVariableDeclaration } from './typeGuards'
6+
import { isIdentifier, isImportDeclaration, isVariableDeclaration } from './typeGuards'
77

88
export function getModuleDeclarationSource(
99
node: Exclude<es.ModuleDeclaration, es.ExportDefaultDeclaration>
@@ -71,10 +71,27 @@ export function getIdsFromDeclaration(decl: es.Declaration, allowNull?: boolean)
7171
return rawIds
7272
}
7373

74+
export function getSourceVariableDeclaration(decl: es.VariableDeclaration) {
75+
assert(
76+
decl.declarations.length === 1,
77+
'Variable Declarations in Source should only have 1 declarator!'
78+
)
79+
80+
const [declaration] = decl.declarations
81+
assert(
82+
isIdentifier(declaration.id),
83+
'Variable Declarations in Source should be declared using an Identifier!'
84+
)
85+
86+
return {
87+
id: declaration.id,
88+
init: declaration.init!,
89+
loc: declaration.loc
90+
}
91+
}
92+
7493
export const getImportedName = (
75-
spec:
76-
| Exclude<es.ImportDeclaration['specifiers'][number], es.ImportNamespaceSpecifier>
77-
| es.ExportSpecifier
94+
spec: es.ImportSpecifier | es.ImportDefaultSpecifier | es.ExportSpecifier
7895
) => {
7996
switch (spec.type) {
8097
case 'ImportDefaultSpecifier':
@@ -85,3 +102,24 @@ export const getImportedName = (
85102
return spec.local.name
86103
}
87104
}
105+
106+
export const speciferToString = (
107+
spec: es.ImportSpecifier | es.ImportDefaultSpecifier | es.ExportSpecifier
108+
) => {
109+
switch (spec.type) {
110+
case 'ImportSpecifier': {
111+
if (spec.imported.name === spec.local.name) {
112+
return spec.imported.name
113+
}
114+
return `${spec.imported.name} as ${spec.local.name}`
115+
}
116+
case 'ImportDefaultSpecifier':
117+
return `default as ${spec.local.name}`
118+
case 'ExportSpecifier': {
119+
if (spec.local.name === spec.exported.name) {
120+
return spec.local.name
121+
}
122+
return `${spec.local.name} as ${spec.exported.name}`
123+
}
124+
}
125+
}

‎src/validator/__tests__/validator.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import * as es from 'estree'
1+
import type es from 'estree'
22

33
import { mockContext } from '../../utils/testing/mocks'
44
import { parse } from '../../parser/parser'
55
import { Chapter, NodeWithInferredType } from '../../types'
6-
import { getVariableDeclarationName } from '../../utils/ast/astCreator'
76
import { stripIndent } from '../../utils/formatters'
87
import { expectParsedError } from '../../utils/testing'
98
import { simple } from '../../utils/walkers'
109
import { validateAndAnnotate } from '../validator'
10+
import { getSourceVariableDeclaration } from '../../utils/ast/helpers'
1111

1212
export function toValidatedAst(code: string) {
1313
const context = mockContext(Chapter.SOURCE_1)
@@ -57,7 +57,7 @@ test('testing typability', () => {
5757
simple(ast, {
5858
VariableDeclaration(node: NodeWithInferredType<es.VariableDeclaration>) {
5959
let expectedTypability = ''
60-
switch (getVariableDeclarationName(node)) {
60+
switch (getSourceVariableDeclaration(node).id.name) {
6161
case 'a':
6262
case 'b':
6363
expectedTypability = 'NotYetTyped'

‎src/validator/validator.ts

+19-14
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
import * as es from 'estree'
1+
import type es from 'estree'
22

33
import { ConstAssignment, UndefinedVariable } from '../errors/errors'
44
import { NoAssignmentToForVariable } from '../errors/validityErrors'
55
import { parse } from '../parser/parser'
6-
import { Context, Node, NodeWithInferredType } from '../types'
7-
import { getVariableDeclarationName } from '../utils/ast/astCreator'
6+
import type { Context, Node, NodeWithInferredType } from '../types'
87
import {
98
getFunctionDeclarationNamesInProgram,
109
getIdentifiersInNativeStorage,
1110
getIdentifiersInProgram,
1211
getNativeIds,
13-
NativeIds
12+
type NativeIds
1413
} from '../utils/uniqueIds'
15-
import { ancestor, base, FullWalkerCallback } from '../utils/walkers'
14+
import { ancestor, base, type FullWalkerCallback } from '../utils/walkers'
15+
import { getSourceVariableDeclaration } from '../utils/ast/helpers'
1616

1717
class Declaration {
1818
public accessedBeforeDeclaration: boolean = false
@@ -30,7 +30,7 @@ export function validateAndAnnotate(
3030
for (const statement of node.body) {
3131
if (statement.type === 'VariableDeclaration') {
3232
initialisedIdentifiers.set(
33-
getVariableDeclarationName(statement),
33+
getSourceVariableDeclaration(statement).id.name,
3434
new Declaration(statement.kind === 'const')
3535
)
3636
} else if (statement.type === 'FunctionDeclaration') {
@@ -64,7 +64,9 @@ export function validateAndAnnotate(
6464
if (init.type === 'VariableDeclaration') {
6565
accessedBeforeDeclarationMap.set(
6666
forStatement,
67-
new Map([[getVariableDeclarationName(init), new Declaration(init.kind === 'const')]])
67+
new Map([
68+
[getSourceVariableDeclaration(init).id.name, new Declaration(init.kind === 'const')]
69+
])
6870
)
6971
scopeHasCallExpressionMap.set(forStatement, false)
7072
}
@@ -105,7 +107,7 @@ export function validateAndAnnotate(
105107
{
106108
VariableDeclaration(node: NodeWithInferredType<es.VariableDeclaration>, ancestors: Node[]) {
107109
const lastAncestor = ancestors[ancestors.length - 2]
108-
const name = getVariableDeclarationName(node)
110+
const { name } = getSourceVariableDeclaration(node).id
109111
const accessedBeforeDeclaration = accessedBeforeDeclarationMap
110112
.get(lastAncestor)!
111113
.get(name)!.accessedBeforeDeclaration
@@ -180,7 +182,10 @@ export function checkForUndefinedVariables(
180182
const identifiers = new Set<string>()
181183
for (const statement of node.body) {
182184
if (statement.type === 'VariableDeclaration') {
183-
identifiers.add((statement.declarations[0].id as es.Identifier).name)
185+
const {
186+
id: { name }
187+
} = getSourceVariableDeclaration(statement)
188+
identifiers.add(name)
184189
} else if (statement.type === 'FunctionDeclaration') {
185190
if (statement.id === null) {
186191
throw new Error(
@@ -217,13 +222,13 @@ export function checkForUndefinedVariables(
217222
BlockStatement: processBlock,
218223
FunctionDeclaration: processFunction,
219224
ArrowFunctionExpression: processFunction,
220-
ForStatement(forStatement: es.ForStatement, ancestors: es.Node[]) {
225+
ForStatement(forStatement: es.ForStatement) {
221226
const init = forStatement.init!
222227
if (init.type === 'VariableDeclaration') {
223-
identifiersIntroducedByNode.set(
224-
forStatement,
225-
new Set([(init.declarations[0].id as es.Identifier).name])
226-
)
228+
const {
229+
id: { name }
230+
} = getSourceVariableDeclaration(init)
231+
identifiersIntroducedByNode.set(forStatement, new Set([name]))
227232
}
228233
},
229234
Identifier(identifier: es.Identifier, ancestors: es.Node[]) {

0 commit comments

Comments
 (0)
Please sign in to comment.