diff --git a/.idea/misc.xml b/.idea/misc.xml index bb14756..f26d89f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -40,7 +40,7 @@ - + \ No newline at end of file diff --git a/src/main/java/CompilerInput.txt b/src/main/java/CompilerInput.txt index f59b7ae..918c686 100644 --- a/src/main/java/CompilerInput.txt +++ b/src/main/java/CompilerInput.txt @@ -1,7 +1,13 @@ public class Example { + public int testVar; + public static int testMethod(char b){ + int a; - a = 3; + int a; + + } + } \ No newline at end of file diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 13ee197..7f55626 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,6 +1,9 @@ import ast.ASTNode; import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.Token; +import ast.ClassNode; +import ast.ProgramNode; +import bytecode.ByteCodeGenerator; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.tree.ParseTree; @@ -20,14 +23,13 @@ public class Main { public static void main(String[] args) throws Exception { try { CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/java/CompilerInput.txt")); - parsefile(codeCharStream); + parseFile(codeCharStream); } catch (IOException e) { System.err.println("Error reading the file: " + e.getMessage()); } } - - static void parsefile(CharStream codeCharStream){ + static void parsefile(CharStream codeCharStream) { /* ------------------------- Scanner -> tokens ------------------------- */ SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); CommonTokenStream tokenStream = new CommonTokenStream(lexer); @@ -39,7 +41,8 @@ public class Main { for (Token token : tokens) { String tokenType = SimpleJavaLexer.VOCABULARY.getSymbolicName(token.getType()); String tokenText = token.getText(); - // System.out.println("Token Type: " + tokenType + ", Token Text: " + tokenText); + // System.out.println("Token Type: " + tokenType + ", Token Text: " + + // tokenText); System.out.println(tokenType + " " + tokenText); } System.out.println(); @@ -50,9 +53,10 @@ public class Main { // Printing the parse tree System.out.println("-------------------- Parser -> Parsetree --------------------"); - System.out.println (parseTree.toStringTree(parser)); + System.out.println(parseTree.toStringTree(parser)); printTree(parseTree, parser, 0); System.out.println(); + ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(ast); /* ------------------------- AST builder -> AST ------------------------- */ ASTBuilder astBuilder = new ASTBuilder(); @@ -60,30 +64,36 @@ public class Main { // Printing the AST System.out.println("-------------------- AST builder -> AST --------------------"); - //System.out.println("AST: " + ast.toString()); + // System.out.println("AST: " + ast.toString()); printAST(abstractSyntaxTree, 0); System.out.println(); - /* ------------------------- Semantic Analyzer -> Tast ------------------------- */ + /* + * ------------------------- Semantic Analyzer -> Tast ------------------------- + */ SemanticAnalyzer.generateTast(abstractSyntaxTree); // Printing the Tast System.out.println("Tast generated"); - /* ------------------------- Bytecode Generator -> Bytecode ------------------------- */ + /* + * ------------------------- Bytecode Generator -> Bytecode + * ------------------------- + */ ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(); byteCodeGenerator.generateByteCode(abstractSyntaxTree); System.out.println("Bytecode generated"); } - /** * This method is used to print the parse tree in a structured format. - * It recursively traverses the tree and prints the rule names and text of the nodes. + * It recursively traverses the tree and prints the rule names and text of the + * nodes. * * @param tree The parse tree to be printed. - * @param parser The parser used to parse the input. It's used to get the rule names. + * @param parser The parser used to parse the input. It's used to get the rule + * names. * @param indent The current indentation level. It's used to format the output. */ public static void printTree(ParseTree tree, Parser parser, int indent) { @@ -102,19 +112,20 @@ public class Main { System.out.println(indentString + tree.getText()); } - // Recursively print the children of the current node, increasing the indentation level + // Recursively print the children of the current node, increasing the + // indentation level for (int i = 0; i < tree.getChildCount(); i++) { printTree(tree.getChild(i), parser, indent + 1); } } - public static void printAST(ASTNode node, int indent) { String indentString = " ".repeat(indent * 2); System.out.println(indentString + node.getClass().toString()); - for (ASTNode child : node.) { - printAST(child, indent + 1); - } + // for (ASTNode child : node.) { + // printAST(child, indent + 1); + // } + byteCodeGenerator.visit(typedAst); } } \ No newline at end of file diff --git a/src/main/java/ast/ASTNode.java b/src/main/java/ast/ASTNode.java index 9c5880e..9944050 100644 --- a/src/main/java/ast/ASTNode.java +++ b/src/main/java/ast/ASTNode.java @@ -1,6 +1,6 @@ package ast; -public class ASTNode { +public interface ASTNode { } diff --git a/src/main/java/ast/ClassNode.java b/src/main/java/ast/ClassNode.java index c57a400..947a977 100644 --- a/src/main/java/ast/ClassNode.java +++ b/src/main/java/ast/ClassNode.java @@ -7,11 +7,13 @@ import ast.type.EnumAccessTypeNode; import java.util.ArrayList; import java.util.List; + +import bytecode.visitor.ClassVisitor; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; -import typechecker.Visitable; +import visitor.Visitable; -public class ClassNode extends ASTNode implements Visitable { +public class ClassNode implements ASTNode, Visitable { public String identifier; public AccessTypeNode accessType; public List members = new ArrayList<>(); @@ -38,6 +40,11 @@ public class ClassNode extends ASTNode implements Visitable { @Override public TypeCheckResult accept(SemanticVisitor visitor) { - return visitor.typeCheck(this); + return visitor.analyze(this); + } + + @Override + public void accept(ClassVisitor classVisitor) { + classVisitor.visit(this); } } diff --git a/src/main/java/ast/LiteralNode.java b/src/main/java/ast/LiteralNode.java index 8fa060a..3873465 100644 --- a/src/main/java/ast/LiteralNode.java +++ b/src/main/java/ast/LiteralNode.java @@ -1,8 +1,10 @@ package ast; import ast.expression.ExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; -public class LiteralNode extends ExpressionNode { +public class LiteralNode implements ExpressionNode { int value; private String type; @@ -20,4 +22,8 @@ public class LiteralNode extends ExpressionNode { } + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return null; + } } diff --git a/src/main/java/ast/ProgramNode.java b/src/main/java/ast/ProgramNode.java index 3d0af61..1aac1b1 100644 --- a/src/main/java/ast/ProgramNode.java +++ b/src/main/java/ast/ProgramNode.java @@ -2,11 +2,13 @@ package ast; import java.util.ArrayList; import java.util.List; + +import bytecode.visitor.ProgramVisitor; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; -import typechecker.Visitable; +import visitor.Visitable; -public class ProgramNode extends ASTNode implements Visitable{ +public class ProgramNode implements ASTNode, Visitable{ public List classes = new ArrayList<>(); public void addClass(ClassNode classNode) { @@ -15,6 +17,11 @@ public class ProgramNode extends ASTNode implements Visitable{ @Override public TypeCheckResult accept(SemanticVisitor visitor) { - return visitor.typeCheck(this); + return visitor.analyze(this); + } + + @Override + public void accept(ProgramVisitor programVisitor) { + programVisitor.visit(this); } } \ No newline at end of file diff --git a/src/main/java/ast/VarNode.java b/src/main/java/ast/VarNode.java index a3ac170..9349eb4 100644 --- a/src/main/java/ast/VarNode.java +++ b/src/main/java/ast/VarNode.java @@ -1,6 +1,10 @@ package ast; -public class VarNode extends ASTNode{ +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; + +public class VarNode implements ASTNode, Visitable { private String identifier; private String type; @@ -18,4 +22,8 @@ public class VarNode extends ASTNode{ return identifier; } + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } } diff --git a/src/main/java/ast/expression/BinaryExpressionNode.java b/src/main/java/ast/expression/BinaryExpressionNode.java index e63bbca..c912408 100644 --- a/src/main/java/ast/expression/BinaryExpressionNode.java +++ b/src/main/java/ast/expression/BinaryExpressionNode.java @@ -1,6 +1,10 @@ package ast.expression; -public class BinaryExpressionNode extends ExpressionNode { +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; + +public class BinaryExpressionNode implements ExpressionNode, Visitable { public ExpressionNode left; public ExpressionNode right; public String operator; // Stores the operator as a string (e.g., "+", "-", "&&") @@ -10,4 +14,9 @@ public class BinaryExpressionNode extends ExpressionNode { this.right = right; this.operator = operator; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } } \ No newline at end of file diff --git a/src/main/java/ast/expression/ExpressionNode.java b/src/main/java/ast/expression/ExpressionNode.java index 8204bed..e790795 100644 --- a/src/main/java/ast/expression/ExpressionNode.java +++ b/src/main/java/ast/expression/ExpressionNode.java @@ -1,9 +1,8 @@ package ast.expression; import ast.ASTNode; +import visitor.Visitable; -public class ExpressionNode extends ASTNode { - - +public interface ExpressionNode extends ASTNode, Visitable { } diff --git a/src/main/java/ast/expression/IdentifierExpressionNode.java b/src/main/java/ast/expression/IdentifierExpressionNode.java index 7631429..1bb8d56 100644 --- a/src/main/java/ast/expression/IdentifierExpressionNode.java +++ b/src/main/java/ast/expression/IdentifierExpressionNode.java @@ -1,9 +1,22 @@ package ast.expression; -public class IdentifierExpressionNode extends ExpressionNode { +import ast.type.TypeNode; +import semantic.SemanticVisitor; + +import typechecker.TypeCheckResult; +import visitor.Visitable; + +public class IdentifierExpressionNode implements ExpressionNode, Visitable { public String name; + public TypeNode type; + public IdentifierExpressionNode(String name) { this.name = name; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } } diff --git a/src/main/java/ast/expression/UnaryExpressionNode.java b/src/main/java/ast/expression/UnaryExpressionNode.java index 0c77ef5..24d1832 100644 --- a/src/main/java/ast/expression/UnaryExpressionNode.java +++ b/src/main/java/ast/expression/UnaryExpressionNode.java @@ -1,6 +1,10 @@ package ast.expression; -public class UnaryExpressionNode extends ExpressionNode { +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; + +public class UnaryExpressionNode implements ExpressionNode, Visitable { public ExpressionNode expression; public String operator; // Stores the operator (e.g., "-", "!") @@ -8,4 +12,9 @@ public class UnaryExpressionNode extends ExpressionNode { this.expression = expression; this.operator = operator; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } } diff --git a/src/main/java/ast/member/ConstructorNode.java b/src/main/java/ast/member/ConstructorNode.java index b411ff1..998d727 100644 --- a/src/main/java/ast/member/ConstructorNode.java +++ b/src/main/java/ast/member/ConstructorNode.java @@ -1,9 +1,16 @@ package ast.member; import ast.type.AccessTypeNode; +import bytecode.visitor.MethodVisitor; +import visitor.Visitable; -public class ConstructorNode extends MethodNode { +public class ConstructorNode extends MethodNode implements Visitable { public ConstructorNode(AccessTypeNode visibility, String name) { super(visibility, name); } + + @Override + public void accept(MethodVisitor methodVisitor) { + methodVisitor.visit(this); + } } diff --git a/src/main/java/ast/member/FieldNode.java b/src/main/java/ast/member/FieldNode.java index cfefdfc..60c5411 100644 --- a/src/main/java/ast/member/FieldNode.java +++ b/src/main/java/ast/member/FieldNode.java @@ -2,11 +2,12 @@ package ast.member; import ast.type.AccessTypeNode; import ast.type.TypeNode; +import bytecode.visitor.ClassVisitor; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; -import typechecker.Visitable; +import visitor.Visitable; -public class FieldNode extends MemberNode implements Visitable { +public class FieldNode implements MemberNode, Visitable { public AccessTypeNode accessTypeNode; public TypeNode type; public String identifier; @@ -19,6 +20,11 @@ public class FieldNode extends MemberNode implements Visitable { @Override public TypeCheckResult accept(SemanticVisitor visitor) { - return visitor.typeCheck(this); + return visitor.analyze(this); + } + + @Override + public void accept(ClassVisitor classVisitor) { + classVisitor.visit(this); } } diff --git a/src/main/java/ast/member/MemberNode.java b/src/main/java/ast/member/MemberNode.java index aa823af..f186835 100644 --- a/src/main/java/ast/member/MemberNode.java +++ b/src/main/java/ast/member/MemberNode.java @@ -2,5 +2,5 @@ package ast.member; import ast.ASTNode; -public class MemberNode extends ASTNode { +public interface MemberNode extends ASTNode { } diff --git a/src/main/java/ast/member/MethodNode.java b/src/main/java/ast/member/MethodNode.java index 122eb5e..c50f6af 100644 --- a/src/main/java/ast/member/MethodNode.java +++ b/src/main/java/ast/member/MethodNode.java @@ -3,15 +3,17 @@ package ast.member; import ast.parameter.ParameterListNode; import ast.statement.StatementNode; import ast.type.AccessTypeNode; -import ast.type.TypeNode; import java.util.ArrayList; import java.util.List; + +import ast.type.TypeNode; +import bytecode.visitor.MethodVisitor; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; -import typechecker.Visitable; +import visitor.Visitable; -public class MethodNode extends MemberNode implements Visitable { +public class MethodNode implements MemberNode, Visitable { public AccessTypeNode visibility; public TypeNode type; public String identifier; @@ -36,6 +38,11 @@ public class MethodNode extends MemberNode implements Visitable { @Override public TypeCheckResult accept(SemanticVisitor visitor) { - return visitor.typeCheck(this); + return visitor.analyze(this); + } + + @Override + public void accept(MethodVisitor methodVisitor) { + methodVisitor.visit(this); } } diff --git a/src/main/java/ast/parameter/ParameterListNode.java b/src/main/java/ast/parameter/ParameterListNode.java index 34c615a..69d12f3 100644 --- a/src/main/java/ast/parameter/ParameterListNode.java +++ b/src/main/java/ast/parameter/ParameterListNode.java @@ -5,7 +5,7 @@ import ast.ASTNode; import java.util.ArrayList; import java.util.List; -public class ParameterListNode extends ASTNode { +public class ParameterListNode implements ASTNode { List parameters = new ArrayList<>(); public ParameterListNode(List parameters){ diff --git a/src/main/java/ast/parameter/ParameterNode.java b/src/main/java/ast/parameter/ParameterNode.java index 739ae21..f3f5193 100644 --- a/src/main/java/ast/parameter/ParameterNode.java +++ b/src/main/java/ast/parameter/ParameterNode.java @@ -3,7 +3,7 @@ package ast.parameter; import ast.ASTNode; import ast.type.TypeNode; -public class ParameterNode extends ASTNode { +public class ParameterNode implements ASTNode { public TypeNode type; public String identifier; diff --git a/src/main/java/ast/statement/AssignmentStatementNode.java b/src/main/java/ast/statement/AssignmentStatementNode.java index b9158e7..9f6a395 100644 --- a/src/main/java/ast/statement/AssignmentStatementNode.java +++ b/src/main/java/ast/statement/AssignmentStatementNode.java @@ -4,7 +4,7 @@ import ast.VarNode; import ast.expression.ExpressionNode; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; -import typechecker.Visitable; +import visitor.Visitable; public class AssignmentStatementNode extends StatementNode implements Visitable { public VarNode varNode; @@ -17,6 +17,6 @@ public class AssignmentStatementNode extends StatementNode implements Visitable @Override public TypeCheckResult accept(SemanticVisitor visitor) { - return visitor.typeCheck(this); + return visitor.analyze(this); } } diff --git a/src/main/java/ast/statement/IfStatementNode.java b/src/main/java/ast/statement/IfStatementNode.java index 93eec91..3f585dd 100644 --- a/src/main/java/ast/statement/IfStatementNode.java +++ b/src/main/java/ast/statement/IfStatementNode.java @@ -1,6 +1,8 @@ package ast.statement; import ast.expression.ExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class IfStatementNode extends StatementNode { public ExpressionNode condition; @@ -12,4 +14,9 @@ public class IfStatementNode extends StatementNode { this.thenStatement = thenStatement; this.elseStatement = elseStatement; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } } \ No newline at end of file diff --git a/src/main/java/ast/statement/ReturnStatementNode.java b/src/main/java/ast/statement/ReturnStatementNode.java index 4ca4dfa..c5e4d6b 100644 --- a/src/main/java/ast/statement/ReturnStatementNode.java +++ b/src/main/java/ast/statement/ReturnStatementNode.java @@ -1,6 +1,8 @@ package ast.statement; import ast.expression.ExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class ReturnStatementNode extends StatementNode { public ExpressionNode expression; @@ -8,4 +10,9 @@ public class ReturnStatementNode extends StatementNode { public ReturnStatementNode(ExpressionNode expression) { this.expression = expression; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } } \ No newline at end of file diff --git a/src/main/java/ast/statement/StatementNode.java b/src/main/java/ast/statement/StatementNode.java index 910a134..eff1804 100644 --- a/src/main/java/ast/statement/StatementNode.java +++ b/src/main/java/ast/statement/StatementNode.java @@ -1,7 +1,8 @@ package ast.statement; import ast.ASTNode; +import visitor.Visitable; -public abstract class StatementNode extends ASTNode { +public abstract class StatementNode implements ASTNode, Visitable { } diff --git a/src/main/java/ast/statement/VariableDeclarationStatementNode.java b/src/main/java/ast/statement/VariableDeclarationStatementNode.java index e7f6e32..4302177 100644 --- a/src/main/java/ast/statement/VariableDeclarationStatementNode.java +++ b/src/main/java/ast/statement/VariableDeclarationStatementNode.java @@ -1,7 +1,9 @@ package ast.statement; -import ast.type.TypeNode; import ast.expression.ExpressionNode; +import ast.type.TypeNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class VariableDeclarationStatementNode extends StatementNode { public TypeNode type; @@ -12,4 +14,9 @@ public class VariableDeclarationStatementNode extends StatementNode { this.identifier = identifier; this.expression = expression; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } } \ No newline at end of file diff --git a/src/main/java/ast/statement/WhileStatementNode.java b/src/main/java/ast/statement/WhileStatementNode.java index e6a10b1..a3f4007 100644 --- a/src/main/java/ast/statement/WhileStatementNode.java +++ b/src/main/java/ast/statement/WhileStatementNode.java @@ -1,6 +1,8 @@ package ast.statement; import ast.expression.ExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class WhileStatementNode extends StatementNode { public ExpressionNode condition; @@ -10,4 +12,9 @@ public class WhileStatementNode extends StatementNode { this.condition = condition; this.body = body; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } } diff --git a/src/main/java/ast/type/AccessTypeNode.java b/src/main/java/ast/type/AccessTypeNode.java index ddacf68..ba156c1 100644 --- a/src/main/java/ast/type/AccessTypeNode.java +++ b/src/main/java/ast/type/AccessTypeNode.java @@ -2,7 +2,7 @@ package ast.type; import ast.ASTNode; -public class AccessTypeNode extends ASTNode { +public class AccessTypeNode implements ASTNode { public EnumAccessTypeNode enumAccessTypeNode; public AccessTypeNode(EnumAccessTypeNode enumAccessTypeNode) { diff --git a/src/main/java/ast/type/BaseTypeNode.java b/src/main/java/ast/type/BaseTypeNode.java new file mode 100644 index 0000000..2d871ab --- /dev/null +++ b/src/main/java/ast/type/BaseTypeNode.java @@ -0,0 +1,13 @@ +package ast.type; + +import ast.ASTNode; + +public class BaseTypeNode implements ASTNode, TypeNode { + + public EnumTypeNode enumType; + + public BaseTypeNode(EnumTypeNode enumType) { + this.enumType = enumType; + } + +} diff --git a/src/main/java/ast/type/ReferenceTypeNode.java b/src/main/java/ast/type/ReferenceTypeNode.java new file mode 100644 index 0000000..88225f3 --- /dev/null +++ b/src/main/java/ast/type/ReferenceTypeNode.java @@ -0,0 +1,6 @@ +package ast.type; + +import ast.ASTNode; + +public class ReferenceTypeNode implements ASTNode, TypeNode { +} diff --git a/src/main/java/ast/type/TypeNode.java b/src/main/java/ast/type/TypeNode.java index 5b1c2a6..79be9c9 100644 --- a/src/main/java/ast/type/TypeNode.java +++ b/src/main/java/ast/type/TypeNode.java @@ -2,10 +2,5 @@ package ast.type; import ast.ASTNode; -public class TypeNode extends ASTNode { - public EnumTypeNode enumTypeNode; - - public TypeNode(EnumTypeNode enumTypeNode) { - this.enumTypeNode = enumTypeNode; - } +public interface TypeNode extends ASTNode { } \ No newline at end of file diff --git a/src/main/java/bytecode/ByteCodeGenerator.java b/src/main/java/bytecode/ByteCodeGenerator.java index 0846386..5494255 100644 --- a/src/main/java/bytecode/ByteCodeGenerator.java +++ b/src/main/java/bytecode/ByteCodeGenerator.java @@ -2,13 +2,15 @@ package bytecode; import ast.ProgramNode; import ast.ClassNode; +import bytecode.visitor.ProgramVisitor; -public class ByteCodeGenerator { +public class ByteCodeGenerator implements ProgramVisitor { - public void generateByteCode(ProgramNode ast) { - for (ClassNode classDeclarationNode : ast.classes) { + @Override + public void visit(ProgramNode programNode) { + for (ClassNode classDeclarationNode : programNode.classes) { ClassCodeGen classCodeGen = new ClassCodeGen(); - classCodeGen.generateClassCode(classDeclarationNode); + classDeclarationNode.accept(classCodeGen); } } } diff --git a/src/main/java/bytecode/ClassCodeGen.java b/src/main/java/bytecode/ClassCodeGen.java index 3b10586..7a1c0f0 100644 --- a/src/main/java/bytecode/ClassCodeGen.java +++ b/src/main/java/bytecode/ClassCodeGen.java @@ -4,6 +4,8 @@ import ast.ClassNode; import ast.member.FieldNode; import ast.member.MemberNode; import ast.member.MethodNode; +import ast.type.BaseTypeNode; +import bytecode.visitor.ClassVisitor; import java.io.File; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; @@ -11,20 +13,22 @@ import org.objectweb.asm.Opcodes; import java.io.FileOutputStream; import java.io.IOException; -public class ClassCodeGen { - public void generateClassCode(ClassNode classNode) { - ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); - Mapper mapper = new Mapper(); +public class ClassCodeGen implements ClassVisitor { + Mapper mapper = new Mapper(); + ClassWriter classWriter; + + @Override + public void visit(ClassNode classNode) { + classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); classWriter.visit(Opcodes.V1_8, mapper.mapAccesTypeToOpcode(classNode.accessType), classNode.identifier, null, "java/lang/Object", null); for (MemberNode memberNode : classNode.members) { if (memberNode instanceof FieldNode) { - FieldCodeGen fieldCodeGen = new FieldCodeGen(); - fieldCodeGen.generateFieldCode(classWriter, (FieldNode) memberNode); + visit((FieldNode) memberNode); } else if (memberNode instanceof MethodNode) { - MethodCodeGen methodCodeGen = new MethodCodeGen(); - methodCodeGen.generateMethodCode(classWriter, (MethodNode) memberNode); + MethodCodeGen methodCodeGen = new MethodCodeGen(classWriter); + ((MethodNode) memberNode).accept(methodCodeGen); } } @@ -34,6 +38,14 @@ public class ClassCodeGen { classWriter.visitEnd(); } + @Override + public void visit(FieldNode fieldNode) { + if(fieldNode.type instanceof BaseTypeNode baseTypeNode){ + classWriter.visitField(mapper.mapAccesTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(baseTypeNode.enumType), null, null ); + } + classWriter.visitEnd(); + } + private void printIntoClassFile(byte[] byteCode, String name) { String directoryPath = "src/main/java/classFileOutput"; File directory = new File(directoryPath); diff --git a/src/main/java/bytecode/Mapper.java b/src/main/java/bytecode/Mapper.java index 168e1e2..08985a6 100644 --- a/src/main/java/bytecode/Mapper.java +++ b/src/main/java/bytecode/Mapper.java @@ -1,8 +1,8 @@ package bytecode; -import ast.type.AccessTypeNode; -import ast.type.EnumAccessTypeNode; +import ast.type.*; import org.objectweb.asm.Opcodes; +import ast.type.BaseTypeNode; public class Mapper { public int mapAccesTypeToOpcode(AccessTypeNode type) { @@ -14,4 +14,26 @@ public class Mapper { } return 0; } + + public String generateMethodDescriptor(BaseTypeNode baseTypeNode) { + String descriptor = "()"; + descriptor += getTypeChar(baseTypeNode.enumType); + return descriptor; + } + + public String getTypeChar(EnumTypeNode enumTypeNode) { + String typeChar = ""; + switch (enumTypeNode) { + case EnumTypeNode.INT: + typeChar = "I"; + break; + case EnumTypeNode.CHAR: + typeChar = "C"; + break; + case EnumTypeNode.BOOLEAN: + typeChar = "Z"; + break; + } + return typeChar; + } } diff --git a/src/main/java/bytecode/MethodCodeGen.java b/src/main/java/bytecode/MethodCodeGen.java index 066905f..e544a8b 100644 --- a/src/main/java/bytecode/MethodCodeGen.java +++ b/src/main/java/bytecode/MethodCodeGen.java @@ -1,17 +1,40 @@ package bytecode; +import ast.member.ConstructorNode; import ast.member.MethodNode; +import ast.type.BaseTypeNode; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; -public class MethodCodeGen { - public void generateMethodCode(ClassWriter classWriter, MethodNode methodNode) { - Mapper mapper = new Mapper(); +public class MethodCodeGen implements bytecode.visitor.MethodVisitor { + + private ClassWriter classWriter; + Mapper mapper = new Mapper(); + + public MethodCodeGen(ClassWriter classWriter) { + this.classWriter = classWriter; + } + + @Override + public void visit(ConstructorNode constructorNode) { MethodVisitor constructor = - classWriter.visitMethod(mapper.mapAccesTypeToOpcode(methodNode.visibility), + classWriter.visitMethod(mapper.mapAccesTypeToOpcode(constructorNode.visibility), "", "()V", null, null); + constructor.visitEnd(); + } + + @Override + public void visit(MethodNode methodNode) { + if(methodNode.type instanceof BaseTypeNode baseTypeNode){ + MethodVisitor method = classWriter.visitMethod(mapper.mapAccesTypeToOpcode(methodNode.visibility), + methodNode.identifier, + mapper.generateMethodDescriptor(baseTypeNode), + null, + null); + method.visitEnd(); + } } } diff --git a/src/main/java/bytecode/visitor/ClassVisitor.java b/src/main/java/bytecode/visitor/ClassVisitor.java new file mode 100644 index 0000000..98ef25c --- /dev/null +++ b/src/main/java/bytecode/visitor/ClassVisitor.java @@ -0,0 +1,10 @@ +package bytecode.visitor; + +import ast.ClassNode; +import ast.member.FieldNode; +import org.objectweb.asm.ClassWriter; + +public interface ClassVisitor { + void visit(ClassNode classNode); + void visit(FieldNode fieldNode); +} diff --git a/src/main/java/bytecode/visitor/MethodVisitor.java b/src/main/java/bytecode/visitor/MethodVisitor.java new file mode 100644 index 0000000..70177ce --- /dev/null +++ b/src/main/java/bytecode/visitor/MethodVisitor.java @@ -0,0 +1,9 @@ +package bytecode.visitor; + +import ast.member.ConstructorNode; +import ast.member.MethodNode; + +public interface MethodVisitor { + void visit(ConstructorNode constructorNode); + void visit(MethodNode methodNode); +} diff --git a/src/main/java/bytecode/visitor/ProgramVisitor.java b/src/main/java/bytecode/visitor/ProgramVisitor.java new file mode 100644 index 0000000..d569ec6 --- /dev/null +++ b/src/main/java/bytecode/visitor/ProgramVisitor.java @@ -0,0 +1,7 @@ +package bytecode.visitor; + +import ast.ProgramNode; + +public interface ProgramVisitor { + void visit(ProgramNode programNode); +} diff --git a/src/main/java/classFileOutput/Example.class b/src/main/java/classFileOutput/Example.class index c0d9270..c99f3e0 100644 Binary files a/src/main/java/classFileOutput/Example.class and b/src/main/java/classFileOutput/Example.class differ diff --git a/src/main/java/parser/ASTBuilder.java b/src/main/java/parser/ASTBuilder.java index 87b0238..ee61b9b 100644 --- a/src/main/java/parser/ASTBuilder.java +++ b/src/main/java/parser/ASTBuilder.java @@ -11,15 +11,14 @@ import ast.member.MethodNode; import ast.parameter.ParameterListNode; import ast.parameter.ParameterNode; import ast.statement.*; -import ast.type.AccessTypeNode; -import ast.type.EnumAccessTypeNode; -import ast.type.EnumTypeNode; -import ast.type.TypeNode; +import ast.type.*; import org.antlr.v4.runtime.tree.TerminalNode; + import java.util.ArrayList; import java.util.List; import parser.generated.*; import parser.generated.SimpleJavaParser.LiteralContext; +import ast.type.BaseTypeNode; public class ASTBuilder extends SimpleJavaBaseVisitor { @Override @@ -77,9 +76,9 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitParameter(SimpleJavaParser.ParameterContext ctx) { - TypeNode type = (TypeNode) visit(ctx.type()); + TypeNode typeNode = (TypeNode) visit(ctx.type()); String identifier = ctx.IDENTIFIER().getText(); - return new ParameterNode(type, identifier); + return new ParameterNode(typeNode, identifier); } @Override @@ -87,11 +86,11 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { String typeStr = ctx.getText(); switch (typeStr) { case "int": - return new TypeNode(EnumTypeNode.INT); + return new BaseTypeNode(EnumTypeNode.INT); case "boolean": - return new TypeNode(EnumTypeNode.BOOLEAN); + return new BaseTypeNode(EnumTypeNode.BOOLEAN); case "char": - return new TypeNode(EnumTypeNode.CHAR); + return new BaseTypeNode(EnumTypeNode.CHAR); default: throw new IllegalArgumentException("Unsupported type: " + typeStr); } @@ -207,6 +206,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { try { int intValue = Integer.parseInt(literalContext.getText()); LiteralNode literalNode = new LiteralNode(intValue); + literalNode.setType("int"); return literalNode; } catch (NumberFormatException ignored) {} diff --git a/src/main/java/semantic/Scope.java b/src/main/java/semantic/Scope.java new file mode 100644 index 0000000..ab5c0cb --- /dev/null +++ b/src/main/java/semantic/Scope.java @@ -0,0 +1,36 @@ +package semantic; + +import ast.type.TypeNode; + +import java.util.HashMap; +import java.util.Stack; + +public class Scope { + + private Stack> localVars; + + public void addLocalVar(String name, TypeNode type) { + if (this.contains(name)) { + throw new RuntimeException("Variable " + name + " already exists in this scope"); + } + localVars.peek().put(name, type); + } + + public boolean contains(String name) { + for (HashMap map : localVars) { + if (map.containsKey(name)) { + return true; + } + } + return false; + } + + public void pushScope() { + localVars.push(new HashMap()); + } + + public void popScope() { + localVars.pop(); + } + +} diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java index 07d0ca2..7a6002b 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -2,91 +2,145 @@ package semantic; import ast.*; -import ast.expression.ExpressionNode; -import ast.member.ConstructorNode; +import ast.expression.BinaryExpressionNode; +import ast.expression.IdentifierExpressionNode; +import ast.expression.UnaryExpressionNode; import ast.member.FieldNode; import ast.member.MemberNode; import ast.member.MethodNode; -import ast.statement.AssignmentStatementNode; -import ast.statement.StatementNode; +import ast.statement.*; + import java.util.ArrayList; import java.util.List; + import typechecker.TypeCheckResult; public class SemanticAnalyzer implements SemanticVisitor { - private ArrayList currentFields = new ArrayList<>(); + private ArrayList currentFields = new ArrayList<>(); - public static ASTNode generateTast(ASTNode node) throws RuntimeException { - SemanticAnalyzer semanticCheck = new SemanticAnalyzer(); - ProgramNode programNode = (ProgramNode) node; - var result = programNode.accept(semanticCheck); - if (result.isValid()) { - return node; - } else { - throw new RuntimeException("Not Valid"); - } - } + private Scope currentScope; - @Override - public TypeCheckResult typeCheck(ProgramNode node) { - - var valid = true; - - List classes = node.classes; - for (ClassNode classNode : classes) { - classNode.accept(this); - } - return new TypeCheckResult(valid, null); - } - - @Override - public TypeCheckResult typeCheck(ClassNode classNode) { - List members = classNode.members; - for (MemberNode memberNode : members) { - if (memberNode instanceof FieldNode fieldNode) { - fieldNode.accept(this); - } else if (memberNode instanceof MethodNode methodNode) { - methodNode.accept(this); - } + public static ASTNode generateTast(ASTNode node) throws RuntimeException { + SemanticAnalyzer semanticCheck = new SemanticAnalyzer(); + ProgramNode programNode = (ProgramNode) node; + var result = programNode.accept(semanticCheck); + if (result.isValid()) { + return node; + } else { + throw new RuntimeException("Not Valid"); + } } - return null; - } + @Override + public TypeCheckResult analyze(ProgramNode node) { - @Override - public TypeCheckResult typeCheck(MethodNode methodNode) { - List statements = methodNode.statements; - for (StatementNode statement : statements) { - if(statement instanceof AssignmentStatementNode assignmentStatementNode) { - assignmentStatementNode.accept(this); - } - } - return null; - } + var valid = true; - @Override - public TypeCheckResult typeCheck(FieldNode toCheck) { - if(currentFields.contains(toCheck.identifier)){ - throw new RuntimeException(toCheck.identifier + " Is Already Declared"); - }else { - currentFields.add(toCheck.identifier); + List classes = node.classes; + for (ClassNode classNode : classes) { + var result = classNode.accept(this); + valid = valid && result.isValid(); + } + return new TypeCheckResult(valid, null); } - return null; - } - @Override - public TypeCheckResult typeCheck(AssignmentStatementNode assignmentStatementNode) { - if(assignmentStatementNode.expression instanceof LiteralNode literalNode) { - VarNode varNode = assignmentStatementNode.varNode; - if(varNode.getType().equals(literalNode.getType())) { - System.out.println("Type is same"); - } else { - System.out.println("Type Mismatch"); - } + @Override + public TypeCheckResult analyze(ClassNode classNode) { + var valid = true; + List members = classNode.members; + for (MemberNode memberNode : members) { + if (memberNode instanceof FieldNode fieldNode) { + var result = fieldNode.accept(this); + valid = valid && result.isValid(); + } else if (memberNode instanceof MethodNode methodNode) { + var result = methodNode.accept(this); + valid = valid && result.isValid(); + } + } + + return new TypeCheckResult(valid, null); + + } + + @Override + public TypeCheckResult analyze(MethodNode methodNode) { + var valid = true; + + currentLocalScope.pushScope(); + + List statements = methodNode.statements; + for (StatementNode statement : statements) { + if (statement instanceof AssignmentStatementNode assignmentStatementNode) { + var result = assignmentStatementNode.accept(this); + valid = valid && result.isValid(); + } else if (statement instanceof VariableDeclarationStatementNode variableDeclarationStatementNode) { + var result = variableDeclarationStatementNode.accept(this); + valid = valid && result.isValid(); + } + } + return new TypeCheckResult(valid, null); + } + + @Override + public TypeCheckResult analyze(FieldNode toCheck) { + if (currentFields.contains(toCheck.identifier)) { + throw new RuntimeException(toCheck.identifier + " Is Already Declared"); + } else { + currentFields.add(toCheck.identifier); + } + return new TypeCheckResult(true, null); + } + + @Override + public TypeCheckResult analyze(AssignmentStatementNode assignmentStatementNode) { + if (assignmentStatementNode.expression instanceof LiteralNode literalNode) { + TypeCheckResult varResult = assignmentStatementNode.varNode.accept(this); + TypeCheckResult expressionResult = assignmentStatementNode.expression.accept(this); + } + return new TypeCheckResult(true, null); + } + + @Override + public TypeCheckResult analyze(VarNode toCheck) { + return new TypeCheckResult(true, null); + } + + @Override + public TypeCheckResult analyze(BinaryExpressionNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(IdentifierExpressionNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(UnaryExpressionNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(VariableDeclarationStatementNode toCheck) { + + return new TypeCheckResult(true, null); + } + + @Override + public TypeCheckResult analyze(IfStatementNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(ReturnStatementNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(WhileStatementNode toCheck) { + return null; } - return null; - } } \ No newline at end of file diff --git a/src/main/java/semantic/SemanticVisitor.java b/src/main/java/semantic/SemanticVisitor.java index 2fbaf41..99d0cb8 100644 --- a/src/main/java/semantic/SemanticVisitor.java +++ b/src/main/java/semantic/SemanticVisitor.java @@ -3,60 +3,40 @@ package semantic; import ast.ClassNode; import ast.ProgramNode; +import ast.VarNode; +import ast.expression.BinaryExpressionNode; +import ast.expression.IdentifierExpressionNode; +import ast.expression.UnaryExpressionNode; import ast.member.FieldNode; import ast.member.MethodNode; -import ast.statement.AssignmentStatementNode; +import ast.statement.*; import typechecker.TypeCheckResult; public interface SemanticVisitor { -// TypeCheckResult typeCheck(ASTNode toCheck); - TypeCheckResult typeCheck(ProgramNode toCheck); + TypeCheckResult analyze(ProgramNode toCheck); - TypeCheckResult typeCheck(ClassNode toCheck); + TypeCheckResult analyze(ClassNode toCheck); - TypeCheckResult typeCheck(MethodNode toCheck); + TypeCheckResult analyze(MethodNode toCheck); - TypeCheckResult typeCheck(FieldNode toCheck); + TypeCheckResult analyze(FieldNode toCheck); - TypeCheckResult typeCheck(AssignmentStatementNode toCheck); -// -// TypeCheckResult typeCheck(MethodParameter toCheck); -// -// TypeCheckResult typeCheck(ForStmt forStmt); -// -// TypeCheckResult typeCheck(WhileStmt whileStmt); -// -// TypeCheckResult typeCheck(ReturnStmt returnStmt); -// -// TypeCheckResult typeCheck(LocalVarDecl localVarDecl); -// -// TypeCheckResult typeCheck(IfStmt ifStmt); -// -// TypeCheckResult typeCheck(Block block); -// -// TypeCheckResult typeCheck(NewDecl newDecl); -// -// TypeCheckResult typeCheck(MethodCall methodCall); -// -// TypeCheckResult typeCheck(Unary unary); -// -// TypeCheckResult typeCheck(This aThis); -// -// TypeCheckResult typeCheck(Null aNull); -// -// TypeCheckResult typeCheck(LocalOrFieldVar localOrFieldVar); -// -// TypeCheckResult typeCheck(IntegerExpr integerExpr); -// -// TypeCheckResult typeCheck(InstVar instVar); -// -// TypeCheckResult typeCheck(CharExpr charExpr); -// -// TypeCheckResult typeCheck(BoolExpr boolExpr); -// -// TypeCheckResult typeCheck(Binary binary); -// -// TypeCheckResult typeCheck(StringExpr instVar); + TypeCheckResult analyze(AssignmentStatementNode toCheck); + TypeCheckResult analyze(VarNode toCheck); + + TypeCheckResult analyze(BinaryExpressionNode toCheck); + + TypeCheckResult analyze(IdentifierExpressionNode toCheck); + + TypeCheckResult analyze(UnaryExpressionNode toCheck); + + TypeCheckResult analyze(VariableDeclarationStatementNode toCheck); + + TypeCheckResult analyze(IfStatementNode toCheck); + + TypeCheckResult analyze(ReturnStatementNode toCheck); + + TypeCheckResult analyze(WhileStatementNode toCheck); } \ No newline at end of file diff --git a/src/main/java/typechecker/Type.java b/src/main/java/typechecker/Type.java deleted file mode 100644 index 89b1c16..0000000 --- a/src/main/java/typechecker/Type.java +++ /dev/null @@ -1,5 +0,0 @@ -package typechecker; - -public interface Type { - boolean equals(Object obj); -} \ No newline at end of file diff --git a/src/main/java/typechecker/TypeCheckResult.java b/src/main/java/typechecker/TypeCheckResult.java index 9068c0d..12143b2 100644 --- a/src/main/java/typechecker/TypeCheckResult.java +++ b/src/main/java/typechecker/TypeCheckResult.java @@ -1,12 +1,14 @@ package typechecker; +import ast.type.TypeNode; + public class TypeCheckResult { private boolean valid; - private Type type; + private TypeNode type; - public TypeCheckResult(boolean valid, Type type) { + public TypeCheckResult(boolean valid, TypeNode type) { this.valid = valid; this.type = type; } @@ -15,7 +17,7 @@ public class TypeCheckResult { return valid; } - public Type getType() { + public TypeNode getType() { return type; } } \ No newline at end of file diff --git a/src/main/java/typechecker/Typer.java b/src/main/java/typechecker/Typer.java deleted file mode 100644 index 3f8872a..0000000 --- a/src/main/java/typechecker/Typer.java +++ /dev/null @@ -1,9 +0,0 @@ -package typechecker; - -public class Typer { - - public static void Typeify(){ - - } - -} diff --git a/src/main/java/typechecker/Visitable.java b/src/main/java/typechecker/Visitable.java deleted file mode 100644 index 99694b7..0000000 --- a/src/main/java/typechecker/Visitable.java +++ /dev/null @@ -1,16 +0,0 @@ -package typechecker; - -import semantic.SemanticVisitor; - -public interface Visitable { -// default void accept(ProgramCodeVisitor visitor) { -// } -// -// default void accept(ClassCodeVisitor visitor) { -// } -// -// default void accept(MethodCodeVisitor visitor) { -// } - - TypeCheckResult accept(SemanticVisitor visitor); -} diff --git a/src/main/java/visitor/Visitable.java b/src/main/java/visitor/Visitable.java new file mode 100644 index 0000000..bd69777 --- /dev/null +++ b/src/main/java/visitor/Visitable.java @@ -0,0 +1,21 @@ +package visitor; + +import bytecode.visitor.ClassVisitor; +import bytecode.visitor.MethodVisitor; +import bytecode.visitor.ProgramVisitor; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; + +public interface Visitable { + default void accept(ProgramVisitor programVisitor) { + + } + default void accept(ClassVisitor classVisitor) { + + } + default void accept(MethodVisitor methodVisitor) { + + } + + TypeCheckResult accept(SemanticVisitor visitor); +}