项目基本结构
课程项目框架按照功能阶段组织如下:
- logging
- 这个被用来报错,感觉还是有点不对劲
- inputHandler
- 引入接口Locator
- 将输入文件封装成可定位的可回退的字符流,方便lexicalAnalyzer提取token
- lexicalAnalyzer
- 本质上是一个token iterator
- lextant: 词法单元中的标点符号以及关键字
- tokens
- 基本抽象token:可定位,可获取词素
- 词素
- 定位
- 是否属于lextant set
- 字面量:整型,浮点,字符,布尔值,字符串
- 标识符
- 标点
- 关键字
- parser
- 读取token流,通过BNF产生式构造AST
- parseTree
- 提供基本类ParseNode
- getClass()
- getToken()
- getType()
- getScope()
- 提供基本类ParseNodeVisitor
- parseTree.nodeTypes
- 非终结符对应的各种具体的Node
- sementicAnalyzer
- 对AST进行语义分析,检查推断类型,分配内存,构建绑定
- sementicAnalyzer.types
- 类型系统
- sementicAnalyzer.signatures
- 根据输入的类型选择合法的操作
- symbolTable
- MemoryLocation
- baseAddress:String; 内存定位总是基于某个基地址,可以是内存的某个段,或者通过“寄存器”间接寻址。这个机器里没有寄存器的概念,但是我们可以通过预留的全局空间来模拟。比如FP,SP的实现。
- offset:int
- 因为分配内存的时候,并没有完全确定下来最后的位置。所以分配的内存信息包含了相对的偏移值。
- MemoryAccessMethod
- 这个类以enum的形式提供了2个内存访问方法,分别是基于符号的直接偏移寻址,以及间接寻址。base[offset], base[0][offset]
- 这个间接寻址等价于通过寄存器寻址,用一个预先分配的固定内存位置充当寄存器。
- design pattern: template method, Java enum singleton
- public void generateAddress(ASMCodeFragment code, String baseAddress, int offset, String comment)
- 往code里加入变量的地址,并加以标注
- 基地址,offset,以及标注(名字)来自绑定的memoryLocation
- 这个类其实应该放在code generator里
- 这个类以enum的形式提供了2个内存访问方法,分别是基于符号的直接偏移寻址,以及间接寻址。base[offset], base[0][offset]
- 基本抽象Scope
- 每个scope有一个内存分配器MemoryAllocator(subscope继承这个分配器)
- MemoryAllocator(管理寻址方式,基址,分配方向)
- 接受给定大小的分配请求,返回MemoryLocation
- MemoryLocation提供生成压栈地址的指令序列
- 接受给定大小的分配请求,返回MemoryLocation
- MemoryAllocator(管理寻址方式,基址,分配方向)
- 每个Scope维护自己的符号表SymbolTable(String -> Binding)
- nullInstance()这个其实没有存在的必要。唯一用到的地方其实是死代码
- getAllocatedSize()
- 每次创建scope时,对应的分配器做一次标记,离开这个scope的时候,分配器弹出上一个记录
- 每个scope有一个内存分配器MemoryAllocator(subscope继承这个分配器)
- SymbolTable本质上就是标识符到绑定的映射
- Binding: 标识符名称,类型,源文件位置,内存位置,等相关的信息。每个分配了内存地址的binding,都应该有一个memoryLocation,并且可以根据这个内存地址来生成代码将此代码压栈。binding.memoryLocation.getAddressCode(),或者CodeGenerator.generateAddressCode(binding.memoryLocation)。哪种设计更好?为什么?
- MemoryLocation
- asmCodeGenerator
- 产生线性的代码结构
- asmCodeGenerator.codeStorage
- 指令,指令块
- asmCodeGenerator.operators
- asmCodeGenerator.runtime
- 运行时支持
- 内存分配器
- 运行时函数
- 运行时支持
一些笔记,以免遗忘
- Binding是在哪里构造的
- 语义分析时,遇到声明语句时,因为已经处理过标识符节点,以及表达式节点。可以在退出访问声明语句节点时构建绑定。
- SemanticAnalyzer
- IdentifierNode
- Scope
- CreateBinding
- 语义分析时,获取了类型信息就直接分配内存并生成绑定并传递给IdentifierNode
- Binding核心功能就是提供类型和内存地址
- IdentifierNode是叶子结点,所以使用visit。语义分析访问属于DeclarationNode的此结点时生成Binding,代码生成器访问时此结点时生成地址。
- MemoryManager.java是一个堆的分配器,这里的函数都使用全局变量,因此不能递归调用。其实与其叫它们函数,不如叫routine/procedure更合适,因为它们没有自己的局部变量。
- 函数调用应该生成一个值,即使这个函数是void,代码生成也是一个ValueCode
- AtomicExpression等同于C里的PrimaryExpression,即最高优先级的表达式,表达式最高优先级总是会收敛到此。
- 错误处理,语法,返回一个ErrorNode,语义赋值一个ErrorTYpe,代码生成拒绝。
- Bilby只有全局(静态)作用域,函数作用域,变量寻址就相当容易。
- 所有的string字面量都可以放在global下。
- 左值以地址的形式出现在赋值操作左侧,其他地方都转成所包含的数值。
- 算符的类型是所支持的signature的集合。
- 如果函数支持重载,那么它的类型也是signature的集合,(匹配参数的时候,只关心参数类型,所以不同的返回类型不能作为不同signature的判断依据)
任务分解
- 堆分配器的运行时逻辑
关于动态作用域跟静态作用域
Design Patterns
- parseTree.PathToRootIterable
size of the skeleton project
engineer@mac bilby-S % find . -name '*.java' | grep 'tests' -v | xargs wc -l | sort -hr
5876 total
785 ./src/asmCodeGenerator/runtime/MemoryManager.java
404 ./src/parser/Parser.java
319 ./src/asmCodeGenerator/ASMCodeGenerator.java
188 ./src/asmCodeGenerator/codeStorage/ASMCodeFragment.java
171 ./src/semanticAnalyzer/SemanticAnalysisVisitor.java
170 ./src/asmCodeGenerator/codeStorage/ASMOpcode.java
167 ./src/lexicalAnalyzer/LexicalAnalyzer.java
166 ./src/parseTree/ParseNode.java
158 ./src/asmCodeGenerator/codeStorage/ASMInstruction.java
124 ./src/symbolTable/Scope.java
121 ./src/parseTree/ParseTreePrinter.java
118 ./src/parseTree/ParseNodeVisitor.java
109 ./src/semanticAnalyzer/signatures/FunctionSignature.java
108 ./src/lexicalAnalyzer/PunctuatorScanningAids.java
105 ./src/asmCodeGenerator/Macros.java
96 ./src/semanticAnalyzer/signatures/FunctionSignatures.java
92 ./src/asmCodeGenerator/runtime/RunTime.java
91 ./src/applications/BilbyApplication.java
88 ./src/inputHandler/InputHandler.java
87 ./src/applications/BilbyCompiler.java
86 ./src/applications/BilbyCodeGenerator.java
85 ./src/inputHandler/LocatedCharStream.java
78 ./src/asmCodeGenerator/PrintStatementGenerator.java
77 ./src/parseTree/nodeTypes/IdentifierNode.java
77 ./src/inputHandler/LineBasedReader.java
68 ./src/symbolTable/SymbolTable.java
66 ./src/symbolTable/Binding.java
65 ./src/logging/BilbyLogger.java
62 ./src/inputHandler/LocatedChar.java
61 ./src/lexicalAnalyzer/PunctuatorScanner.java
61 ./src/inputHandler/TextLocation.java
59 ./src/symbolTable/MemoryLocation.java
58 ./src/symbolTable/NegativeMemoryAllocator.java
58 ./src/asmCodeGenerator/codeStorage/ASMCodeChunk.java
57 ./src/symbolTable/PositiveMemoryAllocator.java
56 ./src/lexicalAnalyzer/Punctuator.java
52 ./src/parseTree/nodeTypes/DeclarationNode.java
51 ./src/tokens/TokenImp.java
50 ./src/parseTree/nodeTypes/OperatorNode.java
49 ./src/lexicalAnalyzer/Keyword.java
49 ./src/inputHandler/PushbackCharStream.java
46 ./src/inputHandler/LocatedCharString.java
43 ./src/symbolTable/MemoryAccessMethod.java
43 ./src/applications/BilbyTokenPrinter.java
42 ./src/applications/BilbySemanticChecker.java
39 ./src/parseTree/PathToRootIterable.java
38 ./src/applications/BilbyAbstractSyntaxTree.java
36 ./src/parseTree/nodeTypes/BooleanConstantNode.java
36 ./src/applications/NumberedFileLister.java
35 ./src/parseTree/nodeTypes/IntegerConstantNode.java
35 ./src/lexicalAnalyzer/ScannerImp.java
33 ./src/tokens/LextantToken.java
33 ./src/parseTree/nodeTypes/PrintStatementNode.java
32 ./src/lexicalAnalyzer/PartiallyScannedPunctuator.java
31 ./src/tokens/Tokens.java
28 ./src/tokens/NumberToken.java
28 ./src/parseTree/nodeTypes/ProgramNode.java
28 ./src/parseTree/nodeTypes/MainBlockNode.java
27 ./src/semanticAnalyzer/types/PrimitiveType.java
25 ./src/lexicalAnalyzer/LexemeMap.java
23 ./src/parseTree/nodeTypes/SpaceNode.java
23 ./src/parseTree/nodeTypes/NewlineNode.java
23 ./src/parseTree/nodeTypes/ErrorNode.java
22 ./src/semanticAnalyzer/SemanticAnalyzer.java
21 ./src/asmCodeGenerator/Labeller.java
20 ./src/tokens/NullToken.java
20 ./src/tokens/IdentifierToken.java
17 ./src/semanticAnalyzer/types/Type.java
13 ./src/tokens/Token.java
11 ./src/symbolTable/MemoryAllocator.java
11 ./src/asmCodeGenerator/operators/SimpleCodeGenerator.java
9 ./src/lexicalAnalyzer/Scanner.java
8 ./src/lexicalAnalyzer/Lextant.java
5 ./src/inputHandler/Locator.java