Skip to content

Commit

Permalink
Merge pull request #12 from source-academy/compiler
Browse files Browse the repository at this point in the history
Add support for arithmetic expression and if else statement
  • Loading branch information
1001mei authored Oct 23, 2023
2 parents 794ee82 + f48524c commit e33afaa
Show file tree
Hide file tree
Showing 16 changed files with 721 additions and 165 deletions.
2 changes: 1 addition & 1 deletion src/ClassFile/types/attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export interface SameFrameExtended {
export interface AppendFrame {
frameType: number /* 252-254 */;
offsetDelta: number;
stack: Array<VerificationTypeInfo>;
locals: Array<VerificationTypeInfo>;
}

export interface FullFrame {
Expand Down
1 change: 0 additions & 1 deletion src/ast/astExtractor/ast-extractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export class ASTExtractor extends BaseJavaCstVisitorWithDefaults {
kind: "CompilationUnit",
topLevelClassOrInterfaceDeclarations: [],
};
this.validateVisitor();
}

extract(cst: CstNode): AST {
Expand Down
12 changes: 7 additions & 5 deletions src/ast/astExtractor/block-statement-extractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,20 @@ export class BlockStatementExtractor extends BaseJavaCstVisitorWithDefaults {

constructor() {
super();
this.validateVisitor();
}

extract(cst: BlockStatementCstNode): BlockStatement {
this.visit(cst);
return {
kind: "LocalVariableDeclarationStatement",
localVariableType: this.type,
variableDeclarationList: {
variableDeclaratorId: this.identifier,
variableInitializer: this.value,
},
variableDeclaratorList: [
{
kind: "VariableDeclarator",
variableDeclaratorId: this.identifier,
variableInitializer: this.value,
}
],
};
}

Expand Down
1 change: 0 additions & 1 deletion src/ast/astExtractor/class-extractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export class ClassExtractor extends BaseJavaCstVisitorWithDefaults {
this.modifier = [];
this.identifier = '';
this.body = [];
this.validateVisitor();
}

extract(cst: CstNode): ClassDeclaration {
Expand Down
15 changes: 8 additions & 7 deletions src/ast/astExtractor/method-extractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export class MethodExtractor extends BaseJavaCstVisitorWithDefaults {
this.identifier = '';
this.params = [];
this.body = [];
this.validateVisitor();
}

private getAndPop() {
Expand All @@ -48,12 +47,13 @@ export class MethodExtractor extends BaseJavaCstVisitorWithDefaults {
methodModifier: this.modifier,
methodHeader: {
result: "void",
methodDeclarator: {
identifier: this.identifier,
formalParameterList: this.params
}
identifier: this.identifier,
formalParameterList: this.params
},
methodBody: {
kind: "Block",
blockStatements:this.body,
},
methodBody: this.body,
};
}

Expand Down Expand Up @@ -89,8 +89,9 @@ export class MethodExtractor extends BaseJavaCstVisitorWithDefaults {
const argName = this.getAndPop();
const typeName = this.getAndPop();
this.params.push({
kind: "FormalParameter",
unannType: typeName,
variableDeclaratorId: argName,
identifier: argName,
});
}

Expand Down
18 changes: 5 additions & 13 deletions src/ast/types/ast.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
import { CompilationUnit } from "./packages-and-modules";
import {
BinaryExpression,
Literal,
LocalVariableDeclarationStatement,
UnaryExpression,
Block,
BlockStatement,
Expression,
} from "./blocks-and-statements";

export interface ExpressionMap {
BinaryExpression: BinaryExpression;
Literal: Literal;
UnaryExpression: UnaryExpression;
}

type Expression = ExpressionMap[keyof ExpressionMap];

interface NodeMap {
CompilationUnit: CompilationUnit;
LocalVariableDeclarationStatement: LocalVariableDeclarationStatement;
Block: Block;
BlockStatement: BlockStatement;
Expression: Expression;
}

Expand Down
91 changes: 80 additions & 11 deletions src/ast/types/blocks-and-statements.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,95 @@
import { Identifier, UnannType } from "./classes";

export type BlockStatement = LocalVariableDeclarationStatement;
export interface Block {
kind: "Block";
blockStatements: Array<BlockStatement>;
}
export type BlockStatement = LocalVariableDeclarationStatement | Statement;

export interface LocalVariableDeclarationStatement {
kind: "LocalVariableDeclarationStatement";
localVariableType: LocalVariableType;
variableDeclarationList: VariableDeclarator;
variableDeclaratorList: Array<VariableDeclarator>;
}

export type Statement = StatementWithoutTrailingSubstatement | IfStatement | WhileStatement | ForStatement;

export interface IfStatement {
kind: "IfStatement";
condition: Expression;
consequent: Statement;
alternate: Statement;
}

export interface WhileStatement {
kind: "WhileStatement";
condition: Expression;
body: Statement;
}

export interface DoStatement {
kind: "DoStatement";
condition: Expression;
body: Statement;
}

export type ForStatement = BasicForStatement | EnhancedForStatement;
export interface BasicForStatement {
kind: "BasicForStatement";
forInit: Array<ExpressionStatement> | LocalVariableDeclarationStatement;
condition: Expression;
forUpdate: Array<ExpressionStatement>;
body: Statement;
}

export interface EnhancedForStatement {
kind: "EnhancedForStatement";
}

export type StatementWithoutTrailingSubstatement = Block | ExpressionStatement | DoStatement;

export type ExpressionStatement = MethodInvocation | Assignment;

export interface MethodInvocation {
kind: "MethodInvocation";
identifier: Identifier
argumentList: ArgumentList;
}

export type ArgumentList = Array<Expression>;

export type LocalVariableType = UnannType;

export interface VariableDeclarator {
kind: "VariableDeclarator";
variableDeclaratorId: VariableDeclaratorId;
variableInitializer: VariableInitializer;
}

export type VariableDeclaratorId = Identifier;
export type VariableInitializer = Expression;
export type Expression = Literal | BinaryExpression | UnaryExpression;

export type Expression = Primary | BinaryExpression | UnaryExpression;
export type Primary = Literal | ExpressionName | Assignment;

export interface Literal {
kind: "Literal";
literalType:
| IntegerLiteral
| FloatingPointLiteral
| BooleanLiteral
| CharacterLiteral
| TextBlockLiteral
| StringLiteral
| NullLiteral;
| IntegerLiteral
| FloatingPointLiteral
| BooleanLiteral
| CharacterLiteral
| TextBlockLiteral
| StringLiteral
| NullLiteral;
}

export type IntegerLiteral =
| DecimalIntegerLiteral
| HexIntegerLiteral
| OctalIntegerLiteral
| BinaryIntegerLiteral;

export interface DecimalIntegerLiteral {
kind: "DecimalIntegerLiteral";
value: string;
Expand Down Expand Up @@ -86,11 +142,24 @@ export interface NullLiteral {

export interface BinaryExpression {
kind: "BinaryExpression";
operator: "+" | "-" | "*" | "/";
operator: "+" | "-" | "*" | "/" | "%" | "|" | "&" | "^" | "<<" | ">>" | ">>>" | "==" | "!=" | "<" | "<=" | ">" | ">=" | "&&" | "||";
left: Expression;
right: Expression;
}

export interface ExpressionName {
kind: "ExpressionName";
name: string;
}

export interface Assignment {
kind: "Assignment";
left: LeftHandSide;
operator: string;
right: Expression;
}

export type LeftHandSide = ExpressionName;
export type UnaryExpression = PrefixExpression;
export interface PrefixExpression {
kind: "PrefixExpression";
Expand Down
14 changes: 6 additions & 8 deletions src/ast/types/classes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BlockStatement } from "./blocks-and-statements";
import { Block } from "./blocks-and-statements";

export type ClassDeclaration = NormalClassDeclaration;

Expand Down Expand Up @@ -41,22 +41,20 @@ export type MethodModifier =

export interface MethodHeader {
result: Result;
methodDeclarator: MethodDeclarator;
}

export type Result = "void";
export interface MethodDeclarator {
identifier: Identifier;
formalParameterList: Array<FormalParameter>;
}

export type Result = "void";

export interface FormalParameter {
kind: "FormalParameter";
unannType: UnannType;
variableDeclaratorId: Identifier;
identifier: Identifier;
}

export type UnannType = string;
export type VariableDeclaratorId = Identifier;

export type MethodBody = Array<BlockStatement>;
export type MethodBody = Block;
export type Identifier = string;
59 changes: 52 additions & 7 deletions src/compiler/binaryWriter.ts → src/compiler/binary-writer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import { CONSTANT_TAG } from "../ClassFile/constants/constants";
import { ClassFile } from "../ClassFile/types";
import { AttributeInfo, CodeAttribute, ExceptionHandler } from "../ClassFile/types/attributes";
import {
AppendFrame,
AttributeInfo,
CodeAttribute,
ExceptionHandler,
ObjectVariableInfo,
StackMapTableAttribute,
UninitializedVariableInfo,
VerificationTypeInfo
} from "../ClassFile/types/attributes";
import {
ConstantClassInfo,
ConstantFieldrefInfo,
Expand All @@ -13,6 +22,8 @@ import {
import { FieldInfo } from "../ClassFile/types/fields";
import { MethodInfo } from "../ClassFile/types/methods";

import * as fs from "fs";

const u1 = 1;
const u2 = 2;
const u4 = 4;
Expand All @@ -26,7 +37,13 @@ export class BinaryWriter {
this.constantPool = [];
}

toBinary(classFile: ClassFile) {
writeBinary(classFile: ClassFile, filepath: string) {
const filename = filepath + "Main.class";
const binary = this.toBinary(classFile);
fs.writeFileSync(filename, binary);
}

private toBinary(classFile: ClassFile) {
this.byteArray = [];
this.constantPool = classFile.constantPool;

Expand All @@ -53,7 +70,7 @@ export class BinaryWriter {


private write(value: number, numOfBytes: number = u1) {
const bytes = [];
const bytes: Array<number> = [];
for (let i = 0; i < numOfBytes; i++) {
bytes.push(value & 0xff);
value >>>= 8;
Expand Down Expand Up @@ -130,6 +147,9 @@ export class BinaryWriter {
case "Code":
this.writeCodeAttribute(attribute as CodeAttribute);
break;
case "StackMapTable":
this.writeStackMapTableAttribute(attribute as StackMapTableAttribute);
break;
default: ;
}
}
Expand All @@ -140,12 +160,37 @@ export class BinaryWriter {
this.write(attribute.codeLength, u4);
this.writeDataView(attribute.code);
this.write(attribute.exceptionTableLength, u2);
attribute.exceptionTable.forEach(e => this.writeException(e));
attribute.exceptionTable.forEach(e => this.writeExceptionHandler(e));
this.write(attribute.attributesCount, u2);
attribute.attributes.forEach(a => this.writeAttribute(a));
}

private writeException(e: ExceptionHandler) {
e;
private writeExceptionHandler(e: ExceptionHandler) {
this.write(e.startPc, u2);
this.write(e.endPc, u2);
this.write(e.handlerPc, u2);
this.write(e.catchType, u2);
}

private writeStackMapTableAttribute(attribute: StackMapTableAttribute) {
this.write(attribute.entries.length, u2);
attribute.entries.forEach(frame => {
const { frameType: frameType } = frame;
this.write(frameType);
if (252 <= frameType && frameType <= 254) {
const { offsetDelta: offsetDelta, locals: locals } = frame as AppendFrame;
this.write(offsetDelta, u2);
locals.forEach(l => this.writeVerificationTypeInfo(l));
}
});
}

private writeVerificationTypeInfo(vtInfo: VerificationTypeInfo) {
this.write(vtInfo.tag);
if (vtInfo.tag == 7) {
this.write((vtInfo as ObjectVariableInfo).cpoolIndex, u2);
} else if (vtInfo.tag == 8) {
this.write((vtInfo as UninitializedVariableInfo).offset, u2);
}
}
}
}
Loading

0 comments on commit e33afaa

Please sign in to comment.