Added Basic RefTypes to InstVar and SematicCheck
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run

This commit is contained in:
Bruder John 2024-06-12 17:33:59 +02:00
parent 56d316a6d0
commit e552bd5ada
31 changed files with 566 additions and 58 deletions

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

13
pom.xml
View File

@ -27,13 +27,22 @@
<artifactId>antlr4-runtime</artifactId>
<version>4.13.1</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.7</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.16.0</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.26.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>

View File

@ -20,6 +20,8 @@ public class ClassNode implements ASTNode, Visitable {
public List<MemberNode> members = new ArrayList<>();
public boolean hasConstructor = false;
public ClassNode() {}
public ClassNode(AccessTypeNode accessType, String identifier){
this.accessType = accessType;
this.identifier = identifier;

View File

@ -1,8 +1,25 @@
package ast.expression;
import ast.ASTNode;
import ast.statement.AssignmentStatementNode;
import ast.statement.IfStatementNode;
import ast.statement.VariableDeclarationStatementNode;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import visitor.Visitable;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonSubTypes({
@JsonSubTypes.Type(value = BinaryExpressionNode.class, name = "Binary"),
@JsonSubTypes.Type(value = This.class, name = "This"),
@JsonSubTypes.Type(value = InstVar.class, name = "InstVar"),
@JsonSubTypes.Type(value = IdentifierExpressionNode.class, name = "Identifier"),
@JsonSubTypes.Type(value = LiteralNode.class, name = "Literal"),
@JsonSubTypes.Type(value = UnaryExpressionNode.class, name = "Unary")}
)
public interface ExpressionNode extends ASTNode, Visitable {
}

View File

@ -10,6 +10,7 @@ public class InstVar implements ExpressionNode, Visitable {
public ExpressionNode expression;
public TypeNode type;
public InstVar(){}
public InstVar(ExpressionNode expression, String identifier) {
this.identifier = identifier;

View File

@ -1,23 +1,25 @@
package ast;
package ast.expression;
import ast.expression.ExpressionNode;
import ast.type.TypeNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class LiteralNode implements ExpressionNode {
int value;
private String type;
private TypeNode type;
public LiteralNode(){}
public LiteralNode(int value) {
this.value = value;
}
public String getType() {
public TypeNode getType() {
return type;
}
public void setType(String type) {
public void setType(TypeNode type) {
this.type = type;
}

View File

@ -0,0 +1,26 @@
package ast.expression;
import ast.ASTNode;
import ast.type.ReferenceTypeNode;
import ast.type.TypeNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class This implements ASTNode, ExpressionNode {
private TypeNode type;
public This(){}
public This(String className) {
type = new ReferenceTypeNode(className);
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
public TypeNode getType() {
return type;
}
}

View File

@ -12,6 +12,8 @@ public class FieldNode implements MemberNode, Visitable {
public TypeNode type;
public String identifier;
public FieldNode(){}
public FieldNode(AccessTypeNode accessTypeNode, TypeNode type, String name){
this.accessTypeNode = accessTypeNode;
this.type = type;

View File

@ -1,6 +1,18 @@
package ast.member;
import ast.ASTNode;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonSubTypes({
@JsonSubTypes.Type(value = MethodNode.class, name = "Method"),
@JsonSubTypes.Type(value = FieldNode.class, name = "Field") }
)
public interface MemberNode extends ASTNode {
}

View File

@ -22,6 +22,8 @@ public class MethodNode implements MemberNode, Visitable {
public List<StatementNode> statements = new ArrayList<>();
public MethodNode(){}
public MethodNode(AccessTypeNode visibility, TypeNode type, String identifier, ParameterListNode parameters,
List<StatementNode> statements){
this.visibility = visibility;

View File

@ -8,6 +8,8 @@ import java.util.List;
public class ParameterListNode implements ASTNode {
public List<ParameterNode> parameters = new ArrayList<>();
public ParameterListNode() {}
public ParameterListNode(List<ParameterNode> parameters){
this.parameters = parameters;
}

View File

@ -7,6 +7,8 @@ public class ParameterNode implements ASTNode {
public TypeNode type;
public String identifier;
public ParameterNode(){}
public ParameterNode(TypeNode type, String identifier) {
this.type = type;
this.identifier = identifier;

View File

@ -10,7 +10,9 @@ import visitor.Visitable;
public class AssignmentStatementNode extends StatementNode implements Visitable {
public ExpressionNode expressionLeft;
public ExpressionNode expressionRight;
public TypeNode type;
// public TypeNode type;
public AssignmentStatementNode(){}
public AssignmentStatementNode(ExpressionNode expressionLeft, ExpressionNode expressionRight) {
this.expressionLeft = expressionLeft;

View File

@ -1,8 +1,22 @@
package ast.statement;
import ast.ASTNode;
import ast.type.BaseTypeNode;
import ast.type.ReferenceTypeNode;
import visitor.Visitable;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonSubTypes({
@JsonSubTypes.Type(value = IfStatementNode.class, name = "IF"),
@JsonSubTypes.Type(value = AssignmentStatementNode.class, name = "Assignment"),
@JsonSubTypes.Type(value = VariableDeclarationStatementNode.class, name = "VariableDeclaration") }
)
public abstract class StatementNode implements ASTNode, Visitable {
}

View File

@ -9,6 +9,9 @@ public class VariableDeclarationStatementNode extends StatementNode {
public TypeNode type;
public String identifier;
public ExpressionNode expression;
public VariableDeclarationStatementNode(){}
public VariableDeclarationStatementNode(TypeNode type, String identifier, ExpressionNode expression) {
this.type = type;
this.identifier = identifier;

View File

@ -5,6 +5,8 @@ import ast.ASTNode;
public class AccessTypeNode implements ASTNode {
public EnumAccessTypeNode enumAccessTypeNode;
public AccessTypeNode(){}
public AccessTypeNode(EnumAccessTypeNode enumAccessTypeNode) {
this.enumAccessTypeNode = enumAccessTypeNode;
}

View File

@ -6,6 +6,8 @@ public class BaseTypeNode implements ASTNode, TypeNode {
public EnumTypeNode enumType;
public BaseTypeNode(){}
public BaseTypeNode(EnumTypeNode enumType) {
this.enumType = enumType;
}

View File

@ -3,4 +3,34 @@ package ast.type;
import ast.ASTNode;
public class ReferenceTypeNode implements ASTNode, TypeNode {
private String identifier;
public ReferenceTypeNode() {}
public ReferenceTypeNode(String identifier) {
this.identifier = identifier;
}
public String getIdentifier() {
return identifier;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ReferenceTypeNode other = (ReferenceTypeNode) obj;
if (identifier == null) {
if (other.identifier != null)
return false;
} else if (!identifier.equals(other.identifier))
return false;
return true;
}
}

View File

@ -1,13 +0,0 @@
package ast.type;
import ast.ASTNode;
import ast.expression.ExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class This implements ASTNode, ExpressionNode {
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return null;
}
}

View File

@ -2,5 +2,17 @@ package ast.type;
import ast.ASTNode;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonSubTypes({
@JsonSubTypes.Type(value = BaseTypeNode.class, name = "Base"),
@JsonSubTypes.Type(value = ReferenceTypeNode.class, name = "Reference") }
)
public interface TypeNode extends ASTNode {
}

View File

@ -1,11 +1,7 @@
package parser;
import ast.*;
import ast.expression.BinaryExpressionNode;
import ast.expression.ExpressionNode;
import ast.expression.ExpresssionOperator;
import ast.expression.IdentifierExpressionNode;
import ast.expression.UnaryExpressionNode;
import ast.expression.*;
import ast.member.FieldNode;
import ast.member.MemberNode;
import ast.member.MethodNode;
@ -210,7 +206,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
int intValue = Integer.parseInt(literalContext.getText());
LiteralNode literalNode = new LiteralNode(intValue);
literalNode.setType("int");
literalNode.setType(new BaseTypeNode(EnumTypeNode.INT));
return literalNode;
} catch (NumberFormatException ignored) {}

View File

@ -10,6 +10,9 @@ import ast.member.MethodNode;
import ast.parameter.ParameterListNode;
import ast.parameter.ParameterNode;
import ast.statement.*;
import ast.type.ReferenceTypeNode;
import ast.expression.This;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -17,8 +20,8 @@ import java.util.Objects;
import ast.type.BaseTypeNode;
import ast.type.EnumTypeNode;
import ast.type.This;
import ast.type.TypeNode;
import semantic.context.Context;
import semantic.exeptions.AlreadyDeclearedException;
import semantic.exeptions.NotDeclearedException;
import semantic.exeptions.TypeMismatchException;
@ -30,6 +33,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
public static ArrayList<Exception> errors = new ArrayList<>();
private Context context;
private static Scope currentScope;
private static ClassNode currentClass;
@ -60,6 +64,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
var valid = true;
currentScope = new Scope();
context = new Context(node);
List<ClassNode> classes = node.classes;
for (ClassNode classNode : classes) {
@ -74,7 +79,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
var valid = true;
currentClass = classNode;
currentFields.clear();
List<MemberNode> members = classNode.members;
for (MemberNode memberNode : members) {
if (memberNode instanceof FieldNode fieldNode) {
@ -238,23 +243,38 @@ public class SemanticAnalyzer implements SemanticVisitor {
@Override
public TypeCheckResult analyze(LiteralNode toCheck) {
return new TypeCheckResult(true, new BaseTypeNode(EnumTypeNode.INT));
return new TypeCheckResult(true, toCheck.getType());
}
@Override
public TypeCheckResult analyze(InstVar toCheck) {
boolean valid = true;
if(toCheck.expression instanceof This){
if(currentFields.get(toCheck.identifier) == null){
errors.add(new NotDeclearedException("Not declared " + toCheck.identifier + " in this scope"));
valid = false;
var result = toCheck.expression.accept(this);
if(result.getType() instanceof BaseTypeNode){
throw new RuntimeException("BaseType has no Methods or Fields");
} else {
TypeNode typeNode = currentFields.get(toCheck.identifier);
return new TypeCheckResult(valid, typeNode);
//Get typ of Field
var type = (ReferenceTypeNode)result.getType();
var classContext = context.getClass(type.getIdentifier());
if(classContext == null){
errors.add(new NotDeclearedException("Not declared " + type.getIdentifier() + " in this scope"));
return new TypeCheckResult(false, null);
} else {
var field = classContext.getField(toCheck.identifier);
return new TypeCheckResult(valid, field.getType());
}
}
return new TypeCheckResult(valid, null);
}
}
@Override
public TypeCheckResult analyze(This toCheck) {
return new TypeCheckResult(true, toCheck.getType());
}
}

View File

@ -2,7 +2,7 @@ package semantic;
import ast.ClassNode;
import ast.LiteralNode;
import ast.expression.LiteralNode;
import ast.ProgramNode;
import ast.expression.BinaryExpressionNode;
import ast.expression.IdentifierExpressionNode;
@ -11,6 +11,7 @@ import ast.expression.UnaryExpressionNode;
import ast.member.FieldNode;
import ast.member.MethodNode;
import ast.statement.*;
import ast.expression.This;
import typechecker.TypeCheckResult;
public interface SemanticVisitor {
@ -42,4 +43,6 @@ public interface SemanticVisitor {
TypeCheckResult analyze(LiteralNode toCheck);
TypeCheckResult analyze(InstVar toCheck);
TypeCheckResult analyze(This toCheck);
}

View File

@ -0,0 +1,27 @@
package semantic.context;
import ast.ClassNode;
import ast.member.FieldNode;
import java.util.HashMap;
public class ClassContext {
private HashMap<String, FieldContext> fields;
public ClassContext(ClassNode classNode) {
fields = new HashMap<>();
classNode.members.forEach(member -> {
if(member instanceof FieldNode fieldNode) {
fields.put(fieldNode.identifier, new FieldContext(fieldNode));
}
});
}
public FieldContext getField(String name) {
return fields.get(name);
}
}

View File

@ -0,0 +1,25 @@
package semantic.context;
import ast.ClassNode;
import ast.ProgramNode;
import java.util.HashMap;
public class Context {
private HashMap<String, ClassContext> classes;
public Context(ProgramNode programNode) {
classes = new HashMap<>();
programNode.classes.forEach(classNode -> {
ClassContext classContext = new ClassContext(classNode);
classes.put(classNode.identifier, classContext);
});
}
public ClassContext getClass(String identifier) {
return classes.get(identifier);
}
}

View File

@ -0,0 +1,22 @@
package semantic.context;
import ast.member.FieldNode;
import ast.type.AccessTypeNode;
import ast.type.EnumAccessTypeNode;
import ast.type.TypeNode;
public class FieldContext {
private AccessTypeNode accessModifier;
private TypeNode type;
public FieldContext(FieldNode field) {
accessModifier = field.accessTypeNode;
type = field.type;
}
public TypeNode getType() {
return type;
}
}

View File

@ -1,7 +1,7 @@
package semantic;
import ast.ClassNode;
import ast.LiteralNode;
import ast.expression.LiteralNode;
import ast.ProgramNode;
import ast.expression.*;
import ast.member.FieldNode;
@ -39,16 +39,14 @@ public class Mocker {
List<StatementNode> statementNodeList = new ArrayList<StatementNode>();
ExpressionNode expressionNodeLeft = new InstVar(new This(), "objectVar");
ExpressionNode expressionNodeLeft = new InstVar(new This("testClass"), "objectVar");
ExpressionNode expressionNodeRight = new LiteralNode(1);
LiteralNode expressionNodeRight = new LiteralNode();
expressionNodeRight.setType(new BaseTypeNode(EnumTypeNode.INT));
StatementNode statementNode1 = new AssignmentStatementNode(expressionNodeLeft, expressionNodeRight);
statementNodeList.add(statementNode1);
StatementNode statementNode2 = new VariableDeclarationStatementNode(new BaseTypeNode(EnumTypeNode.CHAR), "objectVar", new LiteralNode(1));
statementNodeList.add(statementNode2);
MemberNode memberNode3 = new MethodNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar2",parameterListNode, statementNodeList );
classNode.members.add(memberNode3);
@ -76,5 +74,4 @@ public class Mocker {
return programNode;
}
}

View File

@ -2,20 +2,19 @@ package semantic;
import ast.*;
import ast.member.FieldNode;
import ast.member.MemberNode;
import ast.type.AccessTypeNode;
import ast.type.BaseTypeNode;
import ast.type.EnumAccessTypeNode;
import ast.type.EnumTypeNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.assertj.core.api.MatcherAssert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import semantic.exeptions.AlreadyDeclearedException;
import semantic.exeptions.TypeMismatchException;
import java.util.ArrayList;
import java.util.List;
import java.io.File;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class SemanticTest {
@ -44,7 +43,7 @@ public class SemanticTest {
}
@Test
public void typeMismatch(){
public void alreadyDecleared() {
//Arrange
@ -57,8 +56,8 @@ public class SemanticTest {
//Assert
assertEquals(1, SemanticAnalyzer.errors.size());
assertEquals(true, SemanticAnalyzer.errors.get(0) instanceof AlreadyDeclearedException);
assertEquals(null, typedAst);
assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst());
assertNull(typedAst);
}
@ -80,4 +79,85 @@ public class SemanticTest {
}
@Test
public void refTypeCorrect() {
//Arrange
ObjectMapper objectMapper = new ObjectMapper();
ProgramNode programNode = null;
try{
programNode = objectMapper.readValue(new File("src/test/resources/semantic/correctRefType.json"), ProgramNode.class);
} catch (Exception e) {
e.printStackTrace();
}
//Act
ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
//Assert
assertEquals(0, SemanticAnalyzer.errors.size());
assertEquals(programNode, typedAst);
}
@Test
public void jsonWriteTest() {
ObjectMapper objectMapper = new ObjectMapper();
//Arrange
ProgramNode programNode = Mocker.mockCorrectProgrammNode();
try{
objectMapper.writeValue(new File("src/test/resources/semantic/test.json"), programNode);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void jsonReadTest() {
ObjectMapper objectMapper = new ObjectMapper();
ProgramNode programNode1 = null;
try{
programNode1 = objectMapper.readValue(new File("src/test/resources/semantic/test.json"), ProgramNode.class);
} catch (Exception e) {
e.printStackTrace();
}
ProgramNode programNode2 = Mocker.mockCorrectProgrammNode();
}
@Test
public void typeMismatch() {
//Arrange
ObjectMapper objectMapper = new ObjectMapper();
ProgramNode programNode = null;
try{
programNode = objectMapper.readValue(new File("src/test/resources/semantic/refTypeMismatch.json"), ProgramNode.class);
} catch (Exception e) {
e.printStackTrace();
}
//Act
ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
//Assert
assertEquals(1, SemanticAnalyzer.errors.size());
assertInstanceOf(TypeMismatchException.class, SemanticAnalyzer.errors.getFirst());
assertNull(typedAst);
}
}

View File

@ -0,0 +1,70 @@
{
"classes": [
{
"identifier": "testClass1",
"accessType": {
"enumAccessTypeNode": "PUBLIC"
},
"members": [
{
"@type": "Field",
"accessTypeNode": {
"enumAccessTypeNode": "PUBLIC"
},
"type": {
"@type": "Base",
"enumType": "INT"
},
"identifier": "testVar1"
},
{
"@type": "Method",
"visibility": {
"enumAccessTypeNode": "PUBLIC"
},
"type": {
"@type": "Base",
"enumType": "INT"
},
"identifier": "testMethod",
"parameters": {
"parameters": [
{
"type": {
"@type": "Base",
"enumType": "INT"
},
"identifier": "param1"
}
]
},
"statements": [
{
"@type": "Assignment",
"expressionLeft": {
"@type": "InstVar",
"identifier": "testVar1",
"expression": {
"@type": "This",
"type": {
"@type": "Reference",
"identifier": "testClass1"
}
},
"type": null
},
"expressionRight": {
"@type": "Literal",
"type": {
"@type": "Base",
"enumType": "INT"
}
}
}
]
}
],
"hasConstructor": false
}
]
}

View File

@ -0,0 +1,133 @@
{
"classes": [
{
"identifier": "testClass1",
"accessType": {
"enumAccessTypeNode": "PUBLIC"
},
"members": [
{
"@type": "Field",
"accessTypeNode": {
"enumAccessTypeNode": "PUBLIC"
},
"type": {
"@type": "Base",
"enumType": "INT"
},
"identifier": "testVar1"
},
{
"@type": "Method",
"visibility": {
"enumAccessTypeNode": "PUBLIC"
},
"type": {
"@type": "Base",
"enumType": "INT"
},
"identifier": "testMethod",
"parameters": {
"parameters": [
{
"type": {
"@type": "Base",
"enumType": "INT"
},
"identifier": "param1"
}
]
},
"statements": [
{
"@type": "Assignment",
"expressionLeft": {
"@type": "InstVar",
"identifier": "testVar1",
"expression": {
"@type": "This",
"type": {
"@type": "Reference",
"identifier": "testClass1"
}
},
"type": null
},
"expressionRight": {
"@type": "Literal",
"type": {
"@type": "Base",
"enumType": "BOOLEAN"
}
}
}
]
}
],
"hasConstructor": false,
"methods": [
{
"@type": "Method",
"visibility": {
"enumAccessTypeNode": "PUBLIC"
},
"type": {
"@type": "Base",
"enumType": "INT"
},
"identifier": "testMethod",
"parameters": {
"parameters": [
{
"type": {
"@type": "Base",
"enumType": "INT"
},
"identifier": "param1"
}
]
},
"statements": [
{
"@type": "Assignment",
"expressionLeft": {
"@type": "InstVar",
"identifier": "testVar",
"expression": {
"@type": "InstVar",
"identifier": "testVar",
"expression": {
"@type": "This",
"type": {
"@type": "Reference",
"identifier": "testClass2"
}
},
"type": null
},
"type": null
},
"expressionRight": {
"@type": "Literal",
"type": null
},
"type": null
},
{
"@type": "VariableDeclaration",
"type": {
"@type": "Base",
"enumType": "CHAR"
},
"identifier": "objectVar",
"expression": {
"@type": "Literal",
"type": null
}
}
]
}
]
}
]
}

View File

@ -0,0 +1 @@
{"classes":[{"identifier":"testClass","accessType":{"enumAccessTypeNode":"PUBLIC"},"members":[{"@type":"Field","accessTypeNode":{"enumAccessTypeNode":"PUBLIC"},"type":{"@type":"Base","enumType":"INT"},"identifier":"testVar1"},{"@type":"Field","accessTypeNode":{"enumAccessTypeNode":"PUBLIC"},"type":{"@type":"Base","enumType":"INT"},"identifier":"objectVar"},{"@type":"Method","visibility":{"enumAccessTypeNode":"PUBLIC"},"type":{"@type":"Base","enumType":"INT"},"identifier":"testVar2","parameters":{"parameters":[{"type":{"@type":"Base","enumType":"INT"},"identifier":"param1"}]},"statements":[{"@type":"Assignment","expressionLeft":{"@type":"InstVar","identifier":"objectVar","expression":{"@type":"This","type":{"@type":"Reference","identifier":"testClass"}},"type":null},"expressionRight":{"@type":"Literal","type":{"@type":"Base","enumType":"INT"}}}]}],"hasConstructor":false,"methods":[{"@type":"Method","visibility":{"enumAccessTypeNode":"PUBLIC"},"type":{"@type":"Base","enumType":"INT"},"identifier":"testVar2","parameters":{"parameters":[{"type":{"@type":"Base","enumType":"INT"},"identifier":"param1"}]},"statements":[{"@type":"Assignment","expressionLeft":{"@type":"InstVar","identifier":"objectVar","expression":{"@type":"This","type":{"@type":"Reference","identifier":"testClass"}},"type":null},"expressionRight":{"@type":"Literal","type":{"@type":"Base","enumType":"INT"}}}]}]}]}