TypeScript Compiler Source Code
Compiler Architecture
Core Module Responsibilities:
// Simplified Compiler Architecture Workflow
function compile(program: Program): EmitResult {
// 1. Parsing Phase
const sourceFiles = program.getSourceFiles()
const parser = new Parser(program)
const syntaxTrees = sourceFiles.map(file => parser.parseFile(file))
// 2. Type Checking Phase
const checker = new TypeChecker(program)
checker.typeCheck(syntaxTrees)
// 3. Code Generation Phase
const emitter = new Emitter(program)
return emitter.emit(syntaxTrees)
}
// Class Diagram Relationships of Compiler Architecture
class Program {
private sourceFiles: SourceFile[]
private languageService: LanguageService
// ...
}
class Parser {
parseFile(file: SourceFile): SyntaxTree
}
class TypeChecker {
typeCheck(syntaxTrees: SyntaxTree[]): void
}
class Emitter {
emit(syntaxTrees: SyntaxTree[]): EmitResult
}
Lexical Analysis and Syntax Analysis
Scanner Implementation Key Code:
// Simplified Scanner Implementation
class Scanner {
private sourceText: string
private position: number = 0
private token: SyntaxKind = SyntaxKind.Unknown
scan(): SyntaxKind {
while (this.position < this.sourceText.length) {
const ch = this.sourceText.charCodeAt(this.position)
switch (ch) {
case CharacterCodes.Space:
case CharacterCodes.Tab:
case CharacterCodes.LineFeed:
this.position++
continue
case CharacterCodes.DoubleQuote:
return this.scanString()
case CharacterCodes.IdentifierStart:
return this.scanIdentifier()
// ...other character handling
}
}
return SyntaxKind.EndOfFileToken
}
private scanString(): SyntaxKind {
// String literal scanning logic
}
private scanIdentifier(): SyntaxKind {
// Identifier scanning logic
}
}
Parser Syntax Tree Construction:
// Simplified Parser Implementation
class Parser {
parseSourceFile(): SourceFile {
const node = this.createNode(SyntaxKind.SourceFile)
this.nextToken() // Skip initial token
while (this.token !== SyntaxKind.EndOfFileToken) {
const statement = this.parseStatement()
node.statements.push(statement)
}
return this.finishNode(node)
}
private parseStatement(): Statement {
switch (this.token) {
case SyntaxKind.VarKeyword:
return this.parseVariableStatement()
case SyntaxKind.FunctionKeyword:
return this.parseFunctionDeclaration()
// ...other statement types
}
}
}
Type Checker
Core Type Checking Logic:
// Simplified Type Checking Workflow
class TypeChecker {
private typeMap: Map<Node, Type> = new Map()
typeCheck(node: Node): Type {
if (this.typeMap.has(node)) {
return this.typeMap.get(node)!
}
let type: Type
switch (node.kind) {
case SyntaxKind.Identifier:
type = this.checkIdentifier(node as Identifier)
break
case SyntaxKind.BinaryExpression:
type = this.checkBinaryExpression(node as BinaryExpression)
break
// ...other node types
}
this.typeMap.set(node, type)
return type
}
private checkBinaryExpression(node: BinaryExpression): Type {
const leftType = this.typeCheck(node.left)
const rightType = this.typeCheck(node.right)
if (!this.isTypeCompatible(leftType, rightType)) {
this.error(node, DiagnosticMessages.IncompatibleTypes)
}
return this.getBinaryExpressionType(node.operatorToken, leftType, rightType)
}
}
Code Generator
Emitter Implementation Key Code:
// Simplified Emitter Implementation
class Emitter {
emit(sourceFile: SourceFile): EmitResult {
const writer = new CodeWriter()
this.emitNode(sourceFile, writer)
return { outputFiles: writer.getOutputFiles() }
}
private emitNode(node: Node, writer: CodeWriter) {
switch (node.kind) {
case SyntaxKind.FunctionDeclaration:
this.emitFunctionDeclaration(node as FunctionDeclaration, writer)
break
case SyntaxKind.VariableStatement:
this.emitVariableStatement(node as VariableStatement, writer)
break
// ...other node types
}
}
private emitFunctionDeclaration(node: FunctionDeclaration, writer: CodeWriter) {
writer.write(`function ${node.name.text}(`)
this.emitParameters(node.parameters, writer)
writer.write(') {')
this.emitBlock(node.body, writer)
writer.write('}')
}
}
Error Handling and Reporting
Error Diagnostic System:
// Error Reporting Implementation
class DiagnosticReporter {
private diagnostics: Diagnostic[] = []
report(node: Node, message: DiagnosticMessage, ...args: any[]) {
const diagnostic: Diagnostic = {
file: node.getSourceFile(),
start: node.getStart(),
length: node.getWidth(),
messageText: formatMessage(message, args),
category: DiagnosticCategory.Error,
code: getErrorCode(message)
}
this.diagnostics.push(diagnostic)
}
getDiagnostics(): Diagnostic[] {
return this.diagnostics
}
}
// Error Message Definitions
namespace DiagnosticMessages {
export const IncompatibleTypes = {
category: DiagnosticCategory.Error,
code: 2322,
message: "Type '{0}' is not assignable to type '{1}'"
}
// ...other error messages
}



