mirror of
https://github.com/JonathanFleischmann/CompilerULTIMATE.git
synced 2024-12-28 17:08:03 +00:00
Merge branch 'refs/heads/main' into testsuites
This commit is contained in:
commit
fb7a7d8230
@ -3,7 +3,7 @@ grammar Decaf;
|
|||||||
|
|
||||||
class : PUBLIC 'class' id '{' mainmeth? (field | meth | constructor)* '}';
|
class : PUBLIC 'class' id '{' mainmeth? (field | meth | constructor)* '}';
|
||||||
|
|
||||||
field : type id ';';
|
field : PUBLIC? type id ';';
|
||||||
localVar : type id ';';
|
localVar : type id ';';
|
||||||
assignSign : ASSIGN | ADD_ASSIGN | SUB_ASSIGN | MUL_ASSIGN;
|
assignSign : ASSIGN | ADD_ASSIGN | SUB_ASSIGN | MUL_ASSIGN;
|
||||||
returntype : type | VOID;
|
returntype : type | VOID;
|
||||||
@ -20,7 +20,7 @@ block : '{' (localVar | stmt)* '}';
|
|||||||
stmt : 'if' '(' expr ')' block ('else' block)? #If
|
stmt : 'if' '(' expr ')' block ('else' block)? #If
|
||||||
| 'for' '(' assign ';' expr ';' assign ')' block #For
|
| 'for' '(' assign ';' expr ';' assign ')' block #For
|
||||||
| 'while' '(' expr ')' block #While
|
| 'while' '(' expr ')' block #While
|
||||||
| 'do' block 'while' '(' expr ')' #DoWhile
|
| 'do' block 'while' '(' expr ')' ';'? #DoWhile
|
||||||
| 'return' expr ';' #Return
|
| 'return' expr ';' #Return
|
||||||
| 'return' ';' #ReturnVoid
|
| 'return' ';' #ReturnVoid
|
||||||
| 'break' ';' #Break
|
| 'break' ';' #Break
|
||||||
|
@ -17,9 +17,12 @@ public class ASTGenerator {
|
|||||||
declarations = ctx.field().stream().map(ASTGenerator::generateFieldVariable).toList();
|
declarations = ctx.field().stream().map(ASTGenerator::generateFieldVariable).toList();
|
||||||
}
|
}
|
||||||
List<Constructor> constructors = new ArrayList<>();
|
List<Constructor> constructors = new ArrayList<>();
|
||||||
if (ctx.constructor() != null) {
|
if (!ctx.constructor().isEmpty()) {
|
||||||
constructors = ctx.constructor().stream().map(ASTGenerator::generateConstructor).toList();
|
constructors = ctx.constructor().stream().map(ASTGenerator::generateConstructor).toList();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
constructors.add(new Constructor(ctx.id().IDENTIFIER().getText(), List.of(), new Block(List.of(), List.of())));
|
||||||
|
}
|
||||||
List<Method> meths = new ArrayList<>();
|
List<Method> meths = new ArrayList<>();
|
||||||
if (ctx.meth() != null) {
|
if (ctx.meth() != null) {
|
||||||
meths = ctx.meth().stream().map(ASTGenerator::generateMethod).toList();
|
meths = ctx.meth().stream().map(ASTGenerator::generateMethod).toList();
|
||||||
|
@ -13,7 +13,7 @@ import java.io.IOException;
|
|||||||
* Decaf language Compiler
|
* Decaf language Compiler
|
||||||
*/
|
*/
|
||||||
public class Compiler {
|
public class Compiler {
|
||||||
|
/*
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
generateAST("""
|
generateAST("""
|
||||||
public class ClassWithConstructorWithParameters {
|
public class ClassWithConstructorWithParameters {
|
||||||
@ -32,7 +32,7 @@ public class Compiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
}
|
} */
|
||||||
|
|
||||||
public static Class generateAST(String fromSource) {
|
public static Class generateAST(String fromSource) {
|
||||||
CharStream input = CharStreams.fromString(fromSource);
|
CharStream input = CharStreams.fromString(fromSource);
|
||||||
@ -92,7 +92,7 @@ public class Compiler {
|
|||||||
CodeGenUtils.writeClassfile(bytes, classname);
|
CodeGenUtils.writeClassfile(bytes, classname);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// generateByteCodeFileFromFile("src/main/resources/JavaTestfiles/ClassWithConstructor.java", "ClassWithConstructor");
|
generateByteCodeFileFromFile("src/main/resources/JavaTestfiles/ClassCanBeTyped.java", "ClassCanBeTyped");
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,10 +93,12 @@ public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
|
|||||||
recursiveOwnerChain = generateRecursiveOwnerChain(recipientList, null);
|
recursiveOwnerChain = generateRecursiveOwnerChain(recipientList, null);
|
||||||
}
|
}
|
||||||
List<Expression> args = new ArrayList<>();
|
List<Expression> args = new ArrayList<>();
|
||||||
|
if(ctx.methCall().methName().args() != null){
|
||||||
for (var expr : ctx.methCall().methName().args().expr()) {
|
for (var expr : ctx.methCall().methName().args().expr()) {
|
||||||
Expression astExpr = expr.accept(this);
|
Expression astExpr = expr.accept(this);
|
||||||
args.add(astExpr);
|
args.add(astExpr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return new MethodCall(new FieldVarAccess(isField, recursiveOwnerChain, ctx.methCall().methName().id().IDENTIFIER().getText()), args);
|
return new MethodCall(new FieldVarAccess(isField, recursiveOwnerChain, ctx.methCall().methName().id().IDENTIFIER().getText()), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,18 +117,20 @@ public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
|
|||||||
if (ctxList.isEmpty()) {
|
if (ctxList.isEmpty()) {
|
||||||
return recipient;
|
return recipient;
|
||||||
}
|
}
|
||||||
DecafParser.RecipientContext ctx = ctxList.get(0);
|
int lastElement = ctxList.size() - 1;
|
||||||
ctxList.remove(0);
|
DecafParser.RecipientContext ctx = ctxList.get(lastElement);
|
||||||
|
ctxList.remove(lastElement);
|
||||||
if (ctx.id() != null) {
|
if (ctx.id() != null) {
|
||||||
return new FieldVarAccess(false, generateRecursiveOwnerChain(ctxList, recipient), ctx.id().IDENTIFIER().getText());
|
return new FieldVarAccess(false, generateRecursiveOwnerChain(ctxList, recipient), ctx.id().IDENTIFIER().getText());
|
||||||
}
|
}
|
||||||
if (ctx.methName() != null) {
|
if (ctx.methName() != null) {
|
||||||
List<Expression> args = new ArrayList<>();
|
List<Expression> args = new ArrayList<>();
|
||||||
|
if (ctx.methName().args() != null) {
|
||||||
for (var expr : ctx.methName().args().expr()) {
|
for (var expr : ctx.methName().args().expr()) {
|
||||||
Expression astExpr = expr.accept(new ExpressionGenerator());
|
Expression astExpr = expr.accept(new ExpressionGenerator());
|
||||||
args.add(astExpr);
|
args.add(astExpr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return new MethodCall(new FieldVarAccess(false, generateRecursiveOwnerChain(ctxList, recipient), ctx.methName().id().IDENTIFIER().getText()), args);
|
return new MethodCall(new FieldVarAccess(false, generateRecursiveOwnerChain(ctxList, recipient), ctx.methName().id().IDENTIFIER().getText()), args);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ public class StatementGenerator extends DecafBaseVisitor<Statement> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Statement visitReturnVoid(DecafParser.ReturnVoidContext ctx) {
|
public Statement visitReturnVoid(DecafParser.ReturnVoidContext ctx) {
|
||||||
return new ReturnVoid();
|
return new Return(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
|||||||
// Generated from C:/Users/laure/Documents/Dev/Compilerbau/Projekt/CompilerULTIMATE/src/main/antlr/Decaf.g4 by ANTLR 4.13.1
|
// Generated from C:/dev/Pressmium/CompilerULTIMATE/src/main/antlr/Decaf.g4 by ANTLR 4.13.1
|
||||||
package de.maishai.antlr;
|
package de.maishai.antlr;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.ParserRuleContext;
|
import org.antlr.v4.runtime.ParserRuleContext;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Generated from C:/Users/laure/Documents/Dev/Compilerbau/Projekt/CompilerULTIMATE/src/main/antlr/Decaf.g4 by ANTLR 4.13.1
|
// Generated from C:/dev/Pressmium/CompilerULTIMATE/src/main/antlr/Decaf.g4 by ANTLR 4.13.1
|
||||||
package de.maishai.antlr;
|
package de.maishai.antlr;
|
||||||
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
|
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Generated from C:/Users/laure/Documents/Dev/Compilerbau/Projekt/CompilerULTIMATE/src/main/antlr/Decaf.g4 by ANTLR 4.13.1
|
// Generated from C:/dev/Pressmium/CompilerULTIMATE/src/main/antlr/Decaf.g4 by ANTLR 4.13.1
|
||||||
package de.maishai.antlr;
|
package de.maishai.antlr;
|
||||||
import org.antlr.v4.runtime.Lexer;
|
import org.antlr.v4.runtime.Lexer;
|
||||||
import org.antlr.v4.runtime.CharStream;
|
import org.antlr.v4.runtime.CharStream;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Generated from C:/Users/laure/Documents/Dev/Compilerbau/Projekt/CompilerULTIMATE/src/main/antlr/Decaf.g4 by ANTLR 4.13.1
|
// Generated from C:/dev/Pressmium/CompilerULTIMATE/src/main/antlr/Decaf.g4 by ANTLR 4.13.1
|
||||||
package de.maishai.antlr;
|
package de.maishai.antlr;
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
// Generated from C:/Users/laure/Documents/Dev/Compilerbau/Projekt/CompilerULTIMATE/src/main/antlr/Decaf.g4 by ANTLR 4.13.1
|
// Generated from C:/dev/Pressmium/CompilerULTIMATE/src/main/antlr/Decaf.g4 by ANTLR 4.13.1
|
||||||
package de.maishai.antlr;
|
package de.maishai.antlr;
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
|
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
|
||||||
|
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
package de.maishai.ast.records;
|
|
||||||
|
|
||||||
|
|
||||||
public record ReturnVoid() implements Statement {
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package de.maishai.ast.records;
|
package de.maishai.ast.records;
|
||||||
|
|
||||||
public sealed interface Statement extends Node permits Assignment, Break, DoWhile, For, IfElse, MethodCall, New, Return, ReturnVoid, While {
|
public sealed interface Statement extends Node permits Assignment, Break, DoWhile, For, IfElse, MethodCall, New, Return, While {
|
||||||
}
|
}
|
||||||
|
16
src/main/java/de/maishai/typedast/ClassContext.java
Normal file
16
src/main/java/de/maishai/typedast/ClassContext.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package de.maishai.typedast;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ClassContext {
|
||||||
|
private Type name;
|
||||||
|
private ClassWriter cw;
|
||||||
|
|
||||||
|
public ClassContext(String name, ClassWriter cw) {
|
||||||
|
this.name = Type.REFERENCE(name);
|
||||||
|
this.cw = cw;
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,10 @@ import java.util.List;
|
|||||||
public class CodeGenUtils {
|
public class CodeGenUtils {
|
||||||
|
|
||||||
public static String generateDescriptor(List<TypedParameter> arguments, Type returnType) {
|
public static String generateDescriptor(List<TypedParameter> arguments, Type returnType) {
|
||||||
|
if (returnType == null) {
|
||||||
|
returnType = Type.VOID;
|
||||||
|
}
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append('(');
|
builder.append('(');
|
||||||
arguments.forEach(type -> builder.append(type.getType().getDescriptor()));
|
arguments.forEach(type -> builder.append(type.getType().getDescriptor()));
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package de.maishai.typedast.Help;
|
||||||
|
|
||||||
|
import de.maishai.ast.records.*;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
import de.maishai.typedast.TypedExpression;
|
||||||
|
import de.maishai.typedast.typedclass.*;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class TypedExpressionHelp {
|
||||||
|
|
||||||
|
public static TypedExpression convertExpression( TypedClass clas, Expression expression) {
|
||||||
|
if (expression instanceof BoolLiteral boolLiteral) {
|
||||||
|
TypedBoolLiteral typedBoolLiteral = new TypedBoolLiteral( clas, boolLiteral);
|
||||||
|
typedBoolLiteral.typeCheck( clas);
|
||||||
|
return typedBoolLiteral;
|
||||||
|
}
|
||||||
|
else if (expression instanceof CharLiteral charLiteral) {
|
||||||
|
TypedCharLiteral typedCharLiteral = new TypedCharLiteral( clas, charLiteral);
|
||||||
|
typedCharLiteral.typeCheck( clas);
|
||||||
|
return typedCharLiteral;
|
||||||
|
}
|
||||||
|
else if (expression instanceof IntLiteral intLiteral) {
|
||||||
|
TypedIntLiteral typedIntLiteral = new TypedIntLiteral( clas, intLiteral);
|
||||||
|
typedIntLiteral.typeCheck( clas);
|
||||||
|
return typedIntLiteral;
|
||||||
|
}
|
||||||
|
else if (expression instanceof Binary binary) {
|
||||||
|
TypedBinary typedBinary = new TypedBinary( clas, binary);
|
||||||
|
typedBinary.typeCheck( clas);
|
||||||
|
return typedBinary;
|
||||||
|
}
|
||||||
|
else if (expression instanceof FieldVarAccess fieldVarAccess) {
|
||||||
|
TypedFieldVarAccess typedFieldVarAccess = new TypedFieldVarAccess( clas, fieldVarAccess);
|
||||||
|
typedFieldVarAccess.typeCheck( clas);
|
||||||
|
return typedFieldVarAccess;
|
||||||
|
}
|
||||||
|
else if (expression instanceof MethodCall methodCall) {
|
||||||
|
TypedMethodCall typedMethodCall = new TypedMethodCall( clas, methodCall);
|
||||||
|
typedMethodCall.typeCheck( clas);
|
||||||
|
return typedMethodCall;
|
||||||
|
}
|
||||||
|
else if (expression instanceof New newStmt) {
|
||||||
|
TypedNew typedNew = new TypedNew( clas, newStmt);
|
||||||
|
typedNew.typeCheck( clas);
|
||||||
|
return typedNew;
|
||||||
|
}
|
||||||
|
else if (expression instanceof Unary unary) {
|
||||||
|
TypedUnary typedUnary = new TypedUnary( clas, unary);
|
||||||
|
typedUnary.typeCheck( clas);
|
||||||
|
return typedUnary;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,38 +3,70 @@ package de.maishai.typedast;
|
|||||||
import lombok.*;
|
import lombok.*;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
|
||||||
@Data
|
|
||||||
public class MethodContext {
|
public class MethodContext {
|
||||||
|
private record LocalVariable(String name, int index, Type type) {
|
||||||
|
}
|
||||||
|
|
||||||
private Label startLabel;
|
private Label startLabel;
|
||||||
private Label endLabel;
|
private Label endLabel;
|
||||||
private MethodVisitor mv;
|
private MethodVisitor mv;
|
||||||
|
private ClassContext classContext;
|
||||||
private int localVarIndex = 0;
|
private int localVarIndex = 0;
|
||||||
private Map<String, Integer> variableIndex = new HashMap<>();
|
private final Map<String, LocalVariable> variableIndex = new HashMap<>();
|
||||||
|
private Stack<Integer> stack = new Stack<>();
|
||||||
|
private int maxStack = 0;
|
||||||
|
|
||||||
public MethodContext(MethodVisitor mv) {
|
public MethodContext(ClassContext classContext, MethodVisitor mv) {
|
||||||
startLabel = new Label();
|
startLabel = new Label();
|
||||||
endLabel = new Label();
|
endLabel = new Label();
|
||||||
this.mv = mv;
|
this.mv = mv;
|
||||||
|
this.classContext = classContext;
|
||||||
|
registerVariable("this", classContext.getName());
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
mv.visitLabel(startLabel);
|
mv.visitLabel(startLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int addVariable(String name) {
|
public void registerVariable(String name, Type type) {
|
||||||
int index = localVarIndex;
|
int index = localVarIndex;
|
||||||
localVarIndex++;
|
localVarIndex++;
|
||||||
variableIndex.put(name, index);
|
variableIndex.put(name, new LocalVariable(name, index, type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVariableIndex(String name) {
|
||||||
|
int index = variableIndex.get(name).index;
|
||||||
|
if (index == -1) {
|
||||||
|
throw new RuntimeException("Variable not declared");
|
||||||
|
}
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void pushStack(String varName) {
|
||||||
|
stack.push(localVarIndex);
|
||||||
|
if (stack.size() > maxStack) {
|
||||||
|
maxStack = stack.size();
|
||||||
|
}
|
||||||
|
LocalVariable localVariable = variableIndex.get(varName);
|
||||||
|
if (localVariable.type.getKind() == Type.Kind.REFERENCE) {
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, localVariable.index);
|
||||||
|
} else {
|
||||||
|
mv.visitVarInsn(Opcodes.ILOAD, localVariable.index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void popStack() {
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
public void wrapUp() {
|
public void wrapUp() {
|
||||||
mv.visitLabel(endLabel);
|
mv.visitLabel(endLabel);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(maxStack, localVarIndex);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
package de.maishai.typedast;
|
package de.maishai.typedast;
|
||||||
|
|
||||||
public interface TypedExpression extends TypedNode {
|
public interface TypedExpression extends TypedNode {
|
||||||
|
public void codeGen(MethodContext ctx);
|
||||||
|
|
||||||
|
public Type getType();
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,6 @@ package de.maishai.typedast;
|
|||||||
|
|
||||||
import de.maishai.typedast.typedclass.TypedClass;
|
import de.maishai.typedast.typedclass.TypedClass;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public interface TypedNode {
|
public interface TypedNode {
|
||||||
Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes);
|
Type typeCheck(TypedClass clas);
|
||||||
TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST);
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package de.maishai.typedast;
|
package de.maishai.typedast;
|
||||||
|
|
||||||
import org.objectweb.asm.MethodVisitor;
|
|
||||||
|
|
||||||
public interface TypedStatement extends TypedNode {
|
public interface TypedStatement extends TypedNode {
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx);
|
public void codeGen(MethodContext ctx);
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,58 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
import de.maishai.ast.records.Assignment;
|
import de.maishai.ast.records.Assignment;
|
||||||
|
import de.maishai.ast.records.Expression;
|
||||||
import de.maishai.typedast.MethodContext;
|
import de.maishai.typedast.MethodContext;
|
||||||
import de.maishai.typedast.TypedExpression;
|
import de.maishai.typedast.TypedExpression;
|
||||||
import de.maishai.typedast.TypedNode;
|
|
||||||
import de.maishai.typedast.TypedStatement;
|
import de.maishai.typedast.TypedStatement;
|
||||||
import de.maishai.typedast.Type;
|
import de.maishai.typedast.Type;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class TypedAssignment implements TypedStatement {
|
public class TypedAssignment implements TypedStatement {
|
||||||
private String varName;
|
|
||||||
private TypedExpression value;
|
private TypedExpression value;
|
||||||
|
private TypedFieldVarAccess location;
|
||||||
private Type type;
|
private Type type;
|
||||||
@Override
|
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
public TypedAssignment(TypedClass clas, Assignment untyped) {
|
||||||
if (!localVar.containsKey(varName)) {
|
convertToTypedAssignment(clas, untyped);
|
||||||
throw new RuntimeException("Variable not declared");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Type typeLeft = localVar.get(varName);
|
public void convertToTypedAssignment(TypedClass clas, Assignment untyped) {
|
||||||
Type typeRight = value.typeCheck(localVar, classes);
|
value = convertExpression(clas, untyped.value());
|
||||||
|
location = new TypedFieldVarAccess(clas, untyped.location());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type typeCheck(TypedClass clas) {
|
||||||
|
Type typeLeft = null;
|
||||||
|
|
||||||
|
if (clas.isThereField(location.getName())) {
|
||||||
|
typeLeft = clas.getFieldType(location.getName());
|
||||||
|
} else {
|
||||||
|
if (clas.isCurrentMethodPresent() && !clas.isCurrentConstructorPresent()) {
|
||||||
|
if (clas.getCurrentMethod().isLocalVariableInMethod(location.getName())) {
|
||||||
|
typeLeft = clas.getCurrentMethod().getLocalVariableType(location.getName());
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Variable " + location.getName() + " not declared in method");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!clas.isCurrentMethodPresent() && clas.isCurrentConstructorPresent()) {
|
||||||
|
if (clas.getCurrentConstructor().isLocalVariableInConstructor(location.getName())) {
|
||||||
|
typeLeft = clas.getCurrentConstructor().getLocalVariableType(location.getName());
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Variable " + location.getName() + " not declared in constructor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Type typeRight = value.typeCheck(clas);
|
||||||
|
|
||||||
if (typeLeft.equals(typeRight)) {
|
if (typeLeft.equals(typeRight)) {
|
||||||
type = typeLeft;
|
type = typeLeft;
|
||||||
@ -33,16 +62,10 @@ public class TypedAssignment implements TypedStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public void codeGen(MethodContext ctx) {
|
||||||
Assignment untyped = (Assignment) unTypedAST;
|
if (value instanceof TypedIntLiteral) {
|
||||||
TypedAssignment typedAssignment = new TypedAssignment();
|
ctx.getMv().visitIntInsn(Opcodes.BIPUSH, ((TypedIntLiteral) value).getValue());
|
||||||
typedAssignment.setVarName(untyped.location().id());
|
ctx.getMv().visitVarInsn(Opcodes.ISTORE, ctx.getLocalVarIndex());
|
||||||
typedAssignment.setValue((TypedExpression) value.convertToTypedAST(localVar, classes, untyped.value()));
|
}
|
||||||
return typedAssignment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,59 +2,72 @@ package de.maishai.typedast.typedclass;
|
|||||||
|
|
||||||
import de.maishai.ast.Operator;
|
import de.maishai.ast.Operator;
|
||||||
import de.maishai.ast.records.Binary;
|
import de.maishai.ast.records.Binary;
|
||||||
|
import de.maishai.typedast.MethodContext;
|
||||||
import de.maishai.typedast.TypedExpression;
|
import de.maishai.typedast.TypedExpression;
|
||||||
import de.maishai.typedast.TypedNode;
|
|
||||||
import de.maishai.typedast.Type;
|
import de.maishai.typedast.Type;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
public class TypedBinary implements TypedExpression {
|
public class TypedBinary implements TypedExpression {
|
||||||
private TypedExpression left;
|
private TypedExpression left;
|
||||||
private Operator op;
|
private Operator op;
|
||||||
private TypedExpression right;
|
private TypedExpression right;
|
||||||
private Type type;
|
private Type type;
|
||||||
|
|
||||||
|
public TypedBinary(TypedClass clas, Binary unTypedBinary) {
|
||||||
|
convertToTypedBinary(clas, unTypedBinary);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToTypedBinary(TypedClass clas, Binary unTypedBinary) {
|
||||||
|
left = convertExpression(clas, unTypedBinary.left());
|
||||||
|
right = convertExpression(clas, unTypedBinary.right());
|
||||||
|
op = unTypedBinary.op();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
|
Type leftType = left.typeCheck(clas);
|
||||||
|
Type rightType = right.typeCheck(clas);
|
||||||
|
|
||||||
if (op == Operator.ADD || op == Operator.SUB || op == Operator.MUL) {
|
if (op == Operator.ADD || op == Operator.SUB || op == Operator.MUL) {
|
||||||
if (left.typeCheck(localVar, classes) == Type.INT &&
|
if (leftType == Type.INT && rightType == Type.INT) {
|
||||||
right.typeCheck(localVar, classes) == Type.INT) {
|
|
||||||
type = Type.INT;
|
type = Type.INT;
|
||||||
return Type.INT;
|
return Type.INT;
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Type mismatch");
|
throw new RuntimeException("Type mismatch in " + op);
|
||||||
}
|
}
|
||||||
}else if(op == Operator.GT || op == Operator.LT || op == Operator.GE || op == Operator.LE || op == Operator.EQ || op == Operator.NE || op == Operator.AND || op == Operator.OR) {
|
} else if (op == Operator.GT || op == Operator.LT || op == Operator.GE || op == Operator.LE) {
|
||||||
if (left.typeCheck(localVar, classes) == Type.INT &&
|
if (leftType == Type.INT && rightType == Type.INT) {
|
||||||
right.typeCheck(localVar, classes) == Type.INT) {
|
|
||||||
type = Type.BOOL;
|
type = Type.BOOL;
|
||||||
return Type.BOOL;
|
return Type.BOOL;
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Type mismatch");
|
throw new RuntimeException("Type mismatch in " + op);
|
||||||
}
|
}
|
||||||
} else if (op == Operator.AND || op == Operator.OR) {
|
} else if (op == Operator.AND || op == Operator.OR) {
|
||||||
if (left.typeCheck(localVar, classes) == Type.BOOL &&
|
if (leftType == Type.BOOL && rightType == Type.BOOL) {
|
||||||
right.typeCheck(localVar, classes) == Type.BOOL) {
|
|
||||||
type = Type.BOOL;
|
type = Type.BOOL;
|
||||||
return Type.BOOL;
|
return Type.BOOL;
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Type mismatch");
|
throw new RuntimeException("Type mismatch in " + op);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
throw new RuntimeException("Invalid operator");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (leftType == rightType && leftType != Type.VOID) {
|
||||||
|
type = rightType;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Void can not be compared with Void");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public void codeGen(MethodContext ctx) {
|
||||||
Binary binary = (Binary) unTypedAST;
|
|
||||||
|
|
||||||
TypedBinary typedBinary = new TypedBinary();
|
|
||||||
typedBinary.setLeft((TypedExpression) this.left.convertToTypedAST(localVar, classes, binary.left()));
|
|
||||||
typedBinary.setOp(binary.op());
|
|
||||||
typedBinary.setRight((TypedExpression) this.right.convertToTypedAST(localVar, classes, binary.right()));
|
|
||||||
|
|
||||||
return typedBinary;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,159 +1,128 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
import de.maishai.ast.records.*;
|
import de.maishai.ast.records.*;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.MethodContext;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
import de.maishai.typedast.TypedNode;
|
||||||
|
import de.maishai.typedast.TypedStatement;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
@Data
|
@Data
|
||||||
public class TypedBlock implements TypedNode {
|
public class TypedBlock implements TypedNode {
|
||||||
private List<TypedLocalVariable> vars;
|
private List<TypedLocalVariable> vars = new ArrayList<>();
|
||||||
private List<TypedStatement> stmts;
|
private List<TypedStatement> stmts = new ArrayList<>();
|
||||||
|
private Type type;
|
||||||
|
|
||||||
|
|
||||||
|
public TypedBlock(TypedClass clas, Block unTypedBlock) {
|
||||||
public TypedBlock unTypedBlockToTypedBlock(Block unTypedBlock) {
|
convertToTypedBlock(clas, unTypedBlock);
|
||||||
|
|
||||||
TypedBlock typedBlock = new TypedBlock();
|
|
||||||
typedBlock.setStmts(new ArrayList<>());
|
|
||||||
typedBlock.setVars(new ArrayList<>());
|
|
||||||
|
|
||||||
if(unTypedBlock.localVariables().isEmpty()){
|
|
||||||
typedBlock.setVars(List.of());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(unTypedBlock.stmts().isEmpty()){
|
public TypedBlock(List<TypedLocalVariable> vars, List<TypedStatement> stmts) {
|
||||||
typedBlock.setStmts(List.of());
|
this.vars = vars;
|
||||||
|
this.stmts = stmts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToTypedBlock(TypedClass clas, Block unTypedBlock) {
|
||||||
|
|
||||||
|
if (unTypedBlock == null) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Declaration var : unTypedBlock.localVariables()) {
|
for (Declaration var : unTypedBlock.localVariables()) {
|
||||||
TypedLocalVariable typedVar = new TypedLocalVariable();
|
vars.add(new TypedLocalVariable(clas, var));
|
||||||
typedVar.setName(var.name());
|
|
||||||
typedVar.setType(var.type());
|
|
||||||
typedBlock.getVars().add(typedVar);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var stmt : unTypedBlock.stmts()) {
|
for (var stmt : unTypedBlock.stmts()) {
|
||||||
|
|
||||||
if (stmt instanceof Assignment assignment) {
|
if (stmt instanceof Assignment assignment) {
|
||||||
TypedAssignment typedAssignment = new TypedAssignment();
|
TypedAssignment typedAssignment = new TypedAssignment(clas, assignment);
|
||||||
typedAssignment.setVarName(assignment.location().id());
|
typedAssignment.typeCheck(clas);
|
||||||
typedAssignment.setValue(null);
|
stmts.add(typedAssignment);
|
||||||
typedBlock.getStmts().add(typedAssignment);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (stmt instanceof For forStmt) {
|
if (stmt instanceof For forStmt) {
|
||||||
TypedFor typedFor = new TypedFor();
|
TypedFor typedFor = new TypedFor(clas, forStmt);
|
||||||
TypedBlock typedBlock1 = new TypedBlock();
|
typedFor.typeCheck(clas);
|
||||||
typedFor.setTypedBlock(typedBlock1.unTypedBlockToTypedBlock((forStmt.block())));
|
stmts.add(typedFor);
|
||||||
typedFor.setAssign(null);
|
|
||||||
typedFor.setCond(null);
|
|
||||||
typedFor.setInc(null);
|
|
||||||
typedBlock.getStmts().add(typedFor);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (stmt instanceof IfElse ifElse) {
|
if (stmt instanceof IfElse ifElse) {
|
||||||
TypedIfElse typedIfElse = new TypedIfElse();
|
TypedIfElse typedIfElse = new TypedIfElse(clas, ifElse);
|
||||||
TypedBlock typedBlockIf = new TypedBlock();
|
typedIfElse.typeCheck(clas);
|
||||||
TypedBlock typedBlockElse = new TypedBlock();
|
stmts.add(typedIfElse);
|
||||||
typedIfElse.setIfTypedBlock(typedBlockIf.unTypedBlockToTypedBlock(ifElse.ifBlock()));
|
|
||||||
typedIfElse.setElseTypedBlock(typedBlockElse.unTypedBlockToTypedBlock(ifElse.elseBlock()));
|
|
||||||
typedIfElse.setTypedCon(null);
|
|
||||||
typedBlock.getStmts().add(typedIfElse);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(stmt instanceof MethodCall methodCall){
|
|
||||||
TypedMethodCall typedMethodCall = new TypedMethodCall();
|
|
||||||
typedMethodCall.setArgs(null);
|
|
||||||
typedMethodCall.setRecipient(null);
|
|
||||||
typedBlock.getStmts().add(typedMethodCall);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(stmt instanceof New newStmt){
|
|
||||||
TypedNew typedNew = new TypedNew();
|
|
||||||
typedNew.setArgs(null);
|
|
||||||
typedNew.setType(newStmt.type());
|
|
||||||
typedBlock.getStmts().add(typedNew);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(stmt instanceof Return returnStmt){
|
|
||||||
TypedReturn typedReturn = new TypedReturn();
|
|
||||||
typedReturn.setRet(null);
|
|
||||||
typedBlock.getStmts().add(typedReturn);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (stmt instanceof While whileStmt) {
|
if (stmt instanceof While whileStmt) {
|
||||||
TypedWhile typedWhile = new TypedWhile();
|
TypedWhile typedWhile = new TypedWhile(clas, whileStmt);
|
||||||
TypedBlock typedBlock1 = new TypedBlock();
|
typedWhile.typeCheck(clas);
|
||||||
typedWhile.setTypedBlock(typedBlock1.unTypedBlockToTypedBlock(whileStmt.block()));
|
stmts.add(typedWhile);
|
||||||
typedWhile.setCond(null);
|
|
||||||
typedBlock.getStmts().add(typedWhile);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (stmt instanceof DoWhile doWhile) {
|
if (stmt instanceof DoWhile doWhile) {
|
||||||
TypedDoWhile typedDoWhile = new TypedDoWhile();
|
TypedDoWhile typedDoWhile = new TypedDoWhile(clas, doWhile);
|
||||||
TypedBlock typedBlock1 = new TypedBlock();
|
typedDoWhile.typeCheck(clas);
|
||||||
typedDoWhile.setTypedBlock(typedBlock1.unTypedBlockToTypedBlock(doWhile.block()));
|
stmts.add(typedDoWhile);
|
||||||
typedDoWhile.setCond(null);
|
|
||||||
typedBlock.getStmts().add(typedDoWhile);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (stmt instanceof Return returnStmt) {
|
||||||
|
TypedReturn typedReturn = new TypedReturn(clas, returnStmt);
|
||||||
|
typedReturn.typeCheck(clas);
|
||||||
|
stmts.add(typedReturn);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (stmt instanceof New newStmt) {
|
||||||
|
TypedNew typedNew = new TypedNew(clas, newStmt);
|
||||||
|
typedNew.typeCheck(clas);
|
||||||
|
stmts.add(typedNew);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (stmt instanceof Break) {
|
if (stmt instanceof Break) {
|
||||||
TypedBreak typedBreak = new TypedBreak();
|
stmts.add(new TypedBreak());
|
||||||
typedBlock.getStmts().add(typedBreak);
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stmt instanceof MethodCall methodCall) {
|
||||||
|
TypedMethodCall typedMethodCall = new TypedMethodCall(clas, methodCall);
|
||||||
|
typedMethodCall.typeCheck(clas);
|
||||||
|
stmts.add(typedMethodCall);
|
||||||
}
|
}
|
||||||
//System.out.println("stmts:" + typedBlock.getStmts().toString());
|
|
||||||
|
|
||||||
return typedBlock;
|
|
||||||
}
|
}
|
||||||
@Override
|
this.typeCheck(clas);
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
|
||||||
Type typeOfLastStmt = Type.VOID;
|
|
||||||
for (TypedLocalVariable var : vars) {
|
|
||||||
var.typeCheck(localVar, classes);
|
|
||||||
}
|
|
||||||
for (TypedStatement stmt : stmts) {
|
|
||||||
stmt.typeCheck(localVar, classes);
|
|
||||||
typeOfLastStmt = stmt.typeCheck(localVar, classes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return typeOfLastStmt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
Block untyped = (Block) unTypedAST;
|
Type chekType = null;
|
||||||
TypedBlock typedBlock = new TypedBlock();
|
for (TypedStatement stmt : stmts) {
|
||||||
typedBlock.setStmts(new ArrayList<>());
|
stmt.typeCheck(clas);
|
||||||
typedBlock.setVars(new ArrayList<>());
|
if(stmt instanceof TypedReturn returnStmt) {
|
||||||
|
chekType = returnStmt.getType();
|
||||||
for (Declaration var : untyped.localVariables()) {
|
|
||||||
TypedLocalVariable typedVar = new TypedLocalVariable();
|
|
||||||
typedVar.setName(var.name());
|
|
||||||
typedVar.setType(var.type());
|
|
||||||
typedBlock.getVars().add(typedVar);
|
|
||||||
}
|
}
|
||||||
typedBlock.getStmts().add((TypedStatement) untyped.stmts());
|
|
||||||
int i = 0;
|
|
||||||
for(var stmt : untyped.stmts()){
|
|
||||||
System.out.println(i++ +" :" + stmt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return typedBlock;
|
if(chekType == null) {
|
||||||
|
chekType = Type.VOID;
|
||||||
|
}
|
||||||
|
type = chekType;
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
for (TypedLocalVariable var : vars) {
|
for (TypedLocalVariable var : vars) {
|
||||||
var.codeGen(mv, ctx);
|
//var.codeGen(ctx);
|
||||||
}
|
}
|
||||||
for (TypedStatement stmt : stmts) {
|
for (TypedStatement stmt : stmts) {
|
||||||
stmt.codeGen(mv, ctx);
|
stmt.codeGen(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,46 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
import de.maishai.ast.records.BoolLiteral;
|
import de.maishai.ast.records.BoolLiteral;
|
||||||
|
import de.maishai.ast.records.Node;
|
||||||
|
import de.maishai.typedast.MethodContext;
|
||||||
import de.maishai.typedast.TypedExpression;
|
import de.maishai.typedast.TypedExpression;
|
||||||
import de.maishai.typedast.TypedNode;
|
import de.maishai.typedast.TypedNode;
|
||||||
import de.maishai.typedast.Type;
|
import de.maishai.typedast.Type;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
public class TypedBoolLiteral implements TypedExpression {
|
public class TypedBoolLiteral implements TypedExpression {
|
||||||
|
|
||||||
private Boolean value;
|
private Boolean value;
|
||||||
private Type type;
|
private Type type;
|
||||||
@Override
|
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
|
||||||
|
public TypedBoolLiteral(TypedClass clas, BoolLiteral unTypedBoolLiteral) {
|
||||||
|
convertToTypedBoolLiteral(clas, unTypedBoolLiteral);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToTypedBoolLiteral(TypedClass clas, BoolLiteral unTypedBoolLiteral) {
|
||||||
|
value = unTypedBoolLiteral.value();
|
||||||
type = Type.BOOL;
|
type = Type.BOOL;
|
||||||
return Type.BOOL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
BoolLiteral untyped = (BoolLiteral) unTypedAST;
|
return type;
|
||||||
TypedBoolLiteral typedBoolLiteral = new TypedBoolLiteral();
|
|
||||||
typedBoolLiteral.setValue(untyped.value());
|
|
||||||
return typedBoolLiteral;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void codeGen(MethodContext ctx) {
|
||||||
|
if(value){
|
||||||
|
ctx.getMv().visitInsn(Opcodes.ICONST_1);
|
||||||
|
}else{
|
||||||
|
ctx.getMv().visitInsn(Opcodes.ICONST_0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
import de.maishai.ast.records.Break;
|
import de.maishai.ast.records.Break;
|
||||||
|
import de.maishai.ast.records.Node;
|
||||||
import de.maishai.typedast.MethodContext;
|
import de.maishai.typedast.MethodContext;
|
||||||
import de.maishai.typedast.TypedNode;
|
import de.maishai.typedast.TypedNode;
|
||||||
import de.maishai.typedast.TypedStatement;
|
import de.maishai.typedast.TypedStatement;
|
||||||
@ -9,24 +10,22 @@ import lombok.Data;
|
|||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class TypedBreak implements TypedStatement {
|
public class TypedBreak implements TypedStatement {
|
||||||
@Override
|
private Type type = Type.VOID;
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
|
||||||
return Type.VOID;
|
public TypedBreak convertToTypedBreak(TypedClass clas, Break unTypedBreak) {
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
Break untyped = (Break) unTypedAST;
|
return type;
|
||||||
if(untyped == null) {
|
|
||||||
throw new RuntimeException("Break not found");
|
|
||||||
}
|
|
||||||
return new TypedBreak();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,38 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
import de.maishai.ast.records.CharLiteral;
|
import de.maishai.ast.records.CharLiteral;
|
||||||
|
import de.maishai.ast.records.Node;
|
||||||
|
import de.maishai.typedast.MethodContext;
|
||||||
import de.maishai.typedast.TypedExpression;
|
import de.maishai.typedast.TypedExpression;
|
||||||
import de.maishai.typedast.TypedNode;
|
import de.maishai.typedast.TypedNode;
|
||||||
import de.maishai.typedast.Type;
|
import de.maishai.typedast.Type;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class TypedCharLiteral implements TypedExpression {
|
public class TypedCharLiteral implements TypedExpression {
|
||||||
private char value;
|
private char value;
|
||||||
@Override
|
private Type type;
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
|
||||||
return Type.CHAR;
|
public TypedCharLiteral(TypedClass clas, CharLiteral unTypedCharLiteral) {
|
||||||
|
convertToCharLiteral(clas, unTypedCharLiteral);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToCharLiteral(TypedClass clas, CharLiteral unTypedCharLiteral) {
|
||||||
|
value = unTypedCharLiteral.value();
|
||||||
|
type = Type.CHAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
CharLiteral untyped = (CharLiteral) unTypedAST;
|
return type;
|
||||||
TypedCharLiteral typedCharLiteral = new TypedCharLiteral();
|
}
|
||||||
typedCharLiteral.setValue(untyped.value());
|
|
||||||
return typedCharLiteral;
|
|
||||||
|
@Override
|
||||||
|
public void codeGen(MethodContext ctx) {
|
||||||
|
ctx.getMv().visitLdcInsn(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
|
import de.maishai.ast.Operator;
|
||||||
|
import de.maishai.ast.records.*;
|
||||||
import de.maishai.ast.records.Class;
|
import de.maishai.ast.records.Class;
|
||||||
import de.maishai.ast.records.Constructor;
|
import de.maishai.typedast.ClassContext;
|
||||||
import de.maishai.ast.records.Declaration;
|
|
||||||
import de.maishai.ast.records.Method;
|
|
||||||
import de.maishai.typedast.CodeGenUtils;
|
import de.maishai.typedast.CodeGenUtils;
|
||||||
import de.maishai.typedast.Type;
|
import de.maishai.typedast.Type;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@ -23,77 +23,196 @@ import java.util.Map;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class TypedClass implements TypedNode {
|
public class TypedClass implements TypedNode {
|
||||||
private String className;
|
private String className;
|
||||||
private List<TypedField> typedFields;
|
private List<TypedDeclaration> typedDeclarations = new ArrayList<>();
|
||||||
private List<TypedMethod> typedMethods;
|
private List<TypedMethod> typedMethods = new ArrayList<>();
|
||||||
private List<TypedConstructor> typedConstructors;
|
private List<TypedConstructor> typedConstructors = new ArrayList<>();
|
||||||
|
private TypedMethod currentMethod;
|
||||||
|
private TypedConstructor currentConstructor;
|
||||||
|
private Type type;
|
||||||
|
|
||||||
@Override
|
public TypedClass(Class c) {
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
convertToTypedClass(c);
|
||||||
|
|
||||||
if (classes.containsKey(className)) {
|
|
||||||
throw new RuntimeException("Class " + className + " already exists");
|
|
||||||
}
|
|
||||||
classes.put(className, this);
|
|
||||||
for (TypedField field : typedFields) {
|
|
||||||
field.typeCheck(localVar, classes);
|
|
||||||
}
|
|
||||||
for(TypedConstructor constructor : typedConstructors) {
|
|
||||||
constructor.typeCheck(localVar, classes);
|
|
||||||
}
|
|
||||||
for (TypedMethod typedMethod : typedMethods) {
|
|
||||||
typedMethod.typeCheck(localVar, classes);
|
|
||||||
}
|
|
||||||
return Type.REFERENCE(className);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypedNode startConversion(de.maishai.ast.records.Class c) {
|
public void enterCurrentMethod(TypedMethod method) {
|
||||||
Map<String, Type> local = new HashMap<>();
|
currentMethod = method;
|
||||||
Map<String, TypedClass> classMap = new HashMap<>();
|
|
||||||
|
|
||||||
return convertToTypedAST(local, classMap, c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void exitCurrentMethod() {
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
currentMethod = null;
|
||||||
TypedClass typedClass = new TypedClass();
|
|
||||||
Class c = (Class) unTypedAST;
|
|
||||||
typedClass.setClassName(c.classname());
|
|
||||||
typedClass.setTypedFields(new ArrayList<>());
|
|
||||||
typedClass.setTypedMethods(new ArrayList<>());
|
|
||||||
typedClass.setTypedConstructors(new ArrayList<>());
|
|
||||||
|
|
||||||
for (Declaration field : c.fieldDeclarations()) {
|
|
||||||
TypedField typedField = new TypedField();
|
|
||||||
typedClass.getTypedFields().add(typedField.unTypedFieldToTypedField(field));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void enterCurrentConstructor(TypedConstructor constructor) {
|
||||||
|
currentConstructor = constructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exitCurrentConstructor() {
|
||||||
|
currentConstructor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCurrentMethodPresent() {
|
||||||
|
return currentMethod != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCurrentConstructorPresent() {
|
||||||
|
return currentConstructor != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isParameterNameInCurrentMethod(String parameterName) {
|
||||||
|
if (currentMethod == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (TypedParameter p : currentMethod.getTypedParameters()) {
|
||||||
|
if (p.getParaName().equals(parameterName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isParameterNameInCurrentConstructor(String parameterName) {
|
||||||
|
if (currentConstructor == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (TypedParameter p : currentConstructor.getTypedParameters()) {
|
||||||
|
if (p.getParaName().equals(parameterName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToTypedClass(Class c) {
|
||||||
|
className = c.classname();
|
||||||
|
type = Type.REFERENCE(className);
|
||||||
|
|
||||||
|
// Am Anfang werden die Attribute, die Konstruktoren und Methoden in die jeweilige Liste eingefügt.
|
||||||
|
// damit die Methoden verwendet werden können, bevor deren Blöcke ausgeführt werden
|
||||||
|
for (Declaration declaration : c.fieldDeclarations()) {
|
||||||
|
typedDeclarations.add(new TypedDeclaration(this, declaration));
|
||||||
|
}
|
||||||
|
for (Constructor constructor : c.constructors()) {
|
||||||
|
typedConstructors.add(new TypedConstructor(this, constructor));
|
||||||
|
}
|
||||||
|
|
||||||
for (Method method : c.methods()) {
|
for (Method method : c.methods()) {
|
||||||
TypedMethod typedMethod = new TypedMethod();
|
typedMethods.add(new TypedMethod(this, method));
|
||||||
typedClass.getTypedMethods().add(typedMethod.unTypedMethodToTypedMethod(method));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hier werden die Blöcke der Konstruktoren ausgeführt
|
||||||
|
int i = 0;
|
||||||
for (Constructor constructor : c.constructors()) {
|
for (Constructor constructor : c.constructors()) {
|
||||||
TypedConstructor typedConstructor = new TypedConstructor();
|
enterCurrentConstructor(typedConstructors.get(i));
|
||||||
typedClass.getTypedConstructors().add(typedConstructor.unTypedContructorToTypedConstructor(constructor));
|
typedConstructors.get(i).convertToBlock(this, constructor);
|
||||||
|
exitCurrentConstructor();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
// Hier werden die Blöcke der Methoden ausgeführt
|
||||||
|
int j = 0;
|
||||||
|
for (Method method : c.methods()) {
|
||||||
|
enterCurrentMethod(typedMethods.get(j));
|
||||||
|
typedMethods.get(j).convertToTypedBlock(this, method);
|
||||||
|
exitCurrentMethod();
|
||||||
|
j++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return typedClass;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type typeCheck(TypedClass clas) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypedNode startConversion(Class c) {
|
||||||
|
Map<String, Type> local = new HashMap<>();
|
||||||
|
|
||||||
|
return new TypedClass(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isParameterWitNameInMethod(String parameterName) {
|
||||||
|
for (TypedMethod m : typedMethods) {
|
||||||
|
for (TypedParameter p : m.getTypedParameters()) {
|
||||||
|
if (p.getParaName().equals(parameterName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isParameterWitNameInConstructor(String parameterName) {
|
||||||
|
for (TypedConstructor c : typedConstructors) {
|
||||||
|
for (TypedParameter p : c.getTypedParameters()) {
|
||||||
|
if (p.getParaName().equals(parameterName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getParameterTypeInCurrentMethod(String parameterName) {
|
||||||
|
for (TypedMethod m : typedMethods) {
|
||||||
|
for (TypedParameter p : m.getTypedParameters()) {
|
||||||
|
if (p.getParaName().equals(parameterName)) {
|
||||||
|
return p.getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getParameterTypeInCurrentConstructor(String parameterName) {
|
||||||
|
for (TypedParameter p : currentConstructor.getTypedParameters()) {
|
||||||
|
if (p.getParaName().equals(parameterName)) {
|
||||||
|
return p.getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isThereField(String fieldName) {
|
||||||
|
for (TypedDeclaration f : typedDeclarations) {
|
||||||
|
if (f.getName().equals(fieldName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getFieldType(String fieldName) {
|
||||||
|
for (TypedDeclaration f : typedDeclarations) {
|
||||||
|
if (f.getName().equals(fieldName)) {
|
||||||
|
return f.getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getMethodType(String methodName) {
|
||||||
|
for (TypedMethod m : typedMethods) {
|
||||||
|
if (m.getName().equals(methodName)) {
|
||||||
|
return m.getReturnType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public byte[] codeGen() {
|
public byte[] codeGen() {
|
||||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||||
|
ClassContext ctx = new ClassContext(className, cw);
|
||||||
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", null);
|
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", null);
|
||||||
for (TypedField field : typedFields) {
|
for (TypedDeclaration declaration : typedDeclarations) {
|
||||||
field.codeGen(cw);
|
declaration.codeGen(cw);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TypedConstructor constructor : typedConstructors) {
|
for (TypedConstructor constructor : typedConstructors) {
|
||||||
constructor.codeGen(cw);
|
constructor.codeGen(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TypedMethod m : typedMethods) {
|
for (TypedMethod m : typedMethods) {
|
||||||
//m.codeGen(cw);
|
m.codeGen(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cw.toByteArray();
|
return cw.toByteArray();
|
||||||
@ -105,16 +224,28 @@ public class TypedClass implements TypedNode {
|
|||||||
c.setClassName("SomeClass");
|
c.setClassName("SomeClass");
|
||||||
|
|
||||||
//Fields
|
//Fields
|
||||||
TypedField f1 = new TypedField("someNumber", Type.INT);
|
TypedDeclaration f1 = new TypedDeclaration("someNumber", Type.INT);
|
||||||
TypedField f2 = new TypedField("someChar", Type.CHAR);
|
TypedDeclaration f2 = new TypedDeclaration("someChar", Type.CHAR);
|
||||||
c.typedFields = List.of(f1, f2);
|
c.typedDeclarations = List.of(f1, f2);
|
||||||
|
|
||||||
//Constructors
|
//Constructors
|
||||||
TypedConstructor constructor = new TypedConstructor( "SomeClass", List.of(new TypedParameter("test", Type.INT)), new TypedBlock());
|
TypedConstructor constructor = new TypedConstructor("SomeClass", List.of(new TypedParameter("test", Type.INT)), new TypedBlock(new ArrayList<>(), new ArrayList<>()));
|
||||||
c.typedConstructors = List.of(constructor);
|
c.typedConstructors = List.of(constructor);
|
||||||
|
|
||||||
//Methods
|
//Methods
|
||||||
c.typedMethods = new ArrayList<>();
|
c.typedMethods = new ArrayList<>();
|
||||||
|
TypedMethod m = new TypedMethod();
|
||||||
|
m.setName("someMethod");
|
||||||
|
m.setReturnType(Type.INT);
|
||||||
|
m.setTypedParameters(List.of(new TypedParameter("test", Type.INT)));
|
||||||
|
TypedIfElse ifs = new TypedIfElse();
|
||||||
|
TypedBinary cond = new TypedBinary();
|
||||||
|
cond.setOp(Operator.GT);
|
||||||
|
//cond.setLeft(??);
|
||||||
|
cond.setRight(new TypedIntLiteral(12));
|
||||||
|
ifs.setTypedCon(cond);
|
||||||
|
m.setTypedBlock(new TypedBlock(List.of(), List.of(ifs, new TypedReturn())));
|
||||||
|
c.typedMethods.add(m);
|
||||||
|
|
||||||
//codeGen
|
//codeGen
|
||||||
byte[] code = c.codeGen();
|
byte[] code = c.codeGen();
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
import de.maishai.ast.records.Block;
|
|
||||||
import de.maishai.ast.records.Constructor;
|
import de.maishai.ast.records.Constructor;
|
||||||
import de.maishai.ast.records.Parameter;
|
import de.maishai.ast.records.Parameter;
|
||||||
import de.maishai.typedast.CodeGenUtils;
|
import de.maishai.typedast.*;
|
||||||
import de.maishai.typedast.MethodContext;
|
|
||||||
import de.maishai.typedast.TypedNode;
|
|
||||||
import de.maishai.typedast.Type;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.objectweb.asm.ClassWriter;
|
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@ -24,82 +18,75 @@ import java.util.Map;
|
|||||||
public class TypedConstructor implements TypedNode {
|
public class TypedConstructor implements TypedNode {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private List<TypedParameter> typedParameters;
|
private List<TypedParameter> typedParameters = new ArrayList<>();
|
||||||
private TypedBlock typedBlock;
|
private TypedBlock typedBlock;
|
||||||
|
private Type type;
|
||||||
|
private List<TypedLocalVariable> localVariables = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
public TypedConstructor(String name, List<TypedParameter> typedParameters, TypedBlock typedBlock) {
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
this.name = name;
|
||||||
if (localVar.containsKey(name)) {
|
this.typedParameters = typedParameters;
|
||||||
throw new RuntimeException("constructor already declared");
|
this.typedBlock = typedBlock;
|
||||||
}
|
|
||||||
localVar.put(name, Type.VOID);
|
|
||||||
if (typedParameters != null) {
|
|
||||||
for (TypedParameter param : typedParameters) {
|
|
||||||
param.typeCheck(localVar, classes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
typedBlock.typeCheck(localVar, classes);
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypedConstructor unTypedContructorToTypedConstructor(de.maishai.ast.records.Constructor unTypedConstructor) {
|
public TypedConstructor(TypedClass clas, Constructor unTypedConstructor) {
|
||||||
TypedConstructor typedConstructor = new TypedConstructor();
|
convertToTypedConstructor(clas, unTypedConstructor);
|
||||||
typedConstructor.setName(unTypedConstructor.className());
|
}
|
||||||
typedConstructor.setTypedParameters(new ArrayList<>());
|
|
||||||
|
|
||||||
if (unTypedConstructor.params().isEmpty()) {
|
public boolean isLocalVariablePresent(String localVarName) {
|
||||||
typedConstructor.setTypedParameters(List.of());
|
return localVariables.stream().anyMatch(localVariable -> localVariable.getName().equals(localVarName));
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
public boolean isParameterPresent(String parameterName) {
|
||||||
|
return typedParameters.stream().anyMatch(parameter -> parameter.getParaName().equals(parameterName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLocalVariableInConstructor(String localVarName) {
|
||||||
|
return isLocalVariablePresent(localVarName) || isParameterPresent(localVarName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getLocalVariableType(String localVarName) {
|
||||||
|
return localVariables.stream().filter(localVariable -> localVariable.getName().equals(localVarName)).findFirst().get().getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToTypedConstructor(TypedClass clas, Constructor unTypedConstructor) {
|
||||||
|
name = unTypedConstructor.className();
|
||||||
|
|
||||||
for (Parameter param : unTypedConstructor.params()) {
|
for (Parameter param : unTypedConstructor.params()) {
|
||||||
TypedParameter typedParam = new TypedParameter();
|
typedParameters.add(new TypedParameter(clas, param));
|
||||||
typedParam.setParaName(param.name());
|
}
|
||||||
typedParam.setType(param.type());
|
type = Type.VOID;
|
||||||
typedConstructor.getTypedParameters().add(typedParam);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
public void convertToBlock(TypedClass clas, Constructor unTypedConstructor) {
|
||||||
TypedBlock typedBlock = new TypedBlock();
|
this.typedBlock = new TypedBlock(clas, unTypedConstructor.block());
|
||||||
typedConstructor.setTypedBlock(typedBlock.unTypedBlockToTypedBlock(unTypedConstructor.block()));
|
typeCheck(clas);
|
||||||
return typedConstructor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
Constructor untyped = (Constructor) unTypedAST;
|
type = typedBlock.typeCheck(clas);
|
||||||
TypedConstructor typedConstructor = new TypedConstructor();
|
if (type != Type.VOID) {
|
||||||
typedConstructor.setName(untyped.className());
|
throw new RuntimeException("Constructor must not habe a return statement");
|
||||||
typedConstructor.setTypedParameters(new ArrayList<>());
|
|
||||||
|
|
||||||
if (untyped.params().isEmpty()) {
|
|
||||||
typedConstructor.setTypedParameters(null);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
for (Parameter param : untyped.params()) {
|
|
||||||
TypedParameter typedParam = new TypedParameter();
|
|
||||||
typedParam.setType(param.type());
|
|
||||||
typedParam.setParaName(param.name());
|
|
||||||
typedConstructor.getTypedParameters().add(typedParam);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
return type;
|
||||||
TypedBlock typedBlock = new TypedBlock();
|
|
||||||
typedConstructor.setTypedBlock(typedBlock.unTypedBlockToTypedBlock(untyped.block()));
|
|
||||||
return typedConstructor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void codeGen(ClassWriter cw) {
|
|
||||||
|
public void codeGen(ClassContext ctx) {
|
||||||
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
||||||
MethodVisitor mv = cw.visitMethod(accessModifier, "<init>", CodeGenUtils.generateDescriptor(typedParameters, Type.VOID), null, null);
|
MethodVisitor mv = ctx.getCw().visitMethod(accessModifier, "<init>", CodeGenUtils.generateDescriptor(typedParameters, Type.VOID), null, null);
|
||||||
MethodContext context = new MethodContext(mv);
|
MethodContext mctx = new MethodContext(ctx, mv);
|
||||||
|
typedParameters.forEach(param -> mctx.registerVariable(param.getParaName(), param.getType()));
|
||||||
//super();
|
//super();
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
mctx.pushStack("this");
|
||||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||||
|
|
||||||
typedBlock.codeGen(mv, context);
|
typedBlock.codeGen(mctx);
|
||||||
|
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
|
||||||
context.wrapUp();
|
mctx.wrapUp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
|
||||||
|
|
||||||
import de.maishai.typedast.MethodContext;
|
|
||||||
import de.maishai.typedast.TypedNode;
|
|
||||||
import de.maishai.typedast.TypedStatement;
|
|
||||||
import de.maishai.typedast.Type;
|
|
||||||
import lombok.Data;
|
|
||||||
import org.objectweb.asm.MethodVisitor;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
@Data
|
|
||||||
public class TypedContinue implements TypedStatement {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
|
||||||
return new TypedContinue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,62 @@
|
|||||||
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
|
import de.maishai.ast.records.Declaration;
|
||||||
|
import de.maishai.typedast.MethodContext;
|
||||||
|
import de.maishai.typedast.TypedNode;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static de.maishai.typedast.Type.Kind.REFERENCE;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public final class TypedDeclaration implements TypedNode {
|
||||||
|
private String name;
|
||||||
|
private Type type;
|
||||||
|
|
||||||
|
public TypedDeclaration(TypedClass clas, Declaration declaration) {
|
||||||
|
convertToTypedDeclaration(clas, declaration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToTypedDeclaration(TypedClass clas, Declaration declaration) {
|
||||||
|
name = declaration.name();
|
||||||
|
type = declaration.type();
|
||||||
|
typeCheck(clas);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type typeCheck(TypedClass clas) {
|
||||||
|
if (clas.isThereField(name)) {
|
||||||
|
throw new RuntimeException("Field " + name + " already declared");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.getKind() == REFERENCE) {
|
||||||
|
if (!type.getReference().equals(clas.getClassName())) {
|
||||||
|
throw new RuntimeException("Field " + name + " has wrong type");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
||||||
|
System.out.println("Generating code for local variable " + name);
|
||||||
|
int index = ctx.addVariable(name);
|
||||||
|
mv.visitLocalVariable(name, type.getDescriptor(), null, ctx.getStartLabel(), ctx.getEndLabel(), index);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
public void codeGen(ClassWriter cw) {
|
||||||
|
int access = Opcodes.ACC_PUBLIC; // laut Andi ist es ok, dass alle Felder public sind
|
||||||
|
cw.visitField(access, name, type.getDescriptor(), null, null).visitEnd();
|
||||||
|
}
|
||||||
|
}
|
@ -1,38 +1,41 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
import de.maishai.ast.records.DoWhile;
|
import de.maishai.ast.records.*;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class TypedDoWhile implements TypedStatement {
|
public class TypedDoWhile implements TypedStatement {
|
||||||
private TypedBlock typedBlock;
|
private TypedBlock typedBlock;
|
||||||
private TypedExpression cond;
|
private TypedExpression cond;
|
||||||
|
private Type type;
|
||||||
|
|
||||||
|
public TypedDoWhile(TypedClass clas, DoWhile unTypedDoWhile) {
|
||||||
|
convertToTypedDoWhile(clas, unTypedDoWhile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToTypedDoWhile(TypedClass clas, DoWhile unTypedDoWhile) {
|
||||||
|
typedBlock = new TypedBlock(clas, unTypedDoWhile.block());
|
||||||
|
cond = convertExpression(clas, unTypedDoWhile.cond());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
if(cond.typeCheck(localVar, classes) != Type.BOOL){
|
if (cond.typeCheck(clas) != Type.BOOL) {
|
||||||
throw new RuntimeException("Condition must be boolean");
|
throw new RuntimeException("Condition must be boolean");
|
||||||
}
|
}
|
||||||
typedBlock.typeCheck(localVar, classes);
|
typedBlock.typeCheck(clas);
|
||||||
|
this.type = Type.VOID;
|
||||||
return Type.VOID;
|
return Type.VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public void codeGen(MethodContext ctx) {
|
||||||
DoWhile untyped = (DoWhile) unTypedAST;
|
|
||||||
|
|
||||||
TypedDoWhile typedDoWhile = new TypedDoWhile();
|
|
||||||
TypedBlock typedBlock = new TypedBlock();
|
|
||||||
typedDoWhile.setTypedBlock(typedBlock.unTypedBlockToTypedBlock(untyped.block()));
|
|
||||||
typedDoWhile.setCond((TypedExpression) cond.convertToTypedAST(localVar, classes, untyped.cond()));
|
|
||||||
|
|
||||||
return typedDoWhile;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
|
||||||
|
|
||||||
import de.maishai.ast.records.Declaration;
|
|
||||||
import de.maishai.typedast.TypedNode;
|
|
||||||
import de.maishai.typedast.Type;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.objectweb.asm.ClassWriter;
|
|
||||||
import org.objectweb.asm.Opcodes;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Data
|
|
||||||
public class TypedField implements TypedNode {
|
|
||||||
private String varName;
|
|
||||||
private Type type;
|
|
||||||
|
|
||||||
|
|
||||||
public TypedField unTypedFieldToTypedField(Declaration declaration){
|
|
||||||
TypedField typedField = new TypedField();
|
|
||||||
typedField.setType(declaration.type());
|
|
||||||
typedField.setVarName(declaration.name());
|
|
||||||
return typedField;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
|
||||||
if (localVar.containsKey(varName)) {
|
|
||||||
throw new RuntimeException("Variable " + varName + " already declared");
|
|
||||||
}
|
|
||||||
localVar.put(varName, type);
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
|
||||||
Declaration untypedDeclaration = (Declaration) unTypedAST;
|
|
||||||
TypedField typedField = new TypedField();
|
|
||||||
|
|
||||||
typedField.setType(untypedDeclaration.type());
|
|
||||||
typedField.setVarName(untypedDeclaration.name());
|
|
||||||
|
|
||||||
return typedField;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void codeGen(ClassWriter cw) {
|
|
||||||
int access = Opcodes.ACC_PUBLIC; // laut Andi ist es ok, dass alle Felder public sind
|
|
||||||
cw.visitField(access, varName, type.getDescriptor(), null, null).visitEnd();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
|
||||||
|
|
||||||
import de.maishai.ast.records.FieldVarAccess;
|
|
||||||
import de.maishai.typedast.TypedExpression;
|
|
||||||
import de.maishai.typedast.TypedNode;
|
|
||||||
import de.maishai.typedast.Type;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
@Data
|
|
||||||
public class TypedFieldId implements TypedExpression {
|
|
||||||
private Boolean field;
|
|
||||||
private TypedExpression recipient;
|
|
||||||
private String name;
|
|
||||||
@Override
|
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
|
||||||
//TODO: Implement typeCheck for FieldVarAccess
|
|
||||||
if(field){
|
|
||||||
return null;
|
|
||||||
}else{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
|
||||||
FieldVarAccess untypedFieldVarAccess = (FieldVarAccess) unTypedAST;
|
|
||||||
TypedFieldId typedFieldId = new TypedFieldId();
|
|
||||||
typedFieldId.setField(untypedFieldVarAccess.field());
|
|
||||||
typedFieldId.setRecipient((TypedExpression) recipient.convertToTypedAST(localVar, classes, untypedFieldVarAccess.recursiveOwnerChain()));
|
|
||||||
typedFieldId.setName(untypedFieldVarAccess.id());
|
|
||||||
|
|
||||||
return typedFieldId;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,81 @@
|
|||||||
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
|
import de.maishai.ast.records.*;
|
||||||
|
import de.maishai.typedast.MethodContext;
|
||||||
|
import de.maishai.typedast.TypedExpression;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TypedFieldVarAccess implements TypedExpression {
|
||||||
|
private Boolean field;
|
||||||
|
private TypedExpression recursiveOwnerChain;
|
||||||
|
private String name;
|
||||||
|
private Type type;
|
||||||
|
|
||||||
|
public TypedFieldVarAccess(TypedClass clas, FieldVarAccess unTypedFieldVarAccess) {
|
||||||
|
convertToTypedFieldVarAccess(clas, unTypedFieldVarAccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToTypedFieldVarAccess(TypedClass clas, FieldVarAccess unTypedFieldVarAccess) {
|
||||||
|
field = unTypedFieldVarAccess.field();
|
||||||
|
recursiveOwnerChain = convertExpression(clas, unTypedFieldVarAccess.recursiveOwnerChain());
|
||||||
|
name = unTypedFieldVarAccess.id();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type typeCheck(TypedClass clas) {
|
||||||
|
if (field) {
|
||||||
|
if (clas.isThereField(name)) {
|
||||||
|
type = clas.getFieldType(name);
|
||||||
|
return clas.getFieldType(name);
|
||||||
|
}else{
|
||||||
|
throw new RuntimeException("Field " + name + " not declared ");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (clas.isCurrentConstructorPresent()) {
|
||||||
|
if (clas.isParameterNameInCurrentConstructor(name)) {
|
||||||
|
type = clas.getParameterTypeInCurrentConstructor(name);
|
||||||
|
return type;
|
||||||
|
} else if (clas.getCurrentConstructor().isLocalVariablePresent(name)) {
|
||||||
|
type = clas.getCurrentConstructor().getLocalVariableType(name);
|
||||||
|
return type;
|
||||||
|
} else if(clas.isThereField(name)){
|
||||||
|
type = clas.getFieldType(name);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new RuntimeException("Variable " + name + " not declared in constructor");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (clas.isCurrentMethodPresent()) {
|
||||||
|
if (clas.isParameterWitNameInMethod(name)) {
|
||||||
|
type = clas.getParameterTypeInCurrentMethod(name);
|
||||||
|
return type;
|
||||||
|
} else if (clas.getCurrentMethod().isLocalVariablePresent(name)) {
|
||||||
|
type = clas.getCurrentMethod().getLocalVariableType(name);
|
||||||
|
return type;
|
||||||
|
} else if(clas.isThereField(name)){
|
||||||
|
type = clas.getFieldType(name);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new RuntimeException("Variable " + name + " not declared in method");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Variable " + name + " not declared ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void codeGen(MethodContext ctx) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
import de.maishai.ast.records.For;
|
import de.maishai.ast.records.*;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@ -9,40 +9,42 @@ import org.objectweb.asm.MethodVisitor;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class TypedFor implements TypedStatement {
|
public class TypedFor implements TypedStatement {
|
||||||
private TypedExpression assign;
|
private TypedAssignment assign;
|
||||||
private TypedExpression cond;
|
private TypedExpression cond;
|
||||||
private TypedExpression inc;
|
private TypedAssignment inc;
|
||||||
private TypedBlock typedBlock;
|
private TypedBlock typedBlock;
|
||||||
|
private Type type;
|
||||||
|
|
||||||
|
public TypedFor(TypedClass clas, For unTypedFor) {
|
||||||
|
convertToTypedFor(clas, unTypedFor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToTypedFor(TypedClass clas, For unTypedFor) {
|
||||||
|
assign = new TypedAssignment(clas, unTypedFor.assign());
|
||||||
|
cond = convertExpression(clas, unTypedFor.cond());
|
||||||
|
inc = new TypedAssignment(clas, unTypedFor.inc());
|
||||||
|
typedBlock = new TypedBlock(clas, unTypedFor.block());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
assign.typeCheck(localVar, classes);
|
assign.typeCheck(clas);
|
||||||
if(!cond.typeCheck(localVar, classes).equals(Type.BOOL)) {
|
if (!cond.typeCheck(clas).equals(Type.BOOL)) {
|
||||||
throw new RuntimeException("Condition must be a boolean");
|
throw new RuntimeException("Condition must be a boolean");
|
||||||
}
|
}
|
||||||
inc.typeCheck(localVar, classes);
|
inc.typeCheck(clas);
|
||||||
return typedBlock.typeCheck(localVar, classes);
|
type = typedBlock.typeCheck(clas);
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public void codeGen(MethodContext ctx) {
|
||||||
For untyped = (For) unTypedAST;
|
|
||||||
TypedFor typedFor = new TypedFor();
|
|
||||||
typedFor.setAssign((TypedExpression) assign.convertToTypedAST(localVar, classes, untyped.assign()));
|
|
||||||
typedFor.setCond((TypedExpression) cond.convertToTypedAST(localVar, classes, untyped.cond()));
|
|
||||||
typedFor.setInc((TypedExpression) inc.convertToTypedAST(localVar, classes, untyped.inc()));
|
|
||||||
|
|
||||||
TypedBlock typedBlock = new TypedBlock();
|
|
||||||
typedFor.setTypedBlock(typedBlock.unTypedBlockToTypedBlock(untyped.block()));
|
|
||||||
|
|
||||||
return typedFor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,48 +1,72 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
import de.maishai.ast.records.IfElse;
|
import de.maishai.ast.records.*;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.objectweb.asm.Label;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
public class TypedIfElse implements TypedStatement {
|
public class TypedIfElse implements TypedStatement {
|
||||||
private TypedExpression typedCon;
|
private TypedExpression typedCon;
|
||||||
private TypedBlock ifTypedBlock;
|
private TypedBlock ifTypedBlock;
|
||||||
private TypedBlock elseTypedBlock;
|
private TypedBlock elseTypedBlock;
|
||||||
|
private Type type;
|
||||||
|
|
||||||
|
public TypedIfElse(TypedClass clas, IfElse unTypedIfElse) {
|
||||||
|
convertToTypedIfElse(clas, unTypedIfElse);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToTypedIfElse(TypedClass clas, IfElse unTypedIfElse) {
|
||||||
|
ifTypedBlock = new TypedBlock(clas, unTypedIfElse.ifBlock());
|
||||||
|
elseTypedBlock = new TypedBlock(clas, unTypedIfElse.elseBlock());
|
||||||
|
typedCon = convertExpression(clas, unTypedIfElse.cond());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
// condition must be a boolean
|
/*
|
||||||
if (typedCon.typeCheck(localVar, classes) != Type.BOOL) {
|
if (typedCon.typeCheck(clas) != Type.BOOL) {
|
||||||
throw new RuntimeException("If condition must be a boolean");
|
throw new RuntimeException("If condition must be a boolean");
|
||||||
}
|
}
|
||||||
//Statement1 and Statement2 must be of type void
|
if (ifTypedBlock.typeCheck(clas) != Type.VOID) {
|
||||||
if (ifTypedBlock.typeCheck(localVar, classes) != Type.VOID) {
|
|
||||||
throw new RuntimeException("If block must be of type void");
|
throw new RuntimeException("If block must be of type void");
|
||||||
}
|
}
|
||||||
return Type.VOID;
|
*/
|
||||||
|
//TODO: it still not catching the all cases when return is used
|
||||||
|
if (ifTypedBlock.typeCheck(clas) == elseTypedBlock.typeCheck(clas)) {
|
||||||
|
type = ifTypedBlock.typeCheck(clas);
|
||||||
|
}
|
||||||
|
if (elseTypedBlock.typeCheck(clas) == Type.VOID) {
|
||||||
|
type = ifTypedBlock.typeCheck(clas);
|
||||||
|
}
|
||||||
|
if (ifTypedBlock.typeCheck(clas) == Type.VOID) {
|
||||||
|
type = elseTypedBlock.typeCheck(clas);
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public void codeGen(MethodContext ctx) {
|
||||||
IfElse ifElse = (IfElse) unTypedAST;
|
Label falseLabel = new Label();
|
||||||
|
Label end = new Label();
|
||||||
|
typedCon.codeGen(ctx);
|
||||||
|
ctx.getMv().visitJumpInsn(Opcodes.IFEQ, falseLabel);
|
||||||
|
ifTypedBlock.codeGen(ctx);
|
||||||
|
ctx.getMv().visitJumpInsn(Opcodes.GOTO, end);
|
||||||
|
|
||||||
TypedIfElse typedIfElse = new TypedIfElse();
|
ctx.getMv().visitLabel(falseLabel);
|
||||||
typedIfElse.setTypedCon((TypedExpression) typedCon.convertToTypedAST(localVar, classes, ifElse.cond()));
|
if (elseTypedBlock != null) {
|
||||||
|
elseTypedBlock.codeGen(ctx);
|
||||||
TypedBlock ifTypedBlock = new TypedBlock();
|
|
||||||
TypedBlock elseTypedBlock = new TypedBlock();
|
|
||||||
typedIfElse.setIfTypedBlock(ifTypedBlock.unTypedBlockToTypedBlock(ifElse.ifBlock()));
|
|
||||||
typedIfElse.setElseTypedBlock(elseTypedBlock.unTypedBlockToTypedBlock(ifElse.elseBlock()));
|
|
||||||
|
|
||||||
return typedIfElse;
|
|
||||||
}
|
}
|
||||||
|
ctx.getMv().visitLabel(end);
|
||||||
@Override
|
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,46 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
import de.maishai.ast.records.IntLiteral;
|
import de.maishai.ast.records.IntLiteral;
|
||||||
|
import de.maishai.typedast.MethodContext;
|
||||||
import de.maishai.typedast.TypedExpression;
|
import de.maishai.typedast.TypedExpression;
|
||||||
import de.maishai.typedast.TypedNode;
|
import de.maishai.typedast.TypedNode;
|
||||||
import de.maishai.typedast.Type;
|
import de.maishai.typedast.Type;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class TypedIntLiteral implements TypedExpression {
|
public class TypedIntLiteral implements TypedExpression {
|
||||||
private Integer value;
|
private Integer value;
|
||||||
@Override
|
private Type type;
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
|
||||||
return Type.INT;
|
|
||||||
|
public TypedIntLiteral(TypedClass clas, IntLiteral unTypedIntLiteral) {
|
||||||
|
convertToTypedIntLiteral(clas, unTypedIntLiteral);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToTypedIntLiteral(TypedClass clas, IntLiteral unTypedIntLiteral) {
|
||||||
|
value = unTypedIntLiteral.value();
|
||||||
|
type = Type.INT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
IntLiteral untyped = (IntLiteral) unTypedAST;
|
return type;
|
||||||
return new TypedIntLiteral(untyped.value());
|
}
|
||||||
|
|
||||||
|
public TypedIntLiteral(Integer value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void codeGen(MethodContext ctx) {
|
||||||
|
ctx.getMv().visitLdcInsn(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import lombok.Data;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@ -17,29 +16,36 @@ public final class TypedLocalVariable implements TypedNode {
|
|||||||
private String name;
|
private String name;
|
||||||
private Type type;
|
private Type type;
|
||||||
|
|
||||||
@Override
|
public TypedLocalVariable(TypedClass clas, Declaration declaration) {
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
convertToTypedLocalVariable(clas, declaration);
|
||||||
if(localVar.containsKey(name)) {
|
|
||||||
throw new RuntimeException("Variable " + name + " already exists");
|
|
||||||
}
|
}
|
||||||
localVar.put(name, type);
|
|
||||||
|
public void convertToTypedLocalVariable(TypedClass clas, Declaration declaration) {
|
||||||
|
name = declaration.name();
|
||||||
|
type = declaration.type();
|
||||||
|
typeCheck(clas);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type typeCheck(TypedClass clas) {
|
||||||
|
if (clas.isCurrentMethodPresent() && !clas.isCurrentConstructorPresent()) {
|
||||||
|
if (clas.getCurrentMethod().isLocalVariableInMethod(name)) {
|
||||||
|
throw new RuntimeException("Variable " + name + " already declared");
|
||||||
|
}
|
||||||
|
clas.getCurrentMethod().getLocalVariables().add(this);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
if (!clas.isCurrentMethodPresent() && clas.isCurrentConstructorPresent()) {
|
||||||
@Override
|
if (clas.getCurrentConstructor().isLocalVariableInConstructor(name)) {
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
throw new RuntimeException("Variable " + name + " already declared");
|
||||||
Declaration untypedLocalVariable = (Declaration) unTypedAST;
|
}
|
||||||
TypedLocalVariable typedLocalVariable = new TypedLocalVariable();
|
clas.getCurrentConstructor().getLocalVariables().add(this);
|
||||||
|
return type;
|
||||||
typedLocalVariable.setName(untypedLocalVariable.name());
|
}
|
||||||
typedLocalVariable.setType(untypedLocalVariable.type());
|
throw new RuntimeException("not found method or constructor in class");
|
||||||
|
|
||||||
return typedLocalVariable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
||||||
int index = ctx.addVariable(name);
|
ctx.registerVariable(name, type);
|
||||||
mv.visitLocalVariable(name, type.getDescriptor(), null, ctx.getStartLabel(), ctx.getEndLabel(), index);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,101 +1,121 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
|
import de.maishai.ast.records.IfElse;
|
||||||
import de.maishai.ast.records.Method;
|
import de.maishai.ast.records.Method;
|
||||||
import de.maishai.ast.records.Parameter;
|
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import lombok.NoArgsConstructor;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
public class TypedMethod implements TypedNode {
|
public class TypedMethod implements TypedNode {
|
||||||
private String name;
|
private String name;
|
||||||
private Type returnType;
|
private Type returnType;
|
||||||
private List<TypedParameter> typedParameters;
|
private List<TypedParameter> typedParameters = new ArrayList<>();
|
||||||
|
private List<TypedLocalVariable> localVariables = new ArrayList<>();
|
||||||
private TypedBlock typedBlock;
|
private TypedBlock typedBlock;
|
||||||
|
|
||||||
public TypedMethod unTypedMethodToTypedMethod(Method unTypedMethod) {
|
public TypedMethod(TypedClass clas, Method unTypedMethod) {
|
||||||
TypedMethod typedMethod = new TypedMethod();
|
convertToTypedMethod(clas, unTypedMethod);
|
||||||
typedMethod.setName(unTypedMethod.methodName());
|
}
|
||||||
typedMethod.setTypedParameters(new ArrayList<>());
|
|
||||||
|
|
||||||
if(unTypedMethod.params().isEmpty()){
|
public void convertToTypedMethod(TypedClass clas, Method unTypedMethod) {
|
||||||
typedMethod.setTypedParameters(List.of());
|
|
||||||
}else {
|
name = unTypedMethod.methodName();
|
||||||
for (Parameter parameter : unTypedMethod.params()) {
|
returnType = unTypedMethod.type();
|
||||||
TypedParameter typedParameter = new TypedParameter();
|
for (var parameter : unTypedMethod.params()) {
|
||||||
typedParameter.setParaName(parameter.name());
|
typedParameters.add(new TypedParameter(clas, parameter));
|
||||||
typedParameter.setType(parameter.type());
|
|
||||||
typedParameters.add(typedParameter);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
TypedBlock block = new TypedBlock();
|
clas.getTypedMethods().stream().filter(method -> method.equals(this)).findFirst().ifPresentOrElse(
|
||||||
typedMethod.setTypedBlock(block.unTypedBlockToTypedBlock(unTypedMethod.block()));
|
method -> {
|
||||||
return typedMethod;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
|
||||||
if(localVar.containsKey(name)) {
|
|
||||||
throw new RuntimeException("Method " + name + " already exists");
|
throw new RuntimeException("Method " + name + " already exists");
|
||||||
|
}, () -> {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
localVar.put(name, returnType);
|
|
||||||
for(TypedParameter typedParameter : typedParameters) {
|
public void convertToTypedBlock(TypedClass clas, Method unTypedMethod) {
|
||||||
typedParameter.typeCheck(localVar, classes);
|
typedBlock = new TypedBlock(clas, unTypedMethod.block());
|
||||||
|
typeCheck(clas);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLocalVariablePresent(String localVarName) {
|
||||||
|
return localVariables.stream().anyMatch(localVariable -> localVariable.getName().equals(localVarName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isParameterPresent(String parameterName) {
|
||||||
|
return typedParameters.stream().anyMatch(parameter -> parameter.getParaName().equals(parameterName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLocalVariableInMethod(String localVarName) {
|
||||||
|
return isLocalVariablePresent(localVarName) || isParameterPresent(localVarName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getLocalVariableType(String localVarName) {
|
||||||
|
return localVariables.stream().filter(localVariable -> localVariable.getName().equals(localVarName)).findFirst().get().getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasEvenReturnsInIfElseBlocks() {
|
||||||
|
List<TypedIfElse> typedIfElses = new ArrayList<>();
|
||||||
|
for (var stmt : typedBlock.getStmts()) {
|
||||||
|
if (stmt instanceof TypedIfElse ifElse) {
|
||||||
|
for (var stmt2 : ifElse.getIfTypedBlock().getStmts()) {
|
||||||
|
if (stmt2 instanceof TypedReturn) {
|
||||||
|
typedIfElses.add(ifElse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var stmt2 : ifElse.getElseTypedBlock().getStmts()) {
|
||||||
|
if (stmt2 instanceof TypedReturn) {
|
||||||
|
typedIfElses.add(ifElse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typedIfElses.size() % 2 == 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return typedBlock.typeCheck(localVar, classes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
Method untypedMethod = (Method) unTypedAST;
|
if (returnType != Type.VOID && !hasEvenReturnsInIfElseBlocks()) {
|
||||||
TypedMethod typedMethod = new TypedMethod();
|
if (typedBlock.typeCheck(clas).getKind() != returnType.getKind()) {
|
||||||
|
if (hasEvenReturnsInIfElseBlocks()) {
|
||||||
typedMethod.setTypedParameters(new ArrayList<>());
|
throw new RuntimeException("Method " + name + " must have even returns in if else blocks");
|
||||||
typedMethod.setName(untypedMethod.methodName());
|
} else {
|
||||||
typedMethod.setReturnType(untypedMethod.type());
|
throw new RuntimeException("Method " + name + " must return " + returnType.getKind());
|
||||||
|
}
|
||||||
for(Parameter parameter : untypedMethod.params()) {
|
}
|
||||||
TypedParameter typedParameter = new TypedParameter();
|
}
|
||||||
typedParameter.setParaName(parameter.name());
|
return returnType;
|
||||||
typedParameter.setType(parameter.type());
|
|
||||||
typedMethod.getTypedParameters().add(typedParameter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedBlock typedBlock = new TypedBlock();
|
@Override
|
||||||
typedMethod.setTypedBlock(typedBlock.unTypedBlockToTypedBlock(untypedMethod.block()));
|
public boolean equals(Object obj) {
|
||||||
|
if (obj instanceof TypedMethod) {
|
||||||
return typedMethod;
|
TypedMethod other = (TypedMethod) obj;
|
||||||
|
return name.equals(other.name) && returnType.equals(other.returnType) && typedParameters.equals(other.typedParameters);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypedParameter getTypedParameter(Parameter parameter) {
|
|
||||||
TypedParameter typedParameter = new TypedParameter();
|
|
||||||
typedParameter.setParaName(parameter.name());
|
|
||||||
|
|
||||||
if(parameter.type() == Type.CHAR){
|
public void codeGen(ClassContext ctx) {
|
||||||
typedParameter.setType(Type.CHAR);
|
|
||||||
}
|
|
||||||
if(parameter.type() == Type.BOOL){
|
|
||||||
typedParameter.setType(Type.BOOL);
|
|
||||||
}
|
|
||||||
if(parameter.type() == Type.INT){
|
|
||||||
typedParameter.setType(Type.INT);
|
|
||||||
}
|
|
||||||
|
|
||||||
return typedParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void codeGen(ClassWriter cw) {
|
|
||||||
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
||||||
MethodVisitor mv = cw.visitMethod(accessModifier, name,
|
MethodVisitor mv = ctx.getCw().visitMethod(accessModifier, name,
|
||||||
CodeGenUtils.generateDescriptor(typedParameters, returnType), null, null);
|
CodeGenUtils.generateDescriptor(typedParameters, returnType), null, null);
|
||||||
MethodContext context = new MethodContext(mv);
|
MethodContext context = new MethodContext(ctx, mv);
|
||||||
|
typedParameters.forEach(param -> context.registerVariable(param.getParaName(), param.getType()));
|
||||||
|
|
||||||
typedBlock.codeGen(mv, context);
|
typedBlock.codeGen(context);
|
||||||
|
context.wrapUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,66 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
|
import de.maishai.ast.records.Expression;
|
||||||
|
import de.maishai.ast.records.MethodCall;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
|
//TODO: test this after fixing error from parser
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
public class TypedMethodCall implements TypedExpression, TypedStatement {
|
public class TypedMethodCall implements TypedExpression, TypedStatement {
|
||||||
private TypedExpression recipient;
|
private TypedFieldVarAccess recipient;
|
||||||
private List<TypedExpression> args;
|
private List<TypedExpression> args = new ArrayList<>();
|
||||||
|
private Type type;
|
||||||
|
|
||||||
@Override
|
public TypedMethodCall(TypedClass clas, MethodCall unTypedMethodCall) {
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
convertToTypedMethodCall(clas, unTypedMethodCall);
|
||||||
//TODO: Implement typeCheck for MethodCall
|
}
|
||||||
return null;
|
|
||||||
|
public void convertToTypedMethodCall(TypedClass clas, MethodCall unTypedMethodCall) {
|
||||||
|
recipient = new TypedFieldVarAccess(clas, unTypedMethodCall.recipient());
|
||||||
|
for (Expression arg : unTypedMethodCall.args()) {
|
||||||
|
args.add(convertExpression(clas, arg));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
//TODO: Implement this
|
if (clas.isCurrentMethodPresent() || clas.isCurrentConstructorPresent()) {
|
||||||
return null;
|
|
||||||
|
List<TypedMethod> methods = clas.getTypedMethods().stream()
|
||||||
|
.filter(method -> method.getName().equals(recipient.getName()))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
for (TypedMethod method : methods) {
|
||||||
|
if (method.getTypedParameters().size() == args.size()) {
|
||||||
|
boolean allMatch = true;
|
||||||
|
for (int i = 0; i < args.size(); i++) {
|
||||||
|
if (!args.get(i).typeCheck(clas).equals(method.getTypedParameters().get(i).getType())) {
|
||||||
|
allMatch = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (allMatch) {
|
||||||
|
type = method.getReturnType();
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Method not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,56 +1,55 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
|
import de.maishai.ast.records.Expression;
|
||||||
import de.maishai.ast.records.New;
|
import de.maishai.ast.records.New;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class TypedNew implements TypedExpression, TypedStatement {
|
public class TypedNew implements TypedExpression, TypedStatement {
|
||||||
private Type type;
|
private Type type;
|
||||||
private List<TypedExpression> args;
|
private List<TypedExpression> args = new ArrayList<>();
|
||||||
@Override
|
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
public TypedNew(TypedClass clas, New unTypedNew) {
|
||||||
// new A(1, 2, 3)
|
convertToTypedNew(clas, unTypedNew);
|
||||||
if (!classes.containsKey(this.type.getReference())) {
|
|
||||||
throw new RuntimeException("Class " + this.type.getReference() + " not found");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedClass klasse = classes.get(this.type.getReference());
|
public void convertToTypedNew(TypedClass clas, New unTypedNew) {
|
||||||
if (klasse.getTypedFields().size() != args.size()) {
|
type = unTypedNew.type();
|
||||||
throw new RuntimeException("number of arguments is invalid for class" + this.type.getReference());
|
for (Expression arg : unTypedNew.args()) {
|
||||||
|
args.add(convertExpression(clas, arg));
|
||||||
}
|
}
|
||||||
// compare the types of the arguments
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type typeCheck(TypedClass clas) {
|
||||||
|
for (var constructor : clas.getTypedConstructors()) {
|
||||||
|
if (constructor.getTypedParameters().size() == args.size()) {
|
||||||
|
boolean valid = true;
|
||||||
for (int i = 0; i < args.size(); i++) {
|
for (int i = 0; i < args.size(); i++) {
|
||||||
Type type = args.get(i).typeCheck(localVar, classes);
|
if (!constructor.getTypedParameters().get(i).getType().equals(args.get(i).typeCheck(clas))) {
|
||||||
if (!type.equals(klasse.getTypedFields().get(i).getType())) {
|
valid = false;
|
||||||
throw new RuntimeException("False type for argument " + i + " in class " + type.getKind());
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Type.VOID;
|
if (valid) {
|
||||||
|
return Type.REFERENCE(clas.getClassName());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException("No matching constructor found");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public void codeGen(MethodContext ctx) {
|
||||||
New untyped = (New) unTypedAST;
|
|
||||||
TypedNew typedNew = new TypedNew();
|
|
||||||
|
|
||||||
typedNew.setType(untyped.type());
|
|
||||||
|
|
||||||
if(untyped.args().isEmpty()){
|
|
||||||
//TODO: Implement this
|
|
||||||
}
|
|
||||||
for(de.maishai.ast.records.Expression arg : untyped.args()) {
|
|
||||||
//TODO: Implement this
|
|
||||||
}
|
|
||||||
return typedNew;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,38 +1,53 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
import de.maishai.ast.records.Parameter;
|
import de.maishai.ast.records.Parameter;
|
||||||
import de.maishai.typedast.TypedNode;
|
|
||||||
import de.maishai.typedast.Type;
|
import de.maishai.typedast.Type;
|
||||||
|
import de.maishai.typedast.TypedNode;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Data
|
@Data
|
||||||
public class TypedParameter implements TypedNode {
|
public class TypedParameter implements TypedNode {
|
||||||
private String paraName;
|
private String paraName;
|
||||||
private Type type;
|
private Type type;
|
||||||
|
|
||||||
|
public TypedParameter(TypedClass clas, Parameter unTypedParameter) {
|
||||||
|
convertToTypedParameter(clas, unTypedParameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToTypedParameter(TypedClass clas, Parameter unTypedParameter) {
|
||||||
|
paraName = unTypedParameter.name();
|
||||||
|
type = unTypedParameter.type();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
public boolean equals(Object obj) {
|
||||||
if (localVar.containsKey(paraName)) {
|
if (obj instanceof TypedParameter) {
|
||||||
|
TypedParameter other = (TypedParameter) obj;
|
||||||
|
return paraName.equals(other.paraName) && type.equals(other.type);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type typeCheck(TypedClass clas) {
|
||||||
|
|
||||||
|
if (clas.isCurrentMethodPresent()) {
|
||||||
|
if (clas.isParameterWitNameInMethod(paraName)) {
|
||||||
throw new RuntimeException("Parameter " + paraName + " already exists");
|
throw new RuntimeException("Parameter " + paraName + " already exists");
|
||||||
}
|
}
|
||||||
localVar.put(paraName, type);
|
} else if (clas.isCurrentConstructorPresent()) {
|
||||||
|
if (clas.isParameterWitNameInConstructor(paraName)) {
|
||||||
|
throw new RuntimeException("Parameter " + paraName + " already exists");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@Override
|
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
|
||||||
Parameter untyped = (Parameter) unTypedAST;
|
|
||||||
TypedParameter typedParameter = new TypedParameter();
|
|
||||||
typedParameter.setParaName(untyped.name());
|
|
||||||
typedParameter.setType(untyped.type());
|
|
||||||
return typedParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,63 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
|
|
||||||
import de.maishai.ast.records.Return;
|
import de.maishai.ast.records.*;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
public class TypedReturn implements TypedStatement {
|
public class TypedReturn implements TypedStatement {
|
||||||
private TypedExpression ret;
|
private TypedExpression ret;
|
||||||
|
private Type type;
|
||||||
|
|
||||||
@Override
|
public TypedReturn(TypedClass clas, Return unTypedReturn) {
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
convertToTypedReturn(clas, unTypedReturn);
|
||||||
return ret.typeCheck(localVar, classes);
|
}
|
||||||
|
|
||||||
|
public void convertToTypedReturn(TypedClass clas, Return unTypedReturn) {
|
||||||
|
ret = convertExpression(clas, unTypedReturn.ret());
|
||||||
|
if(ret == null){
|
||||||
|
type = Type.VOID;
|
||||||
|
}else{
|
||||||
|
type = ret.getType();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
Return untyped = (Return) unTypedAST;
|
if (clas.isCurrentMethodPresent()) {
|
||||||
TypedReturn typedReturn = new TypedReturn();
|
if (clas.getCurrentMethod().getReturnType().getKind() != this.type.getKind()) {
|
||||||
typedReturn.setRet((TypedExpression) ret.convertToTypedAST(localVar, classes, untyped.ret()));
|
StringBuilder exp = new StringBuilder();
|
||||||
return typedReturn;
|
exp.append("\nMismatched return type: ");
|
||||||
|
exp.append("\nExpected: ").append(clas.getCurrentMethod().getReturnType().getKind());
|
||||||
|
exp.append("\nActual: ").append(this.type.getKind());
|
||||||
|
exp.append("\nMethod name: ").append(clas.getCurrentMethod().getName());
|
||||||
|
throw new RuntimeException(exp.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
|
if (ret == null) {
|
||||||
|
ctx.getMv().visitInsn(Opcodes.RETURN);
|
||||||
|
} else {
|
||||||
|
ret.codeGen(ctx);
|
||||||
|
if (ret.getType().getKind() != Type.Kind.REFERENCE) {
|
||||||
|
ctx.getMv().visitInsn(Opcodes.IRETURN);
|
||||||
|
} else {
|
||||||
|
ctx.getMv().visitInsn(Opcodes.ARETURN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,28 +2,44 @@ package de.maishai.typedast.typedclass;
|
|||||||
|
|
||||||
import de.maishai.ast.UnaryOperator;
|
import de.maishai.ast.UnaryOperator;
|
||||||
import de.maishai.ast.records.Unary;
|
import de.maishai.ast.records.Unary;
|
||||||
|
import de.maishai.typedast.MethodContext;
|
||||||
import de.maishai.typedast.TypedExpression;
|
import de.maishai.typedast.TypedExpression;
|
||||||
import de.maishai.typedast.TypedNode;
|
|
||||||
import de.maishai.typedast.Type;
|
import de.maishai.typedast.Type;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class TypedUnary implements TypedExpression {
|
public class TypedUnary implements TypedExpression {
|
||||||
private UnaryOperator op;
|
private UnaryOperator op;
|
||||||
private TypedExpression right;
|
private TypedExpression right;
|
||||||
|
private Type type;
|
||||||
|
|
||||||
|
public TypedUnary(TypedClass clas, Unary unTypedUnary) {
|
||||||
|
convertToTypedUnary(clas, unTypedUnary);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToTypedUnary(TypedClass clas, Unary unTypedUnary) {
|
||||||
|
op = unTypedUnary.op();
|
||||||
|
right = convertExpression(clas, unTypedUnary.right());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
|
|
||||||
if (op == UnaryOperator.NOT) {
|
if (op == UnaryOperator.NOT) {
|
||||||
if(right.typeCheck(localVar, classes) != Type.BOOL){
|
if (right.typeCheck(clas) != Type.BOOL) {
|
||||||
throw new RuntimeException("Not operator must be applied to boolean");
|
throw new RuntimeException("Not operator must be applied to boolean");
|
||||||
}
|
}
|
||||||
return Type.BOOL;
|
return Type.BOOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op == UnaryOperator.SUB) {
|
if (op == UnaryOperator.SUB) {
|
||||||
if(right.typeCheck(localVar, classes) != Type.INT){
|
if (right.typeCheck(clas) != Type.INT) {
|
||||||
throw new RuntimeException("Minus operator must be applied to int");
|
throw new RuntimeException("Minus operator must be applied to int");
|
||||||
}
|
}
|
||||||
return Type.INT;
|
return Type.INT;
|
||||||
@ -32,11 +48,14 @@ public class TypedUnary implements TypedExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public void codeGen(MethodContext ctx) {
|
||||||
Unary untyped = (Unary) unTypedAST;
|
right.codeGen(ctx);
|
||||||
TypedUnary typedUnary = new TypedUnary();
|
if(op == UnaryOperator.NOT){
|
||||||
typedUnary.setOp(untyped.op());
|
ctx.getMv().visitInsn(Opcodes.ICONST_1);
|
||||||
typedUnary.setRight((TypedExpression) right.convertToTypedAST(localVar, classes, untyped.right()));
|
ctx.getMv().visitInsn(Opcodes.IXOR);
|
||||||
return typedUnary;
|
}
|
||||||
|
if(op == UnaryOperator.SUB){
|
||||||
|
ctx.getMv().visitInsn(Opcodes.INEG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,36 +1,41 @@
|
|||||||
package de.maishai.typedast.typedclass;
|
package de.maishai.typedast.typedclass;
|
||||||
|
|
||||||
import de.maishai.ast.records.While;
|
import de.maishai.ast.records.*;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class TypedWhile implements TypedStatement {
|
public class TypedWhile implements TypedStatement {
|
||||||
private TypedExpression cond;
|
private TypedExpression cond;
|
||||||
private TypedBlock typedBlock;
|
private TypedBlock typedBlock;
|
||||||
|
private Type type;
|
||||||
|
|
||||||
|
public TypedWhile(TypedClass clas, While unTypedWhile) {
|
||||||
|
convertToTypedWhile(clas, unTypedWhile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertToTypedWhile(TypedClass clas, While unTypedWhile) {
|
||||||
|
cond = convertExpression(clas, unTypedWhile.cond());
|
||||||
|
typedBlock = new TypedBlock(clas, unTypedWhile.block());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type typeCheck(Map<String, Type> localVar, Map<String, TypedClass> classes) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
if(cond.typeCheck(localVar, classes) != Type.BOOL){
|
if (cond.typeCheck(clas) != Type.BOOL) {
|
||||||
throw new RuntimeException("While condition must be a boolean");
|
throw new RuntimeException("While condition must be a boolean");
|
||||||
}
|
}
|
||||||
return typedBlock.typeCheck(localVar, classes);
|
type = typedBlock.typeCheck(clas);
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedNode convertToTypedAST(Map<String, Type> localVar, Map<String, TypedClass> classes, de.maishai.ast.records.Node unTypedAST) {
|
public void codeGen(MethodContext ctx) {
|
||||||
While untyped = (While) unTypedAST;
|
|
||||||
TypedWhile typedWhile = new TypedWhile();
|
|
||||||
typedWhile.setCond((TypedExpression) cond.convertToTypedAST(localVar, classes, untyped.cond()));
|
|
||||||
TypedBlock typedBlock = new TypedBlock();
|
|
||||||
typedWhile.setTypedBlock(typedBlock.unTypedBlockToTypedBlock(untyped.block()));
|
|
||||||
return typedWhile;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
81
src/main/resources/JavaTestfiles/ClassCanBeTyped.java
Normal file
81
src/main/resources/JavaTestfiles/ClassCanBeTyped.java
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
public class ClassCanBeTyped {
|
||||||
|
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
ClassCanBeTyped b;
|
||||||
|
ClassCanBeTyped c;
|
||||||
|
public ClassCanBeTyped(int x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
public ClassCanBeTyped(int x, int y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
public ClassCanBeTyped initClassCanBeTyped(int x) {
|
||||||
|
int a;
|
||||||
|
a = 10;
|
||||||
|
b = new ClassCanBeTyped(x);
|
||||||
|
b.x = 10 + a;
|
||||||
|
b.y = 20;
|
||||||
|
b.c.x = 20 + a;
|
||||||
|
b.c.b.y = b.x;
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
public ClassCanBeTyped init(int x, int y) {
|
||||||
|
return new ClassCanBeTyped(x, y);
|
||||||
|
}
|
||||||
|
public ClassCanBeTyped(int x) {
|
||||||
|
this.x = x;
|
||||||
|
int i;
|
||||||
|
b = b.getX().c.getC();
|
||||||
|
i = b.getX().c.getX();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassCanBeTyped() {
|
||||||
|
this.x = 10;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < (x + 1); i = i + 1) {
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < this.x; j += 1) {
|
||||||
|
this.x = this.x * this.x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
this.y = this.y + 1;
|
||||||
|
} while (this.y < 10);
|
||||||
|
|
||||||
|
int k;
|
||||||
|
k = 0;
|
||||||
|
for (k = 0; k < 10; k = k + 1) {
|
||||||
|
if (k == 5) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassCanBeTyped(int x, int y, char z) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX(char z) {
|
||||||
|
return this.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassCanBeTyped getC() {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean methodCall() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user