Compilerbau2024AbsolutNicht.../presentation/slidev/slides.md
2024-07-04 23:32:17 +02:00

7.9 KiB

theme title class highlighter drawings transition mdc plantUmlServer
dracula Compiler ULTIMATE text-center shiki
persist
false
slide-left true 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

@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<Statement>): 
  + stmts(): List<Statement>
}
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<Declaration>, List<Method>, List<Constructor>): 
  + Class(String, List<Declaration>, List<Method>, List<Constructor>): 
  + mainmeth(): Block
  + classname(): String
  + methods(): List<Method>
  + constructors(): List<Constructor>
  + fieldDeclarations(): List<Declaration>
}
entity Constructor << record >> {
  + Constructor(String, List<Parameter>, Block): 
  + params(): List<Parameter>
  + 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<Parameter>, Block): 
  + block(): Block
  + methodName(): String
  + type(): Type
  + params(): List<Parameter>
}
entity MethodCall << record >> {
  + MethodCall(FieldVarAccess, List<Expression>): 
  + recipient(): FieldVarAccess
  + args(): List<Expression>
}
entity New << record >> {
  + New(Type, List<Expression>): 
  + type(): Type
  + args(): List<Expression>
}
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<Class>): 
  + classes(): List<Class>
}
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

Code Generierung

  • Nutzung von ASM
  • Dynamische Bindung/Polymorphie
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
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


@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<String, LocalVariable>
  - mv: MethodVisitor
  - stack: Deque<Integer>
  - returnType: Type
  - breakLabels: Deque<Label>
  - continueLabels: Deque<Label>
  - classContext: ClassContext
  - maxStack: int
  - localVarIndex: int
  + pushInstantToStack(): void
  + popStack(): void
  + getLocalVar(String): Optional<LocalVariable>
  + registerVariable(String, Type): void
  + pushAnonToStack(): void
  + pushStack(String): void
  + wrapUp(): void
}

@enduml


ASMifier

Tool, um aus Java Bytecode ASM Code zu generieren.

Klick