--- theme: dracula title: Compiler ULTIMATE # apply unocss classes to the current slide class: text-center # https://sli.dev/custom/highlighters.html highlighter: shiki # https://sli.dev/guide/drawing drawings: persist: false # slide transition: https://sli.dev/guide/animations#slide-transitions transition: slide-left # enable MDC Syntax: https://sli.dev/guide/syntax#mdc-syntax mdc: true plantUmlServer: 'https://www.plantuml.com/plantuml' --- # Compiler ULTIMATE Kein Weg ist mir im Schlitten je zu weit. --- # Parser **Besonderheiten und Änderungen zu Java:** - Pro Datei nur eine Klasse, mehrer Dateien einlesen - Keine Accessmodifier - print statt System.out.println - i++ eingeschränkt - Kein ++i - Zugriff af Felder nur mit this - Logische Statements Klammern, sonst von links nach rechts - Recipient - Fehlermeldungen werden gesammelt --- ## AST ```plantuml @startuml top to bottom direction entity Assignment << record >> { + Assignment(FieldVarAccess, Expression): + value(): Expression + location(): FieldVarAccess } entity Binary << record >> { + Binary(Expression, Operator, Expression): + op(): Operator + left(): Expression + right(): Expression } entity Block << record >> { + Block(List): + stmts(): List } entity BoolLiteral << record >> { + BoolLiteral(Boolean): + value(): Boolean } entity Break << record >> { + Break(): } entity CharLiteral << record >> { + CharLiteral(char): + value(): char } entity Class << record >> { + Class(String, Block, List, List, List): + Class(String, List, List, List): + mainmeth(): Block + classname(): String + methods(): List + constructors(): List + fieldDeclarations(): List } entity Constructor << record >> { + Constructor(String, List, Block): + params(): List + block(): Block + className(): String } entity Continue << record >> { + Continue(): } entity Declaration << record >> { + Declaration(String, Type): + type(): Type + name(): String } entity DoWhile << record >> { + DoWhile(Block, Expression): + cond(): Expression + block(): Block } interface Expression << interface >> entity FieldVarAccess << record >> { + FieldVarAccess(Boolean, Expression, String): + recursiveOwnerChain(): Expression + field(): Boolean + id(): String } entity For << record >> { + For(Assignment, Expression, Assignment, Block): + block(): Block + cond(): Expression + inc(): Assignment + assign(): Assignment } entity IfElse << record >> { + IfElse(Expression, Block, Block): + elseBlock(): Block + cond(): Expression + ifBlock(): Block } entity IntLiteral << record >> { + IntLiteral(Integer): + value(): Integer } entity Method << record >> { + Method(Type, String, List, Block): + block(): Block + methodName(): String + type(): Type + params(): List } entity MethodCall << record >> { + MethodCall(FieldVarAccess, List): + recipient(): FieldVarAccess + args(): List } entity New << record >> { + New(Type, List): + type(): Type + args(): List } interface Node << interface >> enum Operator << enumeration >> { + Operator(): + values(): Operator[] + valueOf(String): Operator } entity Parameter << record >> { + Parameter(String, Type): + type(): Type + name(): String } entity Print << record >> { + Print(Expression): + value(): Expression } entity Program << record >> { + Program(List): + classes(): List } entity Return << record >> { + Return(Expression): + ret(): Expression } interface Statement << interface >> entity Unary << record >> { + Unary(UnaryOperator, Expression): + right(): Expression + op(): UnaryOperator } enum UnaryOperator << enumeration >> { + UnaryOperator(): + values(): UnaryOperator[] + valueOf(String): UnaryOperator } entity While << record >> { + While(Expression, Block): + cond(): Expression + block(): Block } Assignment -[#008200,dashed]u-^ Statement Binary -[#008200,dashed]u-^ Expression Block -[#008200,dashed]u-^ Node BoolLiteral -[#008200,dashed]u-^ Expression Break -[#008200,dashed]u-^ Statement CharLiteral -[#008200,dashed]u-^ Expression Class -[#008200,dashed]u-^ Node Constructor -[#008200,dashed]u-^ Node Continue -[#008200,dashed]u-^ Statement Declaration -[#008200,dashed]u-^ Statement DoWhile -[#008200,dashed]u-^ Statement Expression -[#008200,plain]u-^ Node FieldVarAccess -[#008200,dashed]u-^ Expression For -[#008200,dashed]u-^ Statement IfElse -[#008200,dashed]u-^ Statement IntLiteral -[#008200,dashed]u-^ Expression Method -[#008200,dashed]u-^ Node MethodCall -[#008200,dashed]u-^ Expression MethodCall -[#008200,dashed]u-^ Statement New -[#008200,dashed]u-^ Expression New -[#008200,dashed]u-^ Statement Parameter -[#008200,dashed]u-^ Node Print -[#008200,dashed]u-^ Statement Program -[#008200,dashed]u-^ Node Return -[#008200,dashed]u-^ Statement Statement -[#008200,plain]u-^ Node Unary -[#008200,dashed]u-^ Expression While -[#008200,dashed]u-^ Statement @enduml ``` ## TypedAST ```plantuml @startuml !theme plain top to bottom direction skinparam linetype ortho class TypedAssignment { + TypedAssignment(TypedExpression, TypedFieldVarAccess, Type): + TypedAssignment(TypedProgram, Assignment): - location: TypedFieldVarAccess - type: Type - value: TypedExpression + toString(): String + equals(Object): boolean # canEqual(Object): boolean + hashCode(): int - convertToTypedAssignment(TypedProgram, Assignment): void + typeCheck(TypedProgram): Type - getTypeFromConstructorOrField(TypedConstructor, String, TypedClass): Type - getOwnerChain(MethodContext): void - getTypeLeft(TypedProgram): Type - getTypeFromMethodOrField(TypedMethod, String, TypedClass): Type + codeGen(MethodContext): void location: TypedFieldVarAccess value: TypedExpression type: Type } class TypedBinary { + TypedBinary(TypedExpression, Operator, TypedExpression, Type): + TypedBinary(): + TypedBinary(TypedProgram, Binary): - left: TypedExpression - right: TypedExpression - type: Type - op: Operator + equals(Object): boolean + hashCode(): int # canEqual(Object): boolean + toString(): String + typeCheck(TypedProgram): Type + codeGen(MethodContext): void - convertToTypedBinary(TypedProgram, Binary): void left: TypedExpression type: Type op: Operator right: TypedExpression } class TypedBlock { + TypedBlock(List, List, Type): + TypedBlock(): + TypedBlock(List, List): + TypedBlock(TypedProgram, Block): - type: Type - vars: List - stmts: List + toString(): String + equals(Object): boolean + hashCode(): int # canEqual(Object): boolean - clearLocalVariable(TypedProgram): void - convertToTypedBlock(TypedProgram, Block): void + typeCheck(TypedProgram): Type + codeGen(MethodContext): void stmts: List vars: List type: Type } class TypedBoolLiteral { + TypedBoolLiteral(Boolean, Type): + TypedBoolLiteral(): + TypedBoolLiteral(BoolLiteral): - type: Type - value: Boolean + equals(Object): boolean # canEqual(Object): boolean + hashCode(): int + toString(): String + codeGen(MethodContext): void - convertToTypedBoolLiteral(BoolLiteral): void + typeCheck(TypedProgram): Type value: Boolean type: Type } class TypedBreak { + TypedBreak(): - type: Type + equals(Object): boolean # canEqual(Object): boolean + hashCode(): int + toString(): String + typeCheck(TypedProgram): Type + codeGen(MethodContext): void type: Type } class TypedCharLiteral { + TypedCharLiteral(char, Type): + TypedCharLiteral(CharLiteral): - value: char - type: Type + equals(Object): boolean # canEqual(Object): boolean + hashCode(): int + toString(): String + typeCheck(TypedProgram): Type - convertToCharLiteral(CharLiteral): void + codeGen(MethodContext): void value: char type: Type } class TypedClass { + TypedClass(String, List, List, List, TypedMain, TypedMethod, TypedConstructor, Type, boolean): + TypedClass(): + TypedClass(String, List, List, List, TypedMain, TypedMethod, TypedConstructor, Type): + TypedClass(Class): - typedMethods: List - typedConstructors: List - currentMethod: TypedMethod - isMainCurrentMethod: boolean - className: String - typedMain: TypedMain - type: Type - currentConstructor: TypedConstructor - typedDeclarations: List + isParameterNameInCurrentConstructor(String): boolean + codeGenClassWriter(): ClassWriter + toString(): String + hashCode(): int + equals(Object): boolean # canEqual(Object): boolean + isParameterWitNameInCurrentMethod(String): boolean + exitCurrentConstructor(): void + isMethodOfCurrentClass(String): boolean + typeCheck(TypedProgram): Type + getFieldType(String): Type + getMethodType(String): Type + getParameterTypeInCurrentConstructor(String): Type + enterCurrentMethod(TypedMethod): void + getParameterTypeInCurrentMethod(String): Type + enterCurrentConstructor(TypedConstructor): void + codeGen(): byte[] + covertBlocksOfConstructorsAndMethods(TypedProgram, Class): void + convertMethodsAndConstructorsAndFields(TypedProgram, Class): void + isThereField(String): boolean + isParameterWitNameInCurrentConstructor(String): boolean + exitCurrentMethod(): void + checkMethodExists(TypedMethod): void currentConstructorPresent: boolean typedConstructors: List currentMethod: TypedMethod typedMain: TypedMain type: Type typedDeclarations: List currentConstructor: TypedConstructor className: String typedMethods: List currentMainMethodPresent: boolean isMainCurrentMethod: boolean currentMethodPresent: boolean } class TypedConstructor { + TypedConstructor(String, List, TypedBlock, Type, List): + TypedConstructor(): + TypedConstructor(String, List, TypedBlock): + TypedConstructor(Constructor, String): - localVariables: List - name: String - typedBlock: TypedBlock - type: Type - typedParameters: List + toString(): String # canEqual(Object): boolean + hashCode(): int + equals(Object): boolean - checkIfParameterExists(String): void + deleteLocalVariableInConstructor(String): void + isLocalVariablePresent(String): boolean - convertToTypedConstructor(Constructor, String): void + getLocalVariableType(String): Type - convertToTypedParameter(List): void + isParameterPresent(String): boolean + typeCheck(TypedProgram): Type + convertToBlock(TypedProgram, Constructor): void + codeGen(ClassContext): void + isLocalVariableInConstructor(String): boolean localVariables: List name: String typedParameters: List type: Type typedBlock: TypedBlock } class TypedContinue { + TypedContinue(): - type: Type + equals(Object): boolean # canEqual(Object): boolean + hashCode(): int + toString(): String + typeCheck(TypedProgram): Type + codeGen(MethodContext): void type: Type } class TypedDeclaration { + TypedDeclaration(TypedProgram, Declaration): + TypedDeclaration(String, Type): + TypedDeclaration(): - name: String - type: Type + equals(Object): boolean + hashCode(): int + toString(): String + typeCheck(TypedProgram): Type - convertToTypedDeclaration(TypedProgram, Declaration): void + codeGen(ClassWriter): void name: String type: Type } class TypedDoWhile { + TypedDoWhile(TypedBlock, TypedExpression, Type): + TypedDoWhile(TypedProgram, DoWhile): - cond: TypedExpression - type: Type - typedBlock: TypedBlock + equals(Object): boolean # canEqual(Object): boolean + hashCode(): int + toString(): String - convertToTypedDoWhile(TypedProgram, DoWhile): void + typeCheck(TypedProgram): Type + codeGen(MethodContext): void cond: TypedExpression typedBlock: TypedBlock type: Type } interface TypedExpression << interface >> { + codeGen(MethodContext): void type: Type } class TypedExpressionUtil { + TypedExpressionUtil(): + convertExpression(TypedProgram, Expression): TypedExpression } class TypedFieldVarAccess { + TypedFieldVarAccess(Boolean, TypedExpression, String, Type): + TypedFieldVarAccess(): + TypedFieldVarAccess(TypedProgram, FieldVarAccess): - field: Boolean - type: Type - name: String - recursiveOwnerChain: TypedExpression # canEqual(Object): boolean + toString(): String + equals(Object): boolean + hashCode(): int + codeGen(MethodContext): void - checkFieldOrMethodOrRecursiveType(TypedProgram): Type + typeCheck(TypedProgram): Type - checkMethodVariableType(TypedProgram): Type - convertToTypedFieldVarAccess(TypedProgram, FieldVarAccess): void - checkVariableType(TypedProgram): Type - checkConstructorVariableType(TypedProgram): Type - checkFieldOrMethodType(TypedProgram): Type - checkTypeField(TypedProgram): Type name: String type: Type recursiveOwnerChain: TypedExpression field: Boolean } class TypedFor { + TypedFor(): + TypedFor(TypedAssignment, TypedExpression, TypedAssignment, TypedBlock, Type): + TypedFor(TypedProgram, For): - assign: TypedAssignment - typedBlock: TypedBlock - type: Type - cond: TypedExpression - inc: TypedAssignment + hashCode(): int # canEqual(Object): boolean + toString(): String + equals(Object): boolean + codeGen(MethodContext): void - convertToTypedFor(TypedProgram, For): void + typeCheck(TypedProgram): Type inc: TypedAssignment type: Type cond: TypedExpression typedBlock: TypedBlock assign: TypedAssignment } class TypedIfElse { + TypedIfElse(TypedExpression, TypedBlock, TypedBlock, Type): + TypedIfElse(): + TypedIfElse(TypedProgram, IfElse): - typedCon: TypedExpression - elseTypedBlock: TypedBlock - ifTypedBlock: TypedBlock - type: Type + toString(): String + equals(Object): boolean # canEqual(Object): boolean + hashCode(): int + codeGen(MethodContext): void - convertToTypedIfElse(TypedProgram, IfElse): void + typeCheck(TypedProgram): Type elseTypedBlock: TypedBlock type: Type ifTypedBlock: TypedBlock typedCon: TypedExpression } class TypedIntLiteral { + TypedIntLiteral(Integer, Type): + TypedIntLiteral(): + TypedIntLiteral(Integer): + TypedIntLiteral(IntLiteral): - value: Integer - type: Type + equals(Object): boolean # canEqual(Object): boolean + hashCode(): int + toString(): String + codeGen(MethodContext): void + typeCheck(TypedProgram): Type - convertToTypedIntLiteral(IntLiteral): void value: Integer type: Type } class TypedLocalVariable { + TypedLocalVariable(TypedProgram, Declaration): + TypedLocalVariable(String, Type): + TypedLocalVariable(): - type: Type - name: String + typeCheck(TypedProgram): Type + equals(Object): boolean + hashCode(): int + toString(): String + codeGen(MethodVisitor, MethodContext): void - convertToTypedLocalVariable(Declaration): void name: String type: Type } class TypedMain { + TypedMain(Type, TypedMethod): + TypedMain(): - type: Type - typedMethod: TypedMethod + equals(Object): boolean # canEqual(Object): boolean + hashCode(): int + toString(): String + codeGen(ClassContext): void + typeCheck(TypedProgram): Type + convertToTypedMethod(TypedProgram, Class): void typedMethod: TypedMethod type: Type } class TypedMethod { + TypedMethod(String, Type, List, List, TypedBlock): + TypedMethod(): + TypedMethod(TypedProgram, Method): - returnType: Type - typedBlock: TypedBlock - localVariables: List - name: String - typedParameters: List + toString(): String - convertToTypedMethod(TypedProgram, Method): void + equals(Object): boolean + codeGen(ClassContext): void + codeGenMain(ClassContext): void - convertToTypedParameter(List): void - checkReturn(List): boolean + isLocalVariablePresent(String): boolean + isParameterPresent(String): boolean + deleteLocalVariableInMethod(String): void + convertToTypedBlock(TypedProgram, Method): void + isLocalVariableInMethod(String): boolean + typeCheck(TypedProgram): Type + getLocalVariableType(String): Type + checkIfParameterExists(String): void localVariables: List name: String typedParameters: List returnType: Type typedBlock: TypedBlock } class TypedMethodCall { + TypedMethodCall(): + TypedMethodCall(TypedFieldVarAccess, List, Type): + TypedMethodCall(TypedProgram, MethodCall): - recipient: TypedFieldVarAccess - args: List - type: Type + hashCode(): int + equals(Object): boolean + toString(): String # canEqual(Object): boolean + typeCheck(TypedProgram): Type + codeGen(MethodContext): void - getOwnerChain(MethodContext): void + findMatchingMethod(TypedClass, String): Optional - convertToTypedMethodCall(TypedProgram, MethodCall): void recipient: TypedFieldVarAccess args: List type: Type } class TypedNew { + TypedNew(Type, List): + TypedNew(TypedProgram, New): - type: Type - args: List + equals(Object): boolean # canEqual(Object): boolean + hashCode(): int + toString(): String + codeGen(MethodContext): void - convertToTypedNew(TypedProgram, New): void - findMatchingConstructorType(TypedProgram, List): Type + typeCheck(TypedProgram): Type args: List type: Type } interface TypedNode << interface >> { + typeCheck(TypedProgram): Type } class TypedParameter { + TypedParameter(String, Type): + TypedParameter(Parameter): - paraName: String - type: Type + toString(): String + typeCheck(TypedProgram): Type + equals(Object): boolean - convertToTypedParameter(Parameter): void paraName: String type: Type } class TypedPrint { + TypedPrint(TypedProgram, Print): + TypedPrint(TypedExpression, Type): + codeGen(MethodContext): void + typeCheck(TypedProgram): Type } class TypedProgram { + TypedProgram(List, TypedClass): + TypedProgram(Program): - typedClasses: List - currentClass: TypedClass + isTypedClassPresent(String): boolean + toString(): String + getTypeOfFieldNameInClass(String, String): Type + getTypedClass(String): TypedClass + startConversion(Program): void - exitCurrentClass(): void + equals(Object): boolean + isClassWithNamePresent(String): boolean + getTypeOfFieldOrMethodNameInClass(String, String): Type - enterCurrentClass(TypedClass): void currentClass: TypedClass typedClasses: List } class TypedReturn { + TypedReturn(): + TypedReturn(TypedExpression, Type): + TypedReturn(TypedProgram, Return): - ret: TypedExpression - type: Type + equals(Object): boolean # canEqual(Object): boolean + hashCode(): int + toString(): String + codeGen(MethodContext): void + typeCheck(TypedProgram): Type - convertToTypedReturn(TypedProgram, Return): void ret: TypedExpression type: Type } interface TypedStatement << interface >> { + codeGen(MethodContext): void } class TypedUnary { + TypedUnary(UnaryOperator, TypedExpression, Type): + TypedUnary(TypedProgram, Unary): - type: Type - op: UnaryOperator - right: TypedExpression + equals(Object): boolean # canEqual(Object): boolean + hashCode(): int + toString(): String + typeCheck(TypedProgram): Type - convertToTypedUnary(TypedProgram, Unary): void + codeGen(MethodContext): void right: TypedExpression op: UnaryOperator type: Type } class TypedWhile { + TypedWhile(TypedExpression, TypedBlock, Type): + TypedWhile(TypedProgram, While): - type: Type - cond: TypedExpression - typedBlock: TypedBlock + equals(Object): boolean # canEqual(Object): boolean + hashCode(): int + toString(): String + codeGen(MethodContext): void + typeCheck(TypedProgram): Type - convertToTypedWhile(TypedProgram, While): void cond: TypedExpression typedBlock: TypedBlock type: Type } TypedAssignment -[#008200,dashed]u-^ TypedStatement TypedBinary -[#008200,dashed]u-^ TypedExpression TypedBlock -[#008200,dashed]u-^ TypedNode TypedBoolLiteral -[#008200,dashed]u-^ TypedExpression TypedBreak -[#008200,dashed]u-^ TypedStatement TypedCharLiteral -[#008200,dashed]u-^ TypedExpression TypedClass -[#008200,dashed]u-^ TypedNode TypedConstructor -[#008200,dashed]u-^ TypedNode TypedContinue -[#008200,dashed]u-^ TypedStatement TypedDeclaration -[#008200,dashed]u-^ TypedNode TypedDoWhile -[#008200,dashed]u-^ TypedStatement TypedExpression -[#008200,plain]u-^ TypedNode TypedFieldVarAccess -[#008200,dashed]u-^ TypedExpression TypedFor -[#008200,dashed]u-^ TypedStatement TypedIfElse -[#008200,dashed]u-^ TypedStatement TypedIntLiteral -[#008200,dashed]u-^ TypedExpression TypedLocalVariable -[#008200,dashed]u-^ TypedNode TypedMain -[#008200,dashed]u-^ TypedNode TypedMethod -[#008200,dashed]u-^ TypedNode TypedMethodCall -[#008200,dashed]u-^ TypedExpression TypedMethodCall -[#008200,dashed]u-^ TypedStatement TypedNew -[#008200,dashed]u-^ TypedExpression TypedNew -[#008200,dashed]u-^ TypedStatement TypedParameter -[#008200,dashed]u-^ TypedNode TypedPrint -[#008200,dashed]u-^ TypedStatement TypedReturn -[#008200,dashed]u-^ TypedStatement TypedStatement -[#008200,plain]u-^ TypedNode TypedUnary -[#008200,dashed]u-^ TypedExpression TypedWhile -[#008200,dashed]u-^ TypedStatement @enduml ``` --- # Grobe TypedAST Struktur ```plantuml @startuml !theme plain left to right direction skinparam linetype ortho interface TypedExpression << interface >> { + codeGen(MethodContext): void type: Type } interface TypedNode << interface >> { + typeCheck(TypedProgram): Type } interface TypedStatement << interface >> { + codeGen(MethodContext): void } class TypedClass{ + typeCheck(TypedProgram): Type } class TypedWhile{ + typeCheck(TypedProgram): Type } class TypedBinary{ + typeCheck(TypedProgram): Type } TypedExpression -[#008200,plain]r-^ TypedNode TypedStatement -[#008200,plain]l-^ TypedNode TypedWhile -[#008200,dashed]-^ TypedStatement TypedClass -[#008200,dashed]-^ TypedNode TypedBinary -[#008200,dashed]-^ TypedExpression @enduml ``` --- # Phasen der Typisierung - Initisialisierungsphase - Programm -> Klassen (Name, Feld-Variablen, Methoden, Konstruktoren) - Konvertierungsphase - Überführung von untypisierten AST zu typisierten AST - TypeCheck-Phase - Semantische Überprüfung - Ausführung von Blöcken --- ## Konvertierung von untypisierten AST zu typisierten AST ```java public class TypedDeclaration implements TypedNode { private String name; private Type type; ... private void convertToTypedDeclaration(Declaration declaration) { name = declaration.name(); type = declaration.type(); } ``` --- # TypeCheck von While-Statement ```java public class TypedWhile implements TypedStatement { private TypedExpression cond; private TypedBlock typedBlock; private Type type; ... @Override public Type typeCheck(TypedProgram typedProgram) { if (cond.typeCheck(typedProgram) != Type.BOOL) { throw new InvalidWhileConditionException(); } type = typedBlock.typeCheck(typedProgram); return type; } } ``` --- # Speichern von lokalen Variablen - Methoden und Konstruktoren haben jeweils eine Liste von lokalen Variablen ```java public int calculateResult(boolean isMultiple, int x, int y) { int resultat = 0;// add resultat to list if(isMultiple) { int a = x * y;// add a to list resultat = a; }// remove a from list else { int b = x + y;// add b to list resultat = b; } // remove b from list return resultat; } // clear list ``` --- # Code Generierung - Nutzung von ASM - Dynamische Bindung/Polymorphie ```java public class TypedWhile implements TypedStatement { ... @Override public void codeGen(MethodContext ctx) { Label loopStart = new Label(); Label loopEnd = new Label(); ctx.getBreakLabels().push(loopEnd); ctx.getContinueLabels().push(loopStart); ctx.getMv().visitLabel(loopStart); cond.codeGen(ctx); ctx.getMv().visitJumpInsn(Opcodes.IFEQ, loopEnd); ctx.popStack(); typedBlock.codeGen(ctx); ctx.getMv().visitJumpInsn(Opcodes.GOTO, loopStart); ctx.getMv().visitLabel(loopEnd); ctx.getContinueLabels().pop(); ctx.getBreakLabels().pop(); } } ``` --- transition: none --- # Code Generierung - Nutzung von ASM - Dynamische Bindung/Polymorphie ```java public class TypedIntLiteral implements TypedExpression { ... @Override public void codeGen(MethodContext ctx) { if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) { ctx.getMv().visitIntInsn(Opcodes.BIPUSH, value); } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) { ctx.getMv().visitIntInsn(Opcodes.SIPUSH, value); } else { ctx.getMv().visitLdcInsn(value); } ctx.pushInstantToStack(); } } ``` --- ## Context Klassen für Class und Method ```plantuml @startuml top to bottom direction skinparam linetype ortho class ClassContext { + ClassContext(String, ClassWriter): - name: String - cw: ClassWriter - type: Type + hashCode(): int + toString(): String } class MethodContext { + MethodContext(ClassContext, MethodVisitor, Type): - variableIndex: Map - mv: MethodVisitor - stack: Deque - returnType: Type - breakLabels: Deque