(); :}
+ ;
+
+/* bin_op */ //We may still be able to use bin_op, so I left it here.
+bin_op ::= PLUS:a {: RESULT = new StringLiteral(axleft, axright, "+"); :}
+ | MINUS:a {: RESULT = new StringLiteral(axleft, axright, "-"); :}
+ | MUL:a {: RESULT = new StringLiteral(axleft, axright, "*"); :}
+ | DIV:a {: RESULT = new StringLiteral(axleft, axright, "//"); :} //Section 2.6.3 in chocopy language reference
+ | MOD:a {: RESULT = new StringLiteral(axleft, axright, "%"); :}
+ ;
+
+
+/* comp_op */ //this might also need some change in order not to break left associativity
+comp_op ::= EQUAL:a {: RESULT = new StringLiteral(axleft, axright, "=="); :}
+ | NEQ:a {: RESULT = new StringLiteral(axleft, axright, "!="); :}
+ | LEQ:a {: RESULT = new StringLiteral(axleft, axright, "<="); :}
+ | GEQ:a {: RESULT = new StringLiteral(axleft, axright, ">="); :}
+ | LT:a {: RESULT = new StringLiteral(axleft, axright, "<"); :}
+ | GT:a {: RESULT = new StringLiteral(axleft, axright, ">"); :}
+ | IS:a {: RESULT = new StringLiteral(axleft, axright, "is"); :}
+ ;
+
+
+/* member_expr */
+member_expr ::= pexpr:p DOT identifier:id {: RESULT = new MemberExpr(pxleft, idxright, p, id); :}
+ ;
+
+
+/* index_expr */
+index_expr ::= pexpr:p LBR expr:e RBR:rbr {: RESULT = new IndexExpr(pxleft, rbrxright, p, e); :}
+ ;
+
+
+/* target */
+target ::= identifier:id {: RESULT = id; :}
+ | member_expr:m {: RESULT = m; :}
+ | index_expr:i {: RESULT = i; :}
+ ;
+
+
+/* Extras - rules below have not been given in language reference, we have them to ease implementation */
+identifier ::= ID:idStr {: RESULT = new Identifier(idStrxleft, idStrxright, idStr); :};
+
+
+stmt_list ::= stmt:s {: RESULT = single(s); :}
+ | stmt_list:l stmt:s {: RESULT = combine(l, s); :}
+ | stmt_list:l error {: RESULT = l; :}
+ /* If there is a syntax error in the source, this says to discard
+ * symbols from the parsing stack and perform reductions until
+ * there is a stmt_list on top of the stack, and then to discard
+ * input symbols until it is possible to shift again, reporting
+ * a syntax error. */
+ ;
\ No newline at end of file
diff --git a/src/main/java/chocopy/common/Utils.java b/src/main/java/chocopy/common/Utils.java
index aefd409..82b5dd7 100644
--- a/src/main/java/chocopy/common/Utils.java
+++ b/src/main/java/chocopy/common/Utils.java
@@ -6,6 +6,7 @@ import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
+
/** Utility functions for general use. */
public class Utils {
diff --git a/src/main/java/chocopy/common/analysis/NodeAnalyzer.java b/src/main/java/chocopy/common/analysis/NodeAnalyzer.java
index 2326fbc..331ebc4 100644
--- a/src/main/java/chocopy/common/analysis/NodeAnalyzer.java
+++ b/src/main/java/chocopy/common/analysis/NodeAnalyzer.java
@@ -19,6 +19,29 @@ import chocopy.common.astnodes.*;
* The class AbstractNodeAnalyzer provides empty default implementations for these methods.
*
*
The type T is the type of result returned by the encapsulated analysis.
+=======
+ * This interface can be used to separate logic for various concrete
+ * classes in the AST class hierarchy.
+ *
+ * The idea is that a phase of the analysis is encapsulated in a class
+ * that implements this interface, and contains an overriding of the
+ * analyze method for each concrete Node class that needs something
+ * other than default processing. Each concrete node class, C, implements
+ * a generic dispatch method that takes a NodeAnalyzer argument and
+ * calls the overloading of analyze that takes an argument of type C.
+ * The effect is that anode.dispatch(anAnalyzer) executes the method
+ * anAnalyzer.analyze that is appropriate to aNode's dynamic type.
+ * As a result each NodeAnalyzer subtype encapsulates all
+ * implementations of a particular action on Nodes. Thus, it inverts
+ * the usual OO pattern in which the implementations of analysis A for
+ * each different class are scattered among the class bodies
+ * themselves as overridings of a method A on the Node class.
+ *
+ * The class AbstractNodeAnalyzer provides empty default
+ * implementations for these methods.
+ *
+ * The type T is the type of result returned by the encapsulated analysis.
+>>>>>>> pa1/master
*/
public interface NodeAnalyzer {
diff --git a/src/main/java/chocopy/common/astnodes/AssignStmt.java b/src/main/java/chocopy/common/astnodes/AssignStmt.java
index 1452463..04b31ef 100644
--- a/src/main/java/chocopy/common/astnodes/AssignStmt.java
+++ b/src/main/java/chocopy/common/astnodes/AssignStmt.java
@@ -5,6 +5,7 @@ import java_cup.runtime.ComplexSymbolFactory.Location;
import java.util.List;
+
/** Single and multiple assignments. */
public class AssignStmt extends Stmt {
/** List of left-hand sides. */
diff --git a/src/main/java/chocopy/common/astnodes/BinaryExpr.java b/src/main/java/chocopy/common/astnodes/BinaryExpr.java
index f4ce05b..8dabb9c 100644
--- a/src/main/java/chocopy/common/astnodes/BinaryExpr.java
+++ b/src/main/java/chocopy/common/astnodes/BinaryExpr.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** . */
public class BinaryExpr extends Expr {
diff --git a/src/main/java/chocopy/common/astnodes/BooleanLiteral.java b/src/main/java/chocopy/common/astnodes/BooleanLiteral.java
index ffce126..2d41a64 100644
--- a/src/main/java/chocopy/common/astnodes/BooleanLiteral.java
+++ b/src/main/java/chocopy/common/astnodes/BooleanLiteral.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** Literals True or False. */
public final class BooleanLiteral extends Literal {
diff --git a/src/main/java/chocopy/common/astnodes/CallExpr.java b/src/main/java/chocopy/common/astnodes/CallExpr.java
index 84f13ae..74f7ab1 100644
--- a/src/main/java/chocopy/common/astnodes/CallExpr.java
+++ b/src/main/java/chocopy/common/astnodes/CallExpr.java
@@ -5,6 +5,7 @@ import java_cup.runtime.ComplexSymbolFactory.Location;
import java.util.List;
+
/** A function call. */
public class CallExpr extends Expr {
diff --git a/src/main/java/chocopy/common/astnodes/ClassDef.java b/src/main/java/chocopy/common/astnodes/ClassDef.java
index 63531c8..02f43cc 100644
--- a/src/main/java/chocopy/common/astnodes/ClassDef.java
+++ b/src/main/java/chocopy/common/astnodes/ClassDef.java
@@ -5,6 +5,7 @@ import java_cup.runtime.ComplexSymbolFactory.Location;
import java.util.List;
+
/** A class definition. */
public class ClassDef extends Declaration {
diff --git a/src/main/java/chocopy/common/astnodes/ClassType.java b/src/main/java/chocopy/common/astnodes/ClassType.java
index fd4cd4d..57117cb 100644
--- a/src/main/java/chocopy/common/astnodes/ClassType.java
+++ b/src/main/java/chocopy/common/astnodes/ClassType.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** A simple class type name. */
public final class ClassType extends TypeAnnotation {
diff --git a/src/main/java/chocopy/common/astnodes/CompilerError.java b/src/main/java/chocopy/common/astnodes/CompilerError.java
index 81cc5bb..960c0d4 100644
--- a/src/main/java/chocopy/common/astnodes/CompilerError.java
+++ b/src/main/java/chocopy/common/astnodes/CompilerError.java
@@ -7,6 +7,7 @@ import java_cup.runtime.ComplexSymbolFactory.Location;
import java.util.Arrays;
import java.util.Objects;
+
/** Represents a single error. Does not correspond to any Python source construct. */
public class CompilerError extends Node {
@@ -49,6 +50,7 @@ public class CompilerError extends Node {
return analyzer.analyze(this);
}
+
/** The error message. */
public final String message;
/** True if this is a syntax error. */
diff --git a/src/main/java/chocopy/common/astnodes/Declaration.java b/src/main/java/chocopy/common/astnodes/Declaration.java
index 0faa921..db660f7 100644
--- a/src/main/java/chocopy/common/astnodes/Declaration.java
+++ b/src/main/java/chocopy/common/astnodes/Declaration.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** Base of all AST nodes representing definitions or declarations. */
public abstract class Declaration extends Node {
@@ -11,6 +12,7 @@ public abstract class Declaration extends Node {
super(left, right);
}
+
/** Return the identifier defined by this Declaration. */
@JsonIgnore
public abstract Identifier getIdentifier();
diff --git a/src/main/java/chocopy/common/astnodes/Errors.java b/src/main/java/chocopy/common/astnodes/Errors.java
index 86240dd..ef03a8a 100644
--- a/src/main/java/chocopy/common/astnodes/Errors.java
+++ b/src/main/java/chocopy/common/astnodes/Errors.java
@@ -7,6 +7,7 @@ import java_cup.runtime.ComplexSymbolFactory.Location;
import java.util.List;
+
/** Collects the error messages in a Program. There is exactly one per Program node. */
public class Errors extends Node {
@@ -26,11 +27,13 @@ public class Errors extends Node {
allowMultipleErrors = true;
}
+
/** Return true iff there are any errors. */
public boolean hasErrors() {
return !this.errors.isEmpty();
}
+
/** Prevent multiple semantic errors on the same node. */
public void suppressMultipleErrors() {
allowMultipleErrors = false;
diff --git a/src/main/java/chocopy/common/astnodes/Expr.java b/src/main/java/chocopy/common/astnodes/Expr.java
index 7372d58..81270b7 100644
--- a/src/main/java/chocopy/common/astnodes/Expr.java
+++ b/src/main/java/chocopy/common/astnodes/Expr.java
@@ -1,5 +1,6 @@
package chocopy.common.astnodes;
+
import chocopy.common.analysis.types.Type;
import com.fasterxml.jackson.annotation.JsonInclude;
import java_cup.runtime.ComplexSymbolFactory.Location;
diff --git a/src/main/java/chocopy/common/astnodes/ExprStmt.java b/src/main/java/chocopy/common/astnodes/ExprStmt.java
index 5b921a0..3533db3 100644
--- a/src/main/java/chocopy/common/astnodes/ExprStmt.java
+++ b/src/main/java/chocopy/common/astnodes/ExprStmt.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** Statements consisting of expressions. */
public final class ExprStmt extends Stmt {
diff --git a/src/main/java/chocopy/common/astnodes/ForStmt.java b/src/main/java/chocopy/common/astnodes/ForStmt.java
index 019b2d8..f7c9e46 100644
--- a/src/main/java/chocopy/common/astnodes/ForStmt.java
+++ b/src/main/java/chocopy/common/astnodes/ForStmt.java
@@ -5,6 +5,7 @@ import java_cup.runtime.ComplexSymbolFactory.Location;
import java.util.List;
+
/** For statements. */
public class ForStmt extends Stmt {
/** Control variable. */
diff --git a/src/main/java/chocopy/common/astnodes/FuncDef.java b/src/main/java/chocopy/common/astnodes/FuncDef.java
index b3ca0f2..4800bd1 100644
--- a/src/main/java/chocopy/common/astnodes/FuncDef.java
+++ b/src/main/java/chocopy/common/astnodes/FuncDef.java
@@ -5,6 +5,7 @@ import java_cup.runtime.ComplexSymbolFactory.Location;
import java.util.List;
+
/** Def statements. */
public class FuncDef extends Declaration {
diff --git a/src/main/java/chocopy/common/astnodes/GlobalDecl.java b/src/main/java/chocopy/common/astnodes/GlobalDecl.java
index b347d4d..f281347 100644
--- a/src/main/java/chocopy/common/astnodes/GlobalDecl.java
+++ b/src/main/java/chocopy/common/astnodes/GlobalDecl.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** Declaration of global variable. */
public class GlobalDecl extends Declaration {
diff --git a/src/main/java/chocopy/common/astnodes/Identifier.java b/src/main/java/chocopy/common/astnodes/Identifier.java
index 7593126..f65ab06 100644
--- a/src/main/java/chocopy/common/astnodes/Identifier.java
+++ b/src/main/java/chocopy/common/astnodes/Identifier.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** A simple identifier. */
public class Identifier extends Expr {
diff --git a/src/main/java/chocopy/common/astnodes/IfExpr.java b/src/main/java/chocopy/common/astnodes/IfExpr.java
index 3d3d809..b76cbcb 100644
--- a/src/main/java/chocopy/common/astnodes/IfExpr.java
+++ b/src/main/java/chocopy/common/astnodes/IfExpr.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** Conditional expressions. */
public class IfExpr extends Expr {
/** Boolean condition. */
diff --git a/src/main/java/chocopy/common/astnodes/IfStmt.java b/src/main/java/chocopy/common/astnodes/IfStmt.java
index 185b8a1..d2b0bf4 100644
--- a/src/main/java/chocopy/common/astnodes/IfStmt.java
+++ b/src/main/java/chocopy/common/astnodes/IfStmt.java
@@ -5,6 +5,7 @@ import java_cup.runtime.ComplexSymbolFactory.Location;
import java.util.List;
+
/** Conditional statement. */
public class IfStmt extends Stmt {
/** Test condition. */
diff --git a/src/main/java/chocopy/common/astnodes/IndexExpr.java b/src/main/java/chocopy/common/astnodes/IndexExpr.java
index ce788fa..28951c8 100644
--- a/src/main/java/chocopy/common/astnodes/IndexExpr.java
+++ b/src/main/java/chocopy/common/astnodes/IndexExpr.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** List-indexing expression. */
public class IndexExpr extends Expr {
diff --git a/src/main/java/chocopy/common/astnodes/IntegerLiteral.java b/src/main/java/chocopy/common/astnodes/IntegerLiteral.java
index f2d165b..38f3df6 100644
--- a/src/main/java/chocopy/common/astnodes/IntegerLiteral.java
+++ b/src/main/java/chocopy/common/astnodes/IntegerLiteral.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** Integer numerals. */
public final class IntegerLiteral extends Literal {
diff --git a/src/main/java/chocopy/common/astnodes/ListExpr.java b/src/main/java/chocopy/common/astnodes/ListExpr.java
index eab6045..1b76d44 100644
--- a/src/main/java/chocopy/common/astnodes/ListExpr.java
+++ b/src/main/java/chocopy/common/astnodes/ListExpr.java
@@ -5,6 +5,7 @@ import java_cup.runtime.ComplexSymbolFactory.Location;
import java.util.List;
+
/** List displays. */
public final class ListExpr extends Expr {
diff --git a/src/main/java/chocopy/common/astnodes/ListType.java b/src/main/java/chocopy/common/astnodes/ListType.java
index 32782ad..d0715e7 100644
--- a/src/main/java/chocopy/common/astnodes/ListType.java
+++ b/src/main/java/chocopy/common/astnodes/ListType.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** Type denotation for a list type. */
public final class ListType extends TypeAnnotation {
diff --git a/src/main/java/chocopy/common/astnodes/Literal.java b/src/main/java/chocopy/common/astnodes/Literal.java
index 2afd1be..798d70c 100644
--- a/src/main/java/chocopy/common/astnodes/Literal.java
+++ b/src/main/java/chocopy/common/astnodes/Literal.java
@@ -4,6 +4,7 @@ import java_cup.runtime.ComplexSymbolFactory.Location;
/**
* Base of all the literal nodes.
+<<<<<<< HEAD
*
* There is nothing in this class, but it is useful to isolate expressions that are constant
* literals.
diff --git a/src/main/java/chocopy/common/astnodes/MemberExpr.java b/src/main/java/chocopy/common/astnodes/MemberExpr.java
index a9e0a4f..3889f20 100644
--- a/src/main/java/chocopy/common/astnodes/MemberExpr.java
+++ b/src/main/java/chocopy/common/astnodes/MemberExpr.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** Attribute accessor. */
public class MemberExpr extends Expr {
diff --git a/src/main/java/chocopy/common/astnodes/MethodCallExpr.java b/src/main/java/chocopy/common/astnodes/MethodCallExpr.java
index ab3f424..64ddf61 100644
--- a/src/main/java/chocopy/common/astnodes/MethodCallExpr.java
+++ b/src/main/java/chocopy/common/astnodes/MethodCallExpr.java
@@ -5,6 +5,7 @@ import java_cup.runtime.ComplexSymbolFactory.Location;
import java.util.List;
+
/** Method calls. */
public class MethodCallExpr extends Expr {
diff --git a/src/main/java/chocopy/common/astnodes/Node.java b/src/main/java/chocopy/common/astnodes/Node.java
index c95f3d6..a1403f7 100644
--- a/src/main/java/chocopy/common/astnodes/Node.java
+++ b/src/main/java/chocopy/common/astnodes/Node.java
@@ -78,6 +78,7 @@ public abstract class Node {
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private String errorMsg;
+
/** A Node corresponding to source text between LEFT and RIGHT. */
public Node(Location left, Location right) {
if (left != null) {
@@ -100,6 +101,7 @@ public abstract class Node {
return location;
}
+
/** Copy LOCATION as getLocation(). */
public void setLocation(final int[] location) {
System.arraycopy(location, 0, this.location, 0, 4);
@@ -113,6 +115,7 @@ public abstract class Node {
this.errorMsg = msg;
}
+
/** Return true iff I have been marked with an error message. */
@JsonIgnore
public boolean hasError() {
@@ -135,11 +138,13 @@ public abstract class Node {
}
}
+
/** Return a serialization of this node in JSON format. */
public String toJSON() throws JsonProcessingException {
return mapper.writeValueAsString(this);
}
+
/** Mapper to-and-from serialized JSON. */
private static final ObjectMapper mapper = new ObjectMapper();
@@ -148,6 +153,7 @@ public abstract class Node {
mapper.registerModule(new ParameterNamesModule());
}
+
/** Returns a T from JSON, a JSON-serialized T value with class CLAS. */
public static T fromJSON(String json, Class clas) throws IOException {
return mapper.readValue(json, clas);
diff --git a/src/main/java/chocopy/common/astnodes/NonLocalDecl.java b/src/main/java/chocopy/common/astnodes/NonLocalDecl.java
index ebaf78d..5086deb 100644
--- a/src/main/java/chocopy/common/astnodes/NonLocalDecl.java
+++ b/src/main/java/chocopy/common/astnodes/NonLocalDecl.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** Nonlocal declaration. */
public class NonLocalDecl extends Declaration {
diff --git a/src/main/java/chocopy/common/astnodes/NoneLiteral.java b/src/main/java/chocopy/common/astnodes/NoneLiteral.java
index b51a581..dc3a7a5 100644
--- a/src/main/java/chocopy/common/astnodes/NoneLiteral.java
+++ b/src/main/java/chocopy/common/astnodes/NoneLiteral.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** The expression 'None'. */
public final class NoneLiteral extends Literal {
diff --git a/src/main/java/chocopy/common/astnodes/Program.java b/src/main/java/chocopy/common/astnodes/Program.java
index e95b2e7..26248fa 100644
--- a/src/main/java/chocopy/common/astnodes/Program.java
+++ b/src/main/java/chocopy/common/astnodes/Program.java
@@ -7,6 +7,7 @@ import java_cup.runtime.ComplexSymbolFactory.Location;
import java.util.ArrayList;
import java.util.List;
+
/** An entire Chocopy program. */
public class Program extends Node {
@@ -42,12 +43,14 @@ public class Program extends Node {
return analyzer.analyze(this);
}
+
/** Returns true iff there is at least one error in the program. */
@JsonIgnore
public boolean hasErrors() {
return errors.hasErrors();
}
+
/** A convenience method returning the list of all CompilerErrors for this program. */
@JsonIgnore
public List getErrorList() {
diff --git a/src/main/java/chocopy/common/astnodes/ReturnStmt.java b/src/main/java/chocopy/common/astnodes/ReturnStmt.java
index e665042..453e8a4 100644
--- a/src/main/java/chocopy/common/astnodes/ReturnStmt.java
+++ b/src/main/java/chocopy/common/astnodes/ReturnStmt.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** Return from function. */
public class ReturnStmt extends Stmt {
@@ -18,4 +19,5 @@ public class ReturnStmt extends Stmt {
public T dispatch(NodeAnalyzer analyzer) {
return analyzer.analyze(this);
}
+
}
diff --git a/src/main/java/chocopy/common/astnodes/StringLiteral.java b/src/main/java/chocopy/common/astnodes/StringLiteral.java
index 0eaf928..d8a5b31 100644
--- a/src/main/java/chocopy/common/astnodes/StringLiteral.java
+++ b/src/main/java/chocopy/common/astnodes/StringLiteral.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** String constants. */
public final class StringLiteral extends Literal {
diff --git a/src/main/java/chocopy/common/astnodes/TypeAnnotation.java b/src/main/java/chocopy/common/astnodes/TypeAnnotation.java
index d90b59e..fec8c40 100644
--- a/src/main/java/chocopy/common/astnodes/TypeAnnotation.java
+++ b/src/main/java/chocopy/common/astnodes/TypeAnnotation.java
@@ -2,6 +2,7 @@ package chocopy.common.astnodes;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** Base of all AST nodes representing type annotations (list or class types. */
public abstract class TypeAnnotation extends Node {
/** An annotation spanning source locations [LEFT..RIGHT]. */
diff --git a/src/main/java/chocopy/common/astnodes/TypedVar.java b/src/main/java/chocopy/common/astnodes/TypedVar.java
index 98aae43..4f712e7 100644
--- a/src/main/java/chocopy/common/astnodes/TypedVar.java
+++ b/src/main/java/chocopy/common/astnodes/TypedVar.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** An identifier with attached type annotation. */
public class TypedVar extends Node {
diff --git a/src/main/java/chocopy/common/astnodes/UnaryExpr.java b/src/main/java/chocopy/common/astnodes/UnaryExpr.java
index 199e701..af1ff3b 100644
--- a/src/main/java/chocopy/common/astnodes/UnaryExpr.java
+++ b/src/main/java/chocopy/common/astnodes/UnaryExpr.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** An expression applying a unary operator. */
public class UnaryExpr extends Expr {
diff --git a/src/main/java/chocopy/common/astnodes/VarDef.java b/src/main/java/chocopy/common/astnodes/VarDef.java
index 61d261a..02380b0 100644
--- a/src/main/java/chocopy/common/astnodes/VarDef.java
+++ b/src/main/java/chocopy/common/astnodes/VarDef.java
@@ -3,6 +3,7 @@ package chocopy.common.astnodes;
import chocopy.common.analysis.NodeAnalyzer;
import java_cup.runtime.ComplexSymbolFactory.Location;
+
/** A declaration of a variable (i.e., with type annotation). */
public class VarDef extends Declaration {
/** The variable and its assigned type. */
diff --git a/src/main/java/chocopy/common/astnodes/WhileStmt.java b/src/main/java/chocopy/common/astnodes/WhileStmt.java
index 9a521e1..8d9ea8c 100644
--- a/src/main/java/chocopy/common/astnodes/WhileStmt.java
+++ b/src/main/java/chocopy/common/astnodes/WhileStmt.java
@@ -5,6 +5,7 @@ import java_cup.runtime.ComplexSymbolFactory.Location;
import java.util.List;
+
/** Indefinite repetition construct. */
public class WhileStmt extends Stmt {
/** Test for whether to continue. */
@@ -19,7 +20,9 @@ public class WhileStmt extends Stmt {
this.body = body;
}
+
public T dispatch(NodeAnalyzer analyzer) {
return analyzer.analyze(this);
}
+
}
diff --git a/src/main/java/chocopy/pa1/StudentParser.java b/src/main/java/chocopy/pa1/StudentParser.java
new file mode 100644
index 0000000..c29db68
--- /dev/null
+++ b/src/main/java/chocopy/pa1/StudentParser.java
@@ -0,0 +1,25 @@
+package chocopy.pa1;
+
+import chocopy.common.astnodes.Program;
+import java_cup.runtime.ComplexSymbolFactory;
+
+import java.io.StringReader;
+
+/**
+ * Interface between driver and parser.
+ */
+public class StudentParser {
+
+ /**
+ * Return the Program AST resulting from parsing INPUT. Turn on
+ * parser debugging iff DEBUG.
+ */
+ public static Program process(String input, boolean debug) {
+ ChocoPyLexer lexer = new ChocoPyLexer(new StringReader(input));
+ ChocoPyParser parser =
+ new ChocoPyParser(lexer, new ComplexSymbolFactory());
+ return parser.parseProgram(debug);
+ }
+}
+
+
diff --git a/src/main/java/chocopy/pa2/DeclarationAnalyzer.java b/src/main/java/chocopy/pa2/DeclarationAnalyzer.java
index a7f4e39..0c0510e 100644
--- a/src/main/java/chocopy/pa2/DeclarationAnalyzer.java
+++ b/src/main/java/chocopy/pa2/DeclarationAnalyzer.java
@@ -28,6 +28,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
firstPass = true;
errors = errors0;
globals = sym;
+ // Symbol table entry for object class
ClassVType cvt = new ClassVType("object"), obj = cvt;
FuncType init = new FuncType(Type.OBJECT_TYPE);
init.parameters.add(Type.OBJECT_TYPE);
@@ -35,6 +36,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
cvt_scope.put("init",init);
cvt.scope=cvt_scope;
sym.put("object", cvt);
+ //Symbol table entry for int class
cvt = new ClassVType("int");
cvt.super_class = obj;
init = new FuncType(Type.INT_TYPE);
@@ -43,6 +45,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
cvt_scope.put("init",init);
cvt.scope=cvt_scope;
sym.put("int", cvt);
+ //Symbol table entry for str class
cvt = new ClassVType("str");
cvt.super_class = obj;
init = new FuncType(Type.STR_TYPE);
@@ -51,6 +54,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
cvt_scope.put("init",init);
cvt.scope=cvt_scope;
sym.put("str", cvt);
+ //Symbol table entry for bool class
cvt = new ClassVType("bool");
cvt.super_class = obj;
init = new FuncType(Type.BOOL_TYPE);
@@ -59,24 +63,25 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
cvt_scope.put("init",init);
cvt.scope=cvt_scope;
sym.put("bool", cvt);
-
+ //Symbol table entry for None return type
cvt = new ClassVType("");
cvt.super_class = obj;
sym.put("", cvt);
-
+ //Symbol table entry for inbuilt print function
ArrayList param = new ArrayList();
param.add(Type.OBJECT_TYPE);
sym.put("print", new FuncType(param, Type.NONE_TYPE));
-
+ //Symbol table entry for inbuilt len function
param = new ArrayList();
param.add(Type.OBJECT_TYPE);
sym.put("len", new FuncType(param, Type.INT_TYPE));
-
+ //Symbol table entry for inbuilt input function
sym.put("input", new FuncType(new ArrayList<>(), Type.STR_TYPE));
typeChecker = new TypeChecker(globals, errors);
}
- public DeclarationAnalyzer(Errors errors0, TypeChecker typeChecker, SymbolTable globals){
+ public DeclarationAnalyzer(Errors errors0, TypeChecker typeChecker, SymbolTable globals)
+ {
firstPass = false;
this.typeChecker = typeChecker;
errors = errors0;
@@ -86,27 +91,18 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
{
return globals;
}
- private void putSymChecked(Node node, String name, Type ty){
- if (ty == null)
- {
- return;
- }
-
- if (globals.get(name)!= null && !(ty instanceof ClassVType) && globals.get(name) instanceof ClassVType) //class names are only in global scope
- {
- errors.semError(node, "Cannot shadow class name: %s", name);
- }
- else if (sym.declares(name))
- {
- errors.semError(
+ private void putSymChecked(Node node, String name, Type ty)
+ {
+ if (ty == null)
+ return;
+
+ if (globals.get(name)!= null && !(ty instanceof ClassVType) && globals.get(name) instanceof ClassVType) //class names are only in global scope
+ errors.semError(node, "Cannot shadow class name: %s", name);
+ else if (sym.declares(name))
+ errors.semError(
node, "Duplicate declaration of identifier in same scope: %s", name);
-
- }
-
- else
- {
- sym.put(name, ty);
- }
+ else
+ sym.put(name, ty);
}
@Override
public Type analyze(Program program)
@@ -116,8 +112,6 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
Identifier id = decl.getIdentifier();
String name = id.name;
Type type = decl.dispatch(this);
-
-
}
// Check for return statements at top
for (Stmt stmt : program.statements)
@@ -130,11 +124,13 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
}
@Override
- public Type analyze(FuncDef node) {
+ public Type analyze(FuncDef node)
+ {
Type fTy = globals.get(node.name.name);
FuncType current_func=null;
- if(!(fTy instanceof FuncType)){
+ if(!(fTy instanceof FuncType))
+ {
if(fTy == null)
{
current_func = new FuncType(new ArrayList(),
@@ -167,7 +163,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
if(!firstPass){
ValueType returnType = ValueType.annotationToValueType(node.returnType);
- if(returnType!=null && !returnType.isSpecialType() && !(globals.get(returnType.className()) instanceof ClassVType))
+ if(returnType!=null && !returnType.isSpecialType() && !returnType.isListType() && !(globals.get(returnType.className()) instanceof ClassVType))
errors.semError(
node.returnType, "Invalid type annotation; there is no class named: %s", returnType.className());
@@ -187,7 +183,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
else
otherDefs.add(decl);
for (Declaration decl : varDefs)
- if(decl instanceof VarDef)
+ if(decl instanceof VarDef||decl instanceof NonLocalDecl)
decl.dispatch(this);
else
decl.dispatch(typeChecker);
@@ -200,7 +196,8 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
return current_func;
}
- public boolean compare_functions(FuncType fun1, FuncType fun2) {
+ public boolean compare_functions(FuncType fun1, FuncType fun2)
+ {
if (fun1.returnType.equals(fun2.returnType)==false)
return false;
if (fun1.parameters.size() != fun2.parameters.size())
@@ -263,7 +260,8 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
!(params.get(0) instanceof ClassValueType)||
!((ClassValueType)params.get(0)).className().equals(current_class.className))
errors.semError(id, "Method overridden with different type signature: __init__");
- else sym.put(name, current_func);
+ else
+ sym.put(name, current_func);
if(params.size() < 1 || (params.get(0) instanceof ClassValueType==false) || ((ClassValueType)params.get(0)).className().equals(current_class.className)==false)
errors.semError(
id, "First parameter of the following method must be of the enclosing class: %s", name);
@@ -286,7 +284,10 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
}
else
sym.put(name, current_func);
- } else if (super_syms.contains(name))
+ }
+ else if (name.equals("__init__") && !(type instanceof FuncType))
+ errors.semError(id, "Cannot re-define attribute: %s", name);
+ else if (super_syms.contains(name))
errors.semError(id, "Cannot re-define attribute: %s", name);
else
sym.put(name, type);
@@ -305,7 +306,23 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
putSymChecked(node.name, node.name.name, cvt);
return cvt;
}
-
+ boolean isVariableType(Type ty)
+ {
+ return ty.isSpecialType() || ty.equals(Type.OBJECT_TYPE)|| ty.isListType();
+ }
+ @Override
+ public Type analyze(NonLocalDecl node)
+ {
+ SymbolTable parent=sym.getParent();
+ if (parent.getParent()!=null && parent.declares(node.variable.name) && isVariableType(sym.get(node.variable.name)))
+ {
+ sym.put(node.variable.name, sym.get(node.variable.name));
+ return sym.get(node.variable.name);
+ }
+ errors.semError(
+ node.variable, "Not a nonlocal variable: %s", node.variable.name);
+ return null;
+ }
@Override
public Type analyze(VarDef node)
{
@@ -332,10 +349,12 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer
return var_type;
}
- public void setScope(SymbolTable currentScope) {
+ public void setScope(SymbolTable currentScope)
+ {
sym = currentScope;
}
- public void setCurrClass(ClassVType current_class){
+ public void setCurrClass(ClassVType current_class)
+ {
this.current_class = current_class;
}
}
diff --git a/src/main/java/chocopy/pa2/StudentAnalysis.java b/src/main/java/chocopy/pa2/StudentAnalysis.java
index d4c553d..cb90b58 100644
--- a/src/main/java/chocopy/pa2/StudentAnalysis.java
+++ b/src/main/java/chocopy/pa2/StudentAnalysis.java
@@ -90,7 +90,7 @@ public class StudentAnalysis {
TypeChecker typeChecker = new TypeChecker(globalSym, program.errors);
program.dispatch(typeChecker);
}
- System.out.println(program);
+ //System.out.println(program);
return program;
}
}
diff --git a/src/main/java/chocopy/pa2/TypeChecker.java b/src/main/java/chocopy/pa2/TypeChecker.java
index 7b4fe2e..5e93485 100644
--- a/src/main/java/chocopy/pa2/TypeChecker.java
+++ b/src/main/java/chocopy/pa2/TypeChecker.java
@@ -16,6 +16,8 @@ import static chocopy.common.analysis.types.Type.OBJECT_TYPE;
import java.util.ArrayList;
+import javax.swing.text.StyledEditorKit.BoldAction;
+
import com.fasterxml.jackson.annotation.JacksonInject.Value;
/**
@@ -31,7 +33,7 @@ public class TypeChecker extends AbstractNodeAnalyzer {
private boolean returned = false, member = false;
/** Collector for errors. */
private final Errors errors;
-
+ private Boolean assign = false;
/**
* Creates a type checker using GLOBALSYMBOLS for the initial global symbol table and ERRORS0 to
* receive semantic errors.
@@ -87,6 +89,7 @@ public class TypeChecker extends AbstractNodeAnalyzer {
Type tr = node.value.dispatch(this);
Type tl;
boolean error = false;
+ assign=true;
for (Expr ex : node.targets)
{
tl = ex.dispatch(this);
@@ -95,17 +98,21 @@ public class TypeChecker extends AbstractNodeAnalyzer {
{
err(node, "Expression `%s` type inference error.", ex);
error = true;
- } else if (ex instanceof IndexExpr &&
- ((IndexExpr)ex).list.getInferredType().equals(Type.STR_TYPE)){
+ }
+ else if (ex instanceof IndexExpr &&
+ ((IndexExpr)ex).list.getInferredType().equals(Type.STR_TYPE))
+ {
err(ex, "`str` is not a list type");
error = true;
}
- else if(tr!=null && tl.isListType() && tr.isListType()){
+ else if(tr!=null && tl.isListType() && tr.isListType())
+ {
if(!((!tl.elementType().isSpecialType()&&tr.elementType().equals(Type.NONE_TYPE))||
- tl.equals(tr)||tr.elementType().equals(Type.EMPTY_TYPE))){
- err(node, "Expected type `%s`; got type `%s`", tl, tr);
+ tl.equals(tr)||tr.elementType().equals(Type.EMPTY_TYPE)))
+ {
+ err(node, "Expected type `%s`; got type `%s`", tl, tr);
error = true;
- }
+ }
}
else if(tl.isListType() && Type.EMPTY_TYPE.equals(tr)) ; //continue;
else if(tr != null && !(StudentAnalysis.subClassOf(tl, tr, currentScope) || !tl.isSpecialType() && tr.equals(Type.NONE_TYPE)))
@@ -114,6 +121,7 @@ public class TypeChecker extends AbstractNodeAnalyzer {
error = true;
}
}
+ assign=false;
return null;
}
@@ -298,7 +306,7 @@ public class TypeChecker extends AbstractNodeAnalyzer {
Type thisArgTy = thisArg.setInferredType(thisArg.dispatch(this)),
thisParamTy = funcTy.parameters.get(i + 1);
- if(!thisParamTy.equals(thisArgTy))
+ if(!thisParamTy.equals(thisArgTy) && !StudentAnalysis.subClassOf(thisParamTy, thisArgTy, currentScope))
err(node, "Expected type `%s`; got type `%s` in parameter %d",
thisParamTy, thisArgTy, i + 1);
}
@@ -317,7 +325,7 @@ public class TypeChecker extends AbstractNodeAnalyzer {
public Type analyze(NoneLiteral node) {
return node.setInferredType(Type.NONE_TYPE);
}
-
+ /*
@Override
public Type analyze(NonLocalDecl node) {
SymbolTable parent = currentScope.getParent();
@@ -337,7 +345,7 @@ public class TypeChecker extends AbstractNodeAnalyzer {
}
return null;
}
-
+ */
@Override
public Type analyze(ReturnStmt node) {
if(node.value != null)
@@ -472,10 +480,13 @@ public class TypeChecker extends AbstractNodeAnalyzer {
public Type analyze(Identifier id) {
String varName = id.name;
Type varType = currentScope.get(varName);
- if(varType!=null && !currentScope.getDeclaredSymbols().contains(varName)){
- err(id, "Cannot assign to variable that is not explicitly declared in this scope: %s", varName);
+ if(varType!=null)
+ {
+ if(assign==true && !currentScope.getDeclaredSymbols().contains(varName))
+ err(id, "Cannot assign to variable that is not explicitly declared in this scope: %s", varName);
+ else if(assign==false && currentScope.get(varName)==null)
+ err(id, "Variable not declared in scope: %s", varName);
}
-
if (varType != null && varType.isValueType()) {
return id.setInferredType(varType);
}
@@ -488,16 +499,14 @@ public class TypeChecker extends AbstractNodeAnalyzer {
public Type analyze(GlobalDecl node)
{
Type ty = sym.get(node.variable.name);
- if (sym.declares(node.variable.name)==false ||
- !isVariableType(ty)
- )
+ if (sym.declares(node.variable.name)==false || !isVariableType(ty))
{
- errors.semError(
+ err(
node.variable, "Not a global variable: %s", node.variable.name);
return null;
}
else if(currentScope.getDeclaredSymbols().contains(node.variable.name)){
- errors.semError(
+ err(
node.variable, "Duplicate declaration of identifier in same scope: %s", node.variable.name);
}
else
diff --git a/src/main/jflex/chocopy/pa1/ChocoPy.jflex b/src/main/jflex/chocopy/pa1/ChocoPy.jflex
new file mode 100644
index 0000000..cbfb668
--- /dev/null
+++ b/src/main/jflex/chocopy/pa1/ChocoPy.jflex
@@ -0,0 +1,279 @@
+package chocopy.pa1;
+import java_cup.runtime.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+%%
+
+/*** Do not change the flags below unless you know what you are doing. ***/
+
+%unicode
+%line
+%column
+%states AFTER, STR
+%class ChocoPyLexer
+%public
+
+%cupsym ChocoPyTokens
+%cup
+%cupdebug
+
+%eofclose false
+
+/*** Do not change the flags above unless you know what you are doing. ***/
+
+/* The following code section is copied verbatim to the
+ * generated lexer class. */
+%{
+ /* The code below includes some convenience methods to create tokens
+ * of a given type and optionally a value that the CUP parser can
+ * understand. Specifically, a lot of the logic below deals with
+ * embedded information about where in the source code a given token
+ * was recognized, so that the parser can report errors accurately.
+ * (It need not be modified for this project.) */
+
+ /** Producer of token-related values for the parser. */
+ final ComplexSymbolFactory symbolFactory = new ComplexSymbolFactory();
+ private int currIndent = 0; //Current Indentation Level
+ private String currString = "";
+ private int str_l = 0, str_c = 0; //Start location of a string.
+ /*A stack that keeps track of the spaces in each Indentation Level*/
+ private ArrayList stack = new ArrayList(20);
+ private boolean indentErrorUnchecked = true;
+ /** Return a terminal symbol of syntactic category TYPE and no
+ * semantic value at the current source location. */
+ private Symbol symbol(int type) {
+ return symbol(type, yytext());
+ }
+
+ /** Return a terminal symbol of syntactic category TYPE and semantic
+ * value VALUE at the current source location. */
+ private Symbol symbol(int type, Object value) {
+ return symbolFactory.newSymbol(ChocoPyTokens.terminalNames[type], type,
+ new ComplexSymbolFactory.Location(yyline + 1, yycolumn + 1),
+ new ComplexSymbolFactory.Location(yyline + 1,yycolumn + yylength()),
+ value);
+ }
+
+ private void push(int indent){
+ stack.add(indent);
+ }
+ private int pop(){
+ if(stack.isEmpty()) return 0;
+ return stack.remove(stack.size() - 1);
+ }
+ private int top(){
+ if(stack.isEmpty()) return 0;
+ return stack.get(stack.size() - 1);
+ }
+ private boolean find(int indent){
+ if(indent == 0) return true;
+ Iterator it = stack.iterator();
+ while(it.hasNext()){
+ if(it.next() == indent)
+ return true;
+ }
+ return false;
+ }
+%}
+
+/* Macros (regexes used in rules below) */
+
+WhiteSpace = [ \t]
+LineBreak = \r|\n|\r\n
+
+
+IntegerLiteral = 0|[1-9][0-9]* // Accroding to the manual, 00+ is illeagal
+StringLiteral = ([^\"\\]|(\\\")|(\\t)|(\\r)|(\\n)|(\\\\))+ // \n, \r, \t, \\, \" and Anything except \ and "
+Identifiers = (_|[a-z]|[A-Z])(_|[a-z]|[A-Z]|[0-9])*
+Comments = #[^\r\n]*
+%%
+//YYINITIAL state is where we're dealing with indentations.
+//We will set the state to YYINITIAL when starting a
+//new line unless this line is within a string, e.g.:
+/*
+"this is \
+a string across \
+multiple lines\
+"
+*/
+{
+ {WhiteSpace}
+ {
+ /*Add indentation */
+ if(yytext() == "\t")
+ currIndent += 8; //'\t' = 8 spaces
+ else
+ currIndent ++;
+ }
+/*
+# This python code will test if '\t' is 8 spaces
+# It will run and print '1\n2'
+# Please tell me if your Python reports an error
+# Or you find documentations that says otherwise
+
+if True:
+ print(1) # \t
+ print(2) # 8 spaces
+*/
+
+ {LineBreak}
+ {
+ /*
+ If this is a blank line, start over on the next line.
+ An empty line should just be ignored, therefore we don't
+ pass a NEWLINE to Cup.
+ */
+ currIndent = 0;
+ }
+ {Comments} { /* ignored */ } //Ignore blank lines
+
+ /*If it's not a blank line (Current character isn't a
+ Whitespace/linebreak/comment), deal with indentation here and
+ start accepting whatever is on this line in `AFTER' state*/
+ [^ \t\r\n#]
+ {
+ //rewind the current character.
+ yypushback(1);
+ if(top() > currIndent)
+ {
+ /*
+ If the indentation of the line is less than number of
+ indents current level should have,
+ keep dedenting until it reaches the level with the same
+ number of indents.
+ It's like a loop, because we're not changing the state
+ and we rewinded the current character. So it will keep
+ going until top()<= currIndent and it will switch to
+ AFTER state.
+ */
+ pop();
+ if(top() < currIndent)
+ {
+ currIndent = top();
+ return symbolFactory.newSymbol("", ChocoPyTokens.UNRECOGNIZED,
+ new ComplexSymbolFactory.Location(yyline + 1, yycolumn - 1),
+ new ComplexSymbolFactory.Location(yyline + 1,yycolumn + yylength()),
+ currIndent);
+ }
+ return symbolFactory.newSymbol(ChocoPyTokens.terminalNames[ChocoPyTokens.DEDENT], ChocoPyTokens.DEDENT,
+ new ComplexSymbolFactory.Location(yyline + 1, yycolumn - 1),
+ new ComplexSymbolFactory.Location(yyline + 1,yycolumn + yylength()),
+ currIndent);
+ }
+ /*Otherwise, we will start dealing with the rest
+ of the line after indentation in AFTER state. */
+ yybegin(AFTER);
+ if(top()< currIndent)
+ {
+ /*
+ If current indentation is more than the number of indents
+ current level should have, start a new level which will have
+ `currIndent' indents.
+ */
+
+ push(currIndent);
+ return symbolFactory.newSymbol(ChocoPyTokens.terminalNames[ChocoPyTokens.INDENT], ChocoPyTokens.INDENT,
+ new ComplexSymbolFactory.Location(yyline + 1, yycolumn - 1),
+ new ComplexSymbolFactory.Location(yyline + 1,yycolumn + yylength()),
+ currIndent);
+ }
+ }
+}
+
+
+ {
+
+ /* Delimiters. */
+ {LineBreak} { yybegin(YYINITIAL); currIndent = 0;indentErrorUnchecked = true; return symbol(ChocoPyTokens.NEWLINE);}
+ ":" { return symbol(ChocoPyTokens.COLON); }
+ "," { return symbol(ChocoPyTokens.COMMA); }
+
+ /* Literals. */
+ {IntegerLiteral} { return symbol(ChocoPyTokens.NUMBER,
+ Integer.parseInt(yytext())); }
+
+ "\"" { yybegin(STR); str_l = yyline + 1; str_c = yycolumn + 1; currString = ""; } //Start taking a string when see a "
+ "False" { return symbol(ChocoPyTokens.BOOL, false); }
+ "True" { return symbol(ChocoPyTokens.BOOL, true); }
+ "None" { return symbol(ChocoPyTokens.NONE); }
+
+ /*Keywords*/
+ "if" { return symbol(ChocoPyTokens.IF); }
+ "else" { return symbol(ChocoPyTokens.ELSE); }
+ "elif" { return symbol(ChocoPyTokens.ELIF); }
+ "while" { return symbol(ChocoPyTokens.WHILE); }
+ "class" { return symbol(ChocoPyTokens.CLASS); }
+ "def" { return symbol(ChocoPyTokens.DEF); }
+ "lambda" { return symbol(ChocoPyTokens.LAMBDA); }
+ "as" { return symbol(ChocoPyTokens.AS); }
+ "for" { return symbol(ChocoPyTokens.FOR); }
+ "global" { return symbol(ChocoPyTokens.GLOBAL); }
+ "in" { return symbol(ChocoPyTokens.IN); }
+ "nonlocal" { return symbol(ChocoPyTokens.NONLOCAL); }
+ "pass" { return symbol(ChocoPyTokens.PASS); }
+ "return" { return symbol(ChocoPyTokens.RETURN); }
+ "assert" { return symbol(ChocoPyTokens.ASSERT); }
+ "await" { return symbol(ChocoPyTokens.AWAIT); }
+ "break" { return symbol(ChocoPyTokens.BREAK); }
+ "continue" { return symbol(ChocoPyTokens.CONTINUE); }
+ "del" { return symbol(ChocoPyTokens.DEL); }
+ "except" { return symbol(ChocoPyTokens.EXCEPT); }
+ "finally" { return symbol(ChocoPyTokens.FINALLY); }
+ "from" { return symbol(ChocoPyTokens.FROM); }
+ "import" { return symbol(ChocoPyTokens.IMPORT); }
+ "raise" { return symbol(ChocoPyTokens.RAISE); }
+ "try" { return symbol(ChocoPyTokens.TRY); }
+ "with" { return symbol(ChocoPyTokens.WITH); }
+ "yield" { return symbol(ChocoPyTokens.YIELD); }
+
+
+ /* Operators. */
+ "+" { return symbol(ChocoPyTokens.PLUS); }
+ "-" { return symbol(ChocoPyTokens.MINUS); }
+ "*" { return symbol(ChocoPyTokens.MUL); }
+ "//" { return symbol(ChocoPyTokens.DIV); }
+ "/" { return symbol(ChocoPyTokens.DIV); } //Accroding to manual, chocopy don't have fp division, '/', '//' should be integr division
+ "%" { return symbol(ChocoPyTokens.MOD); }
+ ">" { return symbol(ChocoPyTokens.GT); }
+ "<" { return symbol(ChocoPyTokens.LT); }
+ "==" { return symbol(ChocoPyTokens.EQUAL); }
+ "!=" { return symbol(ChocoPyTokens.NEQ); }
+ ">=" { return symbol(ChocoPyTokens.GEQ); }
+ "<=" { return symbol(ChocoPyTokens.LEQ); }
+ "=" { return symbol(ChocoPyTokens.ASSIGN); }
+ "and" { return symbol(ChocoPyTokens.AND); }
+ "or" { return symbol(ChocoPyTokens.OR); }
+ "not" { return symbol(ChocoPyTokens.NOT); }
+ "." { return symbol(ChocoPyTokens.DOT); }
+ "(" { return symbol(ChocoPyTokens.LPAR); }
+ ")" { return symbol(ChocoPyTokens.RPAR); }
+ "[" { return symbol(ChocoPyTokens.LBR); }
+ "]" { return symbol(ChocoPyTokens.RBR); }
+ "->" { return symbol(ChocoPyTokens.ARROW); }
+ "is" { return symbol(ChocoPyTokens.IS); }
+
+
+ /*Identifiers*/
+ {Identifiers} { return symbol(ChocoPyTokens.ID, yytext()); }
+
+ /* Whitespace. */
+ {WhiteSpace} { /* ignore */ }
+
+ /* Comment. */
+ {Comments} { /* ignore */ }
+}
+{
+ {StringLiteral} { currString += yytext(); }
+
+ \\$ { /*'\' at the end of line, do nothing.*/ }
+
+ "\"" { yybegin(AFTER); return symbolFactory.newSymbol(ChocoPyTokens.terminalNames[ChocoPyTokens.STRING], ChocoPyTokens.STRING,
+ new ComplexSymbolFactory.Location(str_l, str_c),
+ new ComplexSymbolFactory.Location(yyline + 1,yycolumn + yylength()),
+ currString); } // accepted a ", return to AFTER state
+}
+<> { if(!stack.isEmpty()){ return symbol(ChocoPyTokens.DEDENT, pop());} return symbol(ChocoPyTokens.EOF); }
+
+/* Error fallback. */
+[^] { return symbol(ChocoPyTokens.UNRECOGNIZED); }
diff --git a/src/test/data/pa1/sample/bad_assign_expr1.py b/src/test/data/pa1/sample/bad_assign_expr1.py
new file mode 100644
index 0000000..ccc8c3e
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_assign_expr1.py
@@ -0,0 +1 @@
+x = (y = 2)
diff --git a/src/test/data/pa1/sample/bad_assign_expr1.py.ast b/src/test/data/pa1/sample/bad_assign_expr1.py.ast
new file mode 100644
index 0000000..d134770
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_assign_expr1.py.ast
@@ -0,0 +1,16 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 6, 1, 6 ],
+ "declarations" : [ ],
+ "statements" : [ ],
+ "errors" : {
+ "errors" : [ {
+ "kind" : "CompilerError",
+ "location" : [ 1, 8, 1, 8 ],
+ "message" : "Parse error near token EQ: =",
+ "syntax" : true
+ } ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/bad_assign_expr2.py b/src/test/data/pa1/sample/bad_assign_expr2.py
new file mode 100644
index 0000000..444bc53
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_assign_expr2.py
@@ -0,0 +1 @@
+print(x = 1)
diff --git a/src/test/data/pa1/sample/bad_assign_expr2.py.ast b/src/test/data/pa1/sample/bad_assign_expr2.py.ast
new file mode 100644
index 0000000..53e699c
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_assign_expr2.py.ast
@@ -0,0 +1,16 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 7, 1, 7 ],
+ "declarations" : [ ],
+ "statements" : [ ],
+ "errors" : {
+ "errors" : [ {
+ "kind" : "CompilerError",
+ "location" : [ 1, 9, 1, 9 ],
+ "message" : "Parse error near token EQ: =",
+ "syntax" : true
+ } ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/bad_func_def.py b/src/test/data/pa1/sample/bad_func_def.py
new file mode 100644
index 0000000..ebd2373
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_func_def.py
@@ -0,0 +1,6 @@
+def foo(a, b) -> 1:
+ x:int = a
+ return 1
+
+print(1)
+print(3**6)
diff --git a/src/test/data/pa1/sample/bad_func_def.py.ast b/src/test/data/pa1/sample/bad_func_def.py.ast
new file mode 100644
index 0000000..934bef0
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_func_def.py.ast
@@ -0,0 +1,64 @@
+{
+ "kind" : "Program",
+ "location" : [ 2, 13, 6, 8 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 2, 13, 2, 13 ],
+ "expr" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 13, 2, 13 ],
+ "name" : "a"
+ }
+ }, {
+ "kind" : "ReturnStmt",
+ "location" : [ 3, 5, 3, 12 ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 12, 3, 12 ],
+ "value" : 1
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 5, 1, 5, 8 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 5, 1, 5, 8 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 1, 5, 5 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 5, 7, 5, 7 ],
+ "value" : 1
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ {
+ "kind" : "CompilerError",
+ "location" : [ 1, 10, 1, 10 ],
+ "message" : "Parse error near token COMMA: ,",
+ "syntax" : true
+ }, {
+ "kind" : "CompilerError",
+ "location" : [ 2, 13, 2, 13 ],
+ "message" : "Parse error near token IDENTIFIER: a",
+ "syntax" : true
+ }, {
+ "kind" : "CompilerError",
+ "location" : [ 5, 1, 5, 0 ],
+ "message" : "Parse error near token DEDENT: ",
+ "syntax" : true
+ }, {
+ "kind" : "CompilerError",
+ "location" : [ 6, 9, 6, 9 ],
+ "message" : "Parse error near token TIMES: *",
+ "syntax" : true
+ } ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/bad_indentation.py b/src/test/data/pa1/sample/bad_indentation.py
new file mode 100644
index 0000000..670b7ab
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_indentation.py
@@ -0,0 +1,3 @@
+x = 1
+ y = 2
+z = 3
diff --git a/src/test/data/pa1/sample/bad_indentation.py.ast b/src/test/data/pa1/sample/bad_indentation.py.ast
new file mode 100644
index 0000000..f37b92e
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_indentation.py.ast
@@ -0,0 +1,47 @@
+{
+ "kind" : "Program",
+ "location" : [ 2, 3, 3, 6 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 2, 3, 2, 7 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 2, 3, 2, 3 ],
+ "name" : "y"
+ } ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 7, 2, 7 ],
+ "value" : 2
+ }
+ }, {
+ "kind" : "AssignStmt",
+ "location" : [ 3, 1, 3, 5 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 3, 1, 3, 1 ],
+ "name" : "z"
+ } ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 5, 3, 5 ],
+ "value" : 3
+ }
+ } ],
+ "errors" : {
+ "errors" : [ {
+ "kind" : "CompilerError",
+ "location" : [ 2, 1, 2, 2 ],
+ "message" : "Parse error near token INDENT: ",
+ "syntax" : true
+ }, {
+ "kind" : "CompilerError",
+ "location" : [ 3, 1, 3, 0 ],
+ "message" : "Parse error near token DEDENT: ",
+ "syntax" : true
+ } ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/bad_stmt.py b/src/test/data/pa1/sample/bad_stmt.py
new file mode 100644
index 0000000..8e8a4da
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_stmt.py
@@ -0,0 +1,4 @@
+1 + 2
+3 == 4 or (not False && True)
+5 + 6
+7 << 8
diff --git a/src/test/data/pa1/sample/bad_stmt.py.ast b/src/test/data/pa1/sample/bad_stmt.py.ast
new file mode 100644
index 0000000..afe9602
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_stmt.py.ast
@@ -0,0 +1,65 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 4, 7 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 5 ],
+ "expr" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 1, 1, 5 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 1, 1, 1 ],
+ "value" : 1
+ },
+ "operator" : "+",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 5, 1, 5 ],
+ "value" : 2
+ }
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 3, 1, 3, 5 ],
+ "expr" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 3, 1, 3, 5 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 1, 3, 1 ],
+ "value" : 5
+ },
+ "operator" : "+",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 5, 3, 5 ],
+ "value" : 6
+ }
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 4, 6, 4, 6 ],
+ "expr" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 6, 4, 6 ],
+ "value" : 8
+ }
+ } ],
+ "errors" : {
+ "errors" : [ {
+ "kind" : "CompilerError",
+ "location" : [ 2, 22, 2, 22 ],
+ "message" : "Parse error near token UNRECOGNIZED: &",
+ "syntax" : true
+ }, {
+ "kind" : "CompilerError",
+ "location" : [ 4, 4, 4, 4 ],
+ "message" : "Parse error near token LT: <",
+ "syntax" : true
+ } ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/chained_mixed_assignments.py b/src/test/data/pa1/sample/chained_mixed_assignments.py
new file mode 100644
index 0000000..46a230a
--- /dev/null
+++ b/src/test/data/pa1/sample/chained_mixed_assignments.py
@@ -0,0 +1,2 @@
+x[0] = y = z.f = 1
+z.g = y = x[0]
diff --git a/src/test/data/pa1/sample/chained_mixed_assignments.py.ast b/src/test/data/pa1/sample/chained_mixed_assignments.py.ast
new file mode 100644
index 0000000..9654bf6
--- /dev/null
+++ b/src/test/data/pa1/sample/chained_mixed_assignments.py.ast
@@ -0,0 +1,85 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 2, 15 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 1, 1, 1, 18 ],
+ "targets" : [ {
+ "kind" : "IndexExpr",
+ "location" : [ 1, 1, 1, 4 ],
+ "list" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 1 ],
+ "name" : "x"
+ },
+ "index" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 3, 1, 3 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "Identifier",
+ "location" : [ 1, 8, 1, 8 ],
+ "name" : "y"
+ }, {
+ "kind" : "MemberExpr",
+ "location" : [ 1, 12, 1, 14 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 12, 1, 12 ],
+ "name" : "z"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 14, 1, 14 ],
+ "name" : "f"
+ }
+ } ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 18, 1, 18 ],
+ "value" : 1
+ }
+ }, {
+ "kind" : "AssignStmt",
+ "location" : [ 2, 1, 2, 14 ],
+ "targets" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 2, 1, 2, 3 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 1, 2, 1 ],
+ "name" : "z"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 3, 2, 3 ],
+ "name" : "g"
+ }
+ }, {
+ "kind" : "Identifier",
+ "location" : [ 2, 7, 2, 7 ],
+ "name" : "y"
+ } ],
+ "value" : {
+ "kind" : "IndexExpr",
+ "location" : [ 2, 11, 2, 14 ],
+ "list" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 11, 2, 11 ],
+ "name" : "x"
+ },
+ "index" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 13, 2, 13 ],
+ "value" : 0
+ }
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/chained_var_assignments.py b/src/test/data/pa1/sample/chained_var_assignments.py
new file mode 100644
index 0000000..b253c2a
--- /dev/null
+++ b/src/test/data/pa1/sample/chained_var_assignments.py
@@ -0,0 +1 @@
+x = y = z = 1
diff --git a/src/test/data/pa1/sample/chained_var_assignments.py.ast b/src/test/data/pa1/sample/chained_var_assignments.py.ast
new file mode 100644
index 0000000..28f0ea7
--- /dev/null
+++ b/src/test/data/pa1/sample/chained_var_assignments.py.ast
@@ -0,0 +1,32 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 1, 14 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 1, 1, 1, 13 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 1 ],
+ "name" : "x"
+ }, {
+ "kind" : "Identifier",
+ "location" : [ 1, 5, 1, 5 ],
+ "name" : "y"
+ }, {
+ "kind" : "Identifier",
+ "location" : [ 1, 9, 1, 9 ],
+ "name" : "z"
+ } ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 13, 1, 13 ],
+ "value" : 1
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/class_attr.py b/src/test/data/pa1/sample/class_attr.py
new file mode 100644
index 0000000..bb1e1cd
--- /dev/null
+++ b/src/test/data/pa1/sample/class_attr.py
@@ -0,0 +1,4 @@
+class Foo(object):
+ x:int = 1
+
+f = Foo()
diff --git a/src/test/data/pa1/sample/class_attr.py.ast b/src/test/data/pa1/sample/class_attr.py.ast
new file mode 100644
index 0000000..4fdab40
--- /dev/null
+++ b/src/test/data/pa1/sample/class_attr.py.ast
@@ -0,0 +1,65 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 4, 10 ],
+ "declarations" : [ {
+ "kind" : "ClassDef",
+ "location" : [ 1, 1, 2, 14 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 7, 1, 9 ],
+ "name" : "Foo"
+ },
+ "superClass" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 11, 1, 16 ],
+ "name" : "object"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 2, 5, 2, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 2, 5, 2, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 5 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 7, 2, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 13, 2, 13 ],
+ "value" : 1
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 4, 1, 4, 9 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 4, 1, 4, 1 ],
+ "name" : "f"
+ } ],
+ "value" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 5, 4, 9 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 5, 4, 7 ],
+ "name" : "Foo"
+ },
+ "args" : [ ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/class_attr_get.py b/src/test/data/pa1/sample/class_attr_get.py
new file mode 100644
index 0000000..b4e6365
--- /dev/null
+++ b/src/test/data/pa1/sample/class_attr_get.py
@@ -0,0 +1,5 @@
+class Foo(object):
+ x:int = 1
+
+f = Foo()
+print(f.x)
diff --git a/src/test/data/pa1/sample/class_attr_get.py.ast b/src/test/data/pa1/sample/class_attr_get.py.ast
new file mode 100644
index 0000000..f286342
--- /dev/null
+++ b/src/test/data/pa1/sample/class_attr_get.py.ast
@@ -0,0 +1,91 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 5, 11 ],
+ "declarations" : [ {
+ "kind" : "ClassDef",
+ "location" : [ 1, 1, 2, 14 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 7, 1, 9 ],
+ "name" : "Foo"
+ },
+ "superClass" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 11, 1, 16 ],
+ "name" : "object"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 2, 5, 2, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 2, 5, 2, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 5 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 7, 2, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 13, 2, 13 ],
+ "value" : 1
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 4, 1, 4, 9 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 4, 1, 4, 1 ],
+ "name" : "f"
+ } ],
+ "value" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 5, 4, 9 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 5, 4, 7 ],
+ "name" : "Foo"
+ },
+ "args" : [ ]
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 5, 1, 5, 10 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 5, 1, 5, 10 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 1, 5, 5 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 5, 7, 5, 9 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 7, 5, 7 ],
+ "name" : "f"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 9, 5, 9 ],
+ "name" : "x"
+ }
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/class_attr_set.py b/src/test/data/pa1/sample/class_attr_set.py
new file mode 100644
index 0000000..ac94bf8
--- /dev/null
+++ b/src/test/data/pa1/sample/class_attr_set.py
@@ -0,0 +1,5 @@
+class Foo(object):
+ x:int = 1
+
+f = Foo()
+f.x = 2
diff --git a/src/test/data/pa1/sample/class_attr_set.py.ast b/src/test/data/pa1/sample/class_attr_set.py.ast
new file mode 100644
index 0000000..03d6bba
--- /dev/null
+++ b/src/test/data/pa1/sample/class_attr_set.py.ast
@@ -0,0 +1,87 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 5, 8 ],
+ "declarations" : [ {
+ "kind" : "ClassDef",
+ "location" : [ 1, 1, 2, 14 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 7, 1, 9 ],
+ "name" : "Foo"
+ },
+ "superClass" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 11, 1, 16 ],
+ "name" : "object"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 2, 5, 2, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 2, 5, 2, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 5 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 7, 2, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 13, 2, 13 ],
+ "value" : 1
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 4, 1, 4, 9 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 4, 1, 4, 1 ],
+ "name" : "f"
+ } ],
+ "value" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 5, 4, 9 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 5, 4, 7 ],
+ "name" : "Foo"
+ },
+ "args" : [ ]
+ }
+ }, {
+ "kind" : "AssignStmt",
+ "location" : [ 5, 1, 5, 7 ],
+ "targets" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 5, 1, 5, 3 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 1, 5, 1 ],
+ "name" : "f"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 3, 5, 3 ],
+ "name" : "x"
+ }
+ } ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 5, 7, 5, 7 ],
+ "value" : 2
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/class_constructor.py b/src/test/data/pa1/sample/class_constructor.py
new file mode 100644
index 0000000..46d7ccb
--- /dev/null
+++ b/src/test/data/pa1/sample/class_constructor.py
@@ -0,0 +1,8 @@
+class Foo(object):
+ x:int = 0
+
+ def __init__(self:"Foo", x:int):
+ self.x = x
+
+f = Foo(1)
+print(f.x)
diff --git a/src/test/data/pa1/sample/class_constructor.py.ast b/src/test/data/pa1/sample/class_constructor.py.ast
new file mode 100644
index 0000000..6850e03
--- /dev/null
+++ b/src/test/data/pa1/sample/class_constructor.py.ast
@@ -0,0 +1,159 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 8, 11 ],
+ "declarations" : [ {
+ "kind" : "ClassDef",
+ "location" : [ 1, 1, 7, 0 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 7, 1, 9 ],
+ "name" : "Foo"
+ },
+ "superClass" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 11, 1, 16 ],
+ "name" : "object"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 2, 5, 2, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 2, 5, 2, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 5 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 7, 2, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 13, 2, 13 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 4, 5, 5, 19 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 9, 4, 16 ],
+ "name" : "__init__"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 4, 18, 4, 27 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 18, 4, 21 ],
+ "name" : "self"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 23, 4, 27 ],
+ "className" : "Foo"
+ }
+ }, {
+ "kind" : "TypedVar",
+ "location" : [ 4, 30, 4, 34 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 30, 4, 30 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 32, 4, 34 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 36, 4, 36 ],
+ "className" : ""
+ },
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 5, 9, 5, 18 ],
+ "targets" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 5, 9, 5, 14 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 9, 5, 12 ],
+ "name" : "self"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 14, 5, 14 ],
+ "name" : "x"
+ }
+ } ],
+ "value" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 18, 5, 18 ],
+ "name" : "x"
+ }
+ } ]
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 7, 1, 7, 10 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 7, 1, 7, 1 ],
+ "name" : "f"
+ } ],
+ "value" : {
+ "kind" : "CallExpr",
+ "location" : [ 7, 5, 7, 10 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 7, 5, 7, 7 ],
+ "name" : "Foo"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 7, 9, 7, 9 ],
+ "value" : 1
+ } ]
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 8, 1, 8, 10 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 8, 1, 8, 10 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 1, 8, 5 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 8, 7, 8, 9 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 7, 8, 7 ],
+ "name" : "f"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 9, 8, 9 ],
+ "name" : "x"
+ }
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/class_method.py b/src/test/data/pa1/sample/class_method.py
new file mode 100644
index 0000000..cc03ce2
--- /dev/null
+++ b/src/test/data/pa1/sample/class_method.py
@@ -0,0 +1,9 @@
+class Foo(object):
+ x:int = 0
+
+ def set(self:"Foo", x:int) -> object:
+ self.x = x
+
+f = Foo()
+f.set(1)
+print(f.x)
diff --git a/src/test/data/pa1/sample/class_method.py.ast b/src/test/data/pa1/sample/class_method.py.ast
new file mode 100644
index 0000000..66bc2e1
--- /dev/null
+++ b/src/test/data/pa1/sample/class_method.py.ast
@@ -0,0 +1,181 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 9, 11 ],
+ "declarations" : [ {
+ "kind" : "ClassDef",
+ "location" : [ 1, 1, 7, 0 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 7, 1, 9 ],
+ "name" : "Foo"
+ },
+ "superClass" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 11, 1, 16 ],
+ "name" : "object"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 2, 5, 2, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 2, 5, 2, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 5 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 7, 2, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 13, 2, 13 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 4, 5, 5, 19 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 9, 4, 11 ],
+ "name" : "set"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 4, 13, 4, 22 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 13, 4, 16 ],
+ "name" : "self"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 18, 4, 22 ],
+ "className" : "Foo"
+ }
+ }, {
+ "kind" : "TypedVar",
+ "location" : [ 4, 25, 4, 29 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 25, 4, 25 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 27, 4, 29 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 35, 4, 40 ],
+ "className" : "object"
+ },
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 5, 9, 5, 18 ],
+ "targets" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 5, 9, 5, 14 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 9, 5, 12 ],
+ "name" : "self"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 14, 5, 14 ],
+ "name" : "x"
+ }
+ } ],
+ "value" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 18, 5, 18 ],
+ "name" : "x"
+ }
+ } ]
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 7, 1, 7, 9 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 7, 1, 7, 1 ],
+ "name" : "f"
+ } ],
+ "value" : {
+ "kind" : "CallExpr",
+ "location" : [ 7, 5, 7, 9 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 7, 5, 7, 7 ],
+ "name" : "Foo"
+ },
+ "args" : [ ]
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 8, 1, 8, 8 ],
+ "expr" : {
+ "kind" : "MethodCallExpr",
+ "location" : [ 8, 1, 8, 8 ],
+ "method" : {
+ "kind" : "MemberExpr",
+ "location" : [ 8, 1, 8, 5 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 1, 8, 1 ],
+ "name" : "f"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 3, 8, 5 ],
+ "name" : "set"
+ }
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 8, 7, 8, 7 ],
+ "value" : 1
+ } ]
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 9, 1, 9, 10 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 9, 1, 9, 10 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 1, 9, 5 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 9, 7, 9, 9 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 7, 9, 7 ],
+ "name" : "f"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 9, 9, 9 ],
+ "name" : "x"
+ }
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/coverage.py b/src/test/data/pa1/sample/coverage.py
new file mode 100644
index 0000000..1da3446
--- /dev/null
+++ b/src/test/data/pa1/sample/coverage.py
@@ -0,0 +1,38 @@
+count:int = 0
+
+def foo(s: str) -> int:
+ return len(s)
+
+class bar(object):
+ p: bool = True
+
+ def baz(self:"bar", xx: [int]) -> str:
+ global count
+ x:int = 0
+ y:int = 1
+
+ def qux(y: int) -> object:
+ nonlocal x
+ if x > y:
+ x = -1
+
+ for x in xx:
+ self.p = x == 2
+
+ qux(0) # Yay! ChocoPy
+
+ count = count + 1
+
+ while x <= 0:
+ if self.p:
+ xx[0] = xx[1]
+ self.p = not self.p
+ x = x + 1
+ elif foo("Long"[0]) == 1:
+ return self is None
+
+ return "Nope"
+
+print(bar().baz([1,2]))
+
+
diff --git a/src/test/data/pa1/sample/coverage.py.ast b/src/test/data/pa1/sample/coverage.py.ast
new file mode 100644
index 0000000..c7bab9f
--- /dev/null
+++ b/src/test/data/pa1/sample/coverage.py.ast
@@ -0,0 +1,613 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 36, 24 ],
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 1, 1, 1, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 1, 1, 1, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 5 ],
+ "name" : "count"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 7, 1, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 13, 1, 13 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 3, 1, 4, 18 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 3, 5, 3, 7 ],
+ "name" : "foo"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 3, 9, 3, 14 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 3, 9, 3, 9 ],
+ "name" : "s"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 3, 12, 3, 14 ],
+ "className" : "str"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 3, 20, 3, 22 ],
+ "className" : "int"
+ },
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 4, 5, 4, 17 ],
+ "value" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 12, 4, 17 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 12, 4, 14 ],
+ "name" : "len"
+ },
+ "args" : [ {
+ "kind" : "Identifier",
+ "location" : [ 4, 16, 4, 16 ],
+ "name" : "s"
+ } ]
+ }
+ } ]
+ }, {
+ "kind" : "ClassDef",
+ "location" : [ 6, 1, 36, 0 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 6, 7, 6, 9 ],
+ "name" : "bar"
+ },
+ "superClass" : {
+ "kind" : "Identifier",
+ "location" : [ 6, 11, 6, 16 ],
+ "name" : "object"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 7, 5, 7, 18 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 7, 5, 7, 11 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 7, 5, 7, 5 ],
+ "name" : "p"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 7, 8, 7, 11 ],
+ "className" : "bool"
+ }
+ },
+ "value" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 7, 15, 7, 18 ],
+ "value" : true
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 9, 5, 34, 22 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 9, 9, 11 ],
+ "name" : "baz"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 9, 13, 9, 22 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 13, 9, 16 ],
+ "name" : "self"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 9, 18, 9, 22 ],
+ "className" : "bar"
+ }
+ }, {
+ "kind" : "TypedVar",
+ "location" : [ 9, 25, 9, 33 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 25, 9, 26 ],
+ "name" : "xx"
+ },
+ "type" : {
+ "kind" : "ListType",
+ "location" : [ 9, 29, 9, 33 ],
+ "elementType" : {
+ "kind" : "ClassType",
+ "location" : [ 9, 30, 9, 32 ],
+ "className" : "int"
+ }
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 9, 39, 9, 41 ],
+ "className" : "str"
+ },
+ "declarations" : [ {
+ "kind" : "GlobalDecl",
+ "location" : [ 10, 9, 10, 20 ],
+ "variable" : {
+ "kind" : "Identifier",
+ "location" : [ 10, 16, 10, 20 ],
+ "name" : "count"
+ }
+ }, {
+ "kind" : "VarDef",
+ "location" : [ 11, 9, 11, 17 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 11, 9, 11, 13 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 11, 9, 11, 9 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 11, 11, 11, 13 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 11, 17, 11, 17 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "VarDef",
+ "location" : [ 12, 9, 12, 17 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 12, 9, 12, 13 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 12, 9, 12, 9 ],
+ "name" : "y"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 12, 11, 12, 13 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 12, 17, 12, 17 ],
+ "value" : 1
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 14, 9, 19, 8 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 14, 13, 14, 15 ],
+ "name" : "qux"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 14, 17, 14, 22 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 14, 17, 14, 17 ],
+ "name" : "y"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 14, 20, 14, 22 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 14, 28, 14, 33 ],
+ "className" : "object"
+ },
+ "declarations" : [ {
+ "kind" : "NonLocalDecl",
+ "location" : [ 15, 13, 15, 22 ],
+ "variable" : {
+ "kind" : "Identifier",
+ "location" : [ 15, 22, 15, 22 ],
+ "name" : "x"
+ }
+ } ],
+ "statements" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 16, 13, 19, 8 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 16, 16, 16, 20 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 16, 16, 16, 16 ],
+ "name" : "x"
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "Identifier",
+ "location" : [ 16, 20, 16, 20 ],
+ "name" : "y"
+ }
+ },
+ "thenBody" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 17, 17, 17, 22 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 17, 17, 17, 17 ],
+ "name" : "x"
+ } ],
+ "value" : {
+ "kind" : "UnaryExpr",
+ "location" : [ 17, 21, 17, 22 ],
+ "operator" : "-",
+ "operand" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 17, 22, 17, 22 ],
+ "value" : 1
+ }
+ }
+ } ],
+ "elseBody" : [ ]
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ForStmt",
+ "location" : [ 19, 9, 22, 8 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 19, 13, 19, 13 ],
+ "name" : "x"
+ },
+ "iterable" : {
+ "kind" : "Identifier",
+ "location" : [ 19, 18, 19, 19 ],
+ "name" : "xx"
+ },
+ "body" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 20, 13, 20, 27 ],
+ "targets" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 20, 13, 20, 18 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 20, 13, 20, 16 ],
+ "name" : "self"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 20, 18, 20, 18 ],
+ "name" : "p"
+ }
+ } ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 20, 22, 20, 27 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 20, 22, 20, 22 ],
+ "name" : "x"
+ },
+ "operator" : "==",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 20, 27, 20, 27 ],
+ "value" : 2
+ }
+ }
+ } ]
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 22, 9, 22, 14 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 22, 9, 22, 14 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 22, 9, 22, 11 ],
+ "name" : "qux"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 22, 13, 22, 13 ],
+ "value" : 0
+ } ]
+ }
+ }, {
+ "kind" : "AssignStmt",
+ "location" : [ 24, 9, 24, 25 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 24, 9, 24, 13 ],
+ "name" : "count"
+ } ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 24, 17, 24, 25 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 24, 17, 24, 21 ],
+ "name" : "count"
+ },
+ "operator" : "+",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 24, 25, 24, 25 ],
+ "value" : 1
+ }
+ }
+ }, {
+ "kind" : "WhileStmt",
+ "location" : [ 26, 9, 34, 8 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 26, 15, 26, 20 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 26, 15, 26, 15 ],
+ "name" : "x"
+ },
+ "operator" : "<=",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 26, 20, 26, 20 ],
+ "value" : 0
+ }
+ },
+ "body" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 27, 13, 34, 8 ],
+ "condition" : {
+ "kind" : "MemberExpr",
+ "location" : [ 27, 16, 27, 21 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 27, 16, 27, 19 ],
+ "name" : "self"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 27, 21, 27, 21 ],
+ "name" : "p"
+ }
+ },
+ "thenBody" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 28, 17, 28, 29 ],
+ "targets" : [ {
+ "kind" : "IndexExpr",
+ "location" : [ 28, 17, 28, 21 ],
+ "list" : {
+ "kind" : "Identifier",
+ "location" : [ 28, 17, 28, 18 ],
+ "name" : "xx"
+ },
+ "index" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 28, 20, 28, 20 ],
+ "value" : 0
+ }
+ } ],
+ "value" : {
+ "kind" : "IndexExpr",
+ "location" : [ 28, 25, 28, 29 ],
+ "list" : {
+ "kind" : "Identifier",
+ "location" : [ 28, 25, 28, 26 ],
+ "name" : "xx"
+ },
+ "index" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 28, 28, 28, 28 ],
+ "value" : 1
+ }
+ }
+ }, {
+ "kind" : "AssignStmt",
+ "location" : [ 29, 17, 29, 35 ],
+ "targets" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 29, 17, 29, 22 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 29, 17, 29, 20 ],
+ "name" : "self"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 29, 22, 29, 22 ],
+ "name" : "p"
+ }
+ } ],
+ "value" : {
+ "kind" : "UnaryExpr",
+ "location" : [ 29, 26, 29, 35 ],
+ "operator" : "not",
+ "operand" : {
+ "kind" : "MemberExpr",
+ "location" : [ 29, 30, 29, 35 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 29, 30, 29, 33 ],
+ "name" : "self"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 29, 35, 29, 35 ],
+ "name" : "p"
+ }
+ }
+ }
+ }, {
+ "kind" : "AssignStmt",
+ "location" : [ 30, 17, 30, 25 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 30, 17, 30, 17 ],
+ "name" : "x"
+ } ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 30, 21, 30, 25 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 30, 21, 30, 21 ],
+ "name" : "x"
+ },
+ "operator" : "+",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 30, 25, 30, 25 ],
+ "value" : 1
+ }
+ }
+ } ],
+ "elseBody" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 31, 13, 34, 8 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 31, 18, 31, 36 ],
+ "left" : {
+ "kind" : "CallExpr",
+ "location" : [ 31, 18, 31, 31 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 31, 18, 31, 20 ],
+ "name" : "foo"
+ },
+ "args" : [ {
+ "kind" : "IndexExpr",
+ "location" : [ 31, 22, 31, 30 ],
+ "list" : {
+ "kind" : "StringLiteral",
+ "location" : [ 31, 22, 31, 27 ],
+ "value" : "Long"
+ },
+ "index" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 31, 29, 31, 29 ],
+ "value" : 0
+ }
+ } ]
+ },
+ "operator" : "==",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 31, 36, 31, 36 ],
+ "value" : 1
+ }
+ },
+ "thenBody" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 32, 17, 32, 35 ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 32, 24, 32, 35 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 32, 24, 32, 27 ],
+ "name" : "self"
+ },
+ "operator" : "is",
+ "right" : {
+ "kind" : "NoneLiteral",
+ "location" : [ 32, 32, 32, 35 ]
+ }
+ }
+ } ],
+ "elseBody" : [ ]
+ } ]
+ } ]
+ }, {
+ "kind" : "ReturnStmt",
+ "location" : [ 34, 9, 34, 21 ],
+ "value" : {
+ "kind" : "StringLiteral",
+ "location" : [ 34, 16, 34, 21 ],
+ "value" : "Nope"
+ }
+ } ]
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 36, 1, 36, 23 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 36, 1, 36, 23 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 36, 1, 36, 5 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "MethodCallExpr",
+ "location" : [ 36, 7, 36, 22 ],
+ "method" : {
+ "kind" : "MemberExpr",
+ "location" : [ 36, 7, 36, 15 ],
+ "object" : {
+ "kind" : "CallExpr",
+ "location" : [ 36, 7, 36, 11 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 36, 7, 36, 9 ],
+ "name" : "bar"
+ },
+ "args" : [ ]
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 36, 13, 36, 15 ],
+ "name" : "baz"
+ }
+ },
+ "args" : [ {
+ "kind" : "ListExpr",
+ "location" : [ 36, 17, 36, 21 ],
+ "elements" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 36, 18, 36, 18 ],
+ "value" : 1
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 36, 20, 36, 20 ],
+ "value" : 2
+ } ]
+ } ]
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/def_func.py b/src/test/data/pa1/sample/def_func.py
new file mode 100644
index 0000000..55e9c43
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func.py
@@ -0,0 +1,4 @@
+def foo() -> int:
+ return 1
+
+foo()
diff --git a/src/test/data/pa1/sample/def_func.py.ast b/src/test/data/pa1/sample/def_func.py.ast
new file mode 100644
index 0000000..00a7e65
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func.py.ast
@@ -0,0 +1,48 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 4, 6 ],
+ "declarations" : [ {
+ "kind" : "FuncDef",
+ "location" : [ 1, 1, 2, 13 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 5, 1, 7 ],
+ "name" : "foo"
+ },
+ "params" : [ ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 14, 1, 16 ],
+ "className" : "int"
+ },
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 2, 5, 2, 12 ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 12, 2, 12 ],
+ "value" : 1
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 4, 1, 4, 5 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 1, 4, 5 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 1, 4, 3 ],
+ "name" : "foo"
+ },
+ "args" : [ ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/def_func_args.py b/src/test/data/pa1/sample/def_func_args.py
new file mode 100644
index 0000000..196f504
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_args.py
@@ -0,0 +1,4 @@
+def foo(x:int, y:int) -> bool:
+ return x > y
+
+foo(1,2)
diff --git a/src/test/data/pa1/sample/def_func_args.py.ast b/src/test/data/pa1/sample/def_func_args.py.ast
new file mode 100644
index 0000000..77d9dc9
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_args.py.ast
@@ -0,0 +1,92 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 4, 9 ],
+ "declarations" : [ {
+ "kind" : "FuncDef",
+ "location" : [ 1, 1, 2, 17 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 5, 1, 7 ],
+ "name" : "foo"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 1, 9, 1, 13 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 9, 1, 9 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 11, 1, 13 ],
+ "className" : "int"
+ }
+ }, {
+ "kind" : "TypedVar",
+ "location" : [ 1, 16, 1, 20 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 16, 1, 16 ],
+ "name" : "y"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 18, 1, 20 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 26, 1, 29 ],
+ "className" : "bool"
+ },
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 2, 5, 2, 16 ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 2, 12, 2, 16 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 12, 2, 12 ],
+ "name" : "x"
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 16, 2, 16 ],
+ "name" : "y"
+ }
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 4, 1, 4, 8 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 1, 4, 8 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 1, 4, 3 ],
+ "name" : "foo"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 5, 4, 5 ],
+ "value" : 1
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 7, 4, 7 ],
+ "value" : 2
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/def_func_global.py b/src/test/data/pa1/sample/def_func_global.py
new file mode 100644
index 0000000..12f9dfc
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_global.py
@@ -0,0 +1,7 @@
+z:int = 0
+
+def foo(x:int) -> bool:
+ global z
+ return x > z
+
+foo(1)
diff --git a/src/test/data/pa1/sample/def_func_global.py.ast b/src/test/data/pa1/sample/def_func_global.py.ast
new file mode 100644
index 0000000..736af77
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_global.py.ast
@@ -0,0 +1,105 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 7, 7 ],
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 1, 1, 1, 9 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 1, 1, 1, 5 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 1 ],
+ "name" : "z"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 3, 1, 5 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 9, 1, 9 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 3, 1, 5, 17 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 3, 5, 3, 7 ],
+ "name" : "foo"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 3, 9, 3, 13 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 3, 9, 3, 9 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 3, 11, 3, 13 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 3, 19, 3, 22 ],
+ "className" : "bool"
+ },
+ "declarations" : [ {
+ "kind" : "GlobalDecl",
+ "location" : [ 4, 5, 4, 12 ],
+ "variable" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 12, 4, 12 ],
+ "name" : "z"
+ }
+ } ],
+ "statements" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 5, 5, 5, 16 ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 5, 12, 5, 16 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 12, 5, 12 ],
+ "name" : "x"
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 16, 5, 16 ],
+ "name" : "z"
+ }
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 7, 1, 7, 6 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 7, 1, 7, 6 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 7, 1, 7, 3 ],
+ "name" : "foo"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 7, 5, 7, 5 ],
+ "value" : 1
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/def_func_nested.py b/src/test/data/pa1/sample/def_func_nested.py
new file mode 100644
index 0000000..835614e
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_nested.py
@@ -0,0 +1,10 @@
+
+def foo(x:int) -> bool:
+ a:int = 0
+ b:int = 1
+ def bar(y: int) -> int:
+ a:int = 2
+ return y
+ return bar(x) > a
+
+foo(1)
diff --git a/src/test/data/pa1/sample/def_func_nested.py.ast b/src/test/data/pa1/sample/def_func_nested.py.ast
new file mode 100644
index 0000000..0024178
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_nested.py.ast
@@ -0,0 +1,187 @@
+{
+ "kind" : "Program",
+ "location" : [ 2, 1, 10, 7 ],
+ "declarations" : [ {
+ "kind" : "FuncDef",
+ "location" : [ 2, 1, 8, 22 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 7 ],
+ "name" : "foo"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 2, 9, 2, 13 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 9, 2, 9 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 11, 2, 13 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 19, 2, 22 ],
+ "className" : "bool"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 3, 5, 3, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 3, 5, 3, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 3, 5, 3, 5 ],
+ "name" : "a"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 3, 7, 3, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 13, 3, 13 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "VarDef",
+ "location" : [ 4, 5, 4, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 4, 5, 4, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 5, 4, 5 ],
+ "name" : "b"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 7, 4, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 13, 4, 13 ],
+ "value" : 1
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 5, 5, 7, 17 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 9, 5, 11 ],
+ "name" : "bar"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 5, 13, 5, 18 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 13, 5, 13 ],
+ "name" : "y"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 5, 16, 5, 18 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 5, 24, 5, 26 ],
+ "className" : "int"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 6, 9, 6, 17 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 6, 9, 6, 13 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 6, 9, 6, 9 ],
+ "name" : "a"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 6, 11, 6, 13 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 6, 17, 6, 17 ],
+ "value" : 2
+ }
+ } ],
+ "statements" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 7, 9, 7, 16 ],
+ "value" : {
+ "kind" : "Identifier",
+ "location" : [ 7, 16, 7, 16 ],
+ "name" : "y"
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 8, 5, 8, 21 ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 8, 12, 8, 21 ],
+ "left" : {
+ "kind" : "CallExpr",
+ "location" : [ 8, 12, 8, 17 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 12, 8, 14 ],
+ "name" : "bar"
+ },
+ "args" : [ {
+ "kind" : "Identifier",
+ "location" : [ 8, 16, 8, 16 ],
+ "name" : "x"
+ } ]
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 21, 8, 21 ],
+ "name" : "a"
+ }
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 10, 1, 10, 6 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 10, 1, 10, 6 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 10, 1, 10, 3 ],
+ "name" : "foo"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 10, 5, 10, 5 ],
+ "value" : 1
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/def_func_nonlocal.py b/src/test/data/pa1/sample/def_func_nonlocal.py
new file mode 100644
index 0000000..1304328
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_nonlocal.py
@@ -0,0 +1,11 @@
+
+def foo(x:int) -> bool:
+ a:int = 0
+ b:int = 1
+ def bar(y: int) -> int:
+ nonlocal a
+ a = 2
+ return y
+ return bar(x) > a
+
+foo(1)
diff --git a/src/test/data/pa1/sample/def_func_nonlocal.py.ast b/src/test/data/pa1/sample/def_func_nonlocal.py.ast
new file mode 100644
index 0000000..5c1e1de
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_nonlocal.py.ast
@@ -0,0 +1,186 @@
+{
+ "kind" : "Program",
+ "location" : [ 2, 1, 11, 7 ],
+ "declarations" : [ {
+ "kind" : "FuncDef",
+ "location" : [ 2, 1, 9, 22 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 7 ],
+ "name" : "foo"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 2, 9, 2, 13 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 9, 2, 9 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 11, 2, 13 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 19, 2, 22 ],
+ "className" : "bool"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 3, 5, 3, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 3, 5, 3, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 3, 5, 3, 5 ],
+ "name" : "a"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 3, 7, 3, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 13, 3, 13 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "VarDef",
+ "location" : [ 4, 5, 4, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 4, 5, 4, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 5, 4, 5 ],
+ "name" : "b"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 7, 4, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 13, 4, 13 ],
+ "value" : 1
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 5, 5, 8, 17 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 9, 5, 11 ],
+ "name" : "bar"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 5, 13, 5, 18 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 13, 5, 13 ],
+ "name" : "y"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 5, 16, 5, 18 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 5, 24, 5, 26 ],
+ "className" : "int"
+ },
+ "declarations" : [ {
+ "kind" : "NonLocalDecl",
+ "location" : [ 6, 9, 6, 18 ],
+ "variable" : {
+ "kind" : "Identifier",
+ "location" : [ 6, 18, 6, 18 ],
+ "name" : "a"
+ }
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 7, 9, 7, 13 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 7, 9, 7, 9 ],
+ "name" : "a"
+ } ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 7, 13, 7, 13 ],
+ "value" : 2
+ }
+ }, {
+ "kind" : "ReturnStmt",
+ "location" : [ 8, 9, 8, 16 ],
+ "value" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 16, 8, 16 ],
+ "name" : "y"
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 9, 5, 9, 21 ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 9, 12, 9, 21 ],
+ "left" : {
+ "kind" : "CallExpr",
+ "location" : [ 9, 12, 9, 17 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 12, 9, 14 ],
+ "name" : "bar"
+ },
+ "args" : [ {
+ "kind" : "Identifier",
+ "location" : [ 9, 16, 9, 16 ],
+ "name" : "x"
+ } ]
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 21, 9, 21 ],
+ "name" : "a"
+ }
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 11, 1, 11, 6 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 11, 1, 11, 6 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 11, 1, 11, 3 ],
+ "name" : "foo"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 11, 5, 11, 5 ],
+ "value" : 1
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/expr_if.py b/src/test/data/pa1/sample/expr_if.py
new file mode 100644
index 0000000..e9e9c26
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_if.py
@@ -0,0 +1 @@
+3 if 1 > 2 else 4
diff --git a/src/test/data/pa1/sample/expr_if.py.ast b/src/test/data/pa1/sample/expr_if.py.ast
new file mode 100644
index 0000000..0ed9a55
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_if.py.ast
@@ -0,0 +1,43 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 1, 18 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 17 ],
+ "expr" : {
+ "kind" : "IfExpr",
+ "location" : [ 1, 1, 1, 17 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 6, 1, 10 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 6, 1, 6 ],
+ "value" : 1
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 10, 1, 10 ],
+ "value" : 2
+ }
+ },
+ "thenExpr" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 1, 1, 1 ],
+ "value" : 3
+ },
+ "elseExpr" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 17, 1, 17 ],
+ "value" : 4
+ }
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/expr_if_chained.py b/src/test/data/pa1/sample/expr_if_chained.py
new file mode 100644
index 0000000..4a7837e
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_if_chained.py
@@ -0,0 +1 @@
+3 if 1 > 2 else 4 if 1 < 0 else 5
diff --git a/src/test/data/pa1/sample/expr_if_chained.py.ast b/src/test/data/pa1/sample/expr_if_chained.py.ast
new file mode 100644
index 0000000..2776da9
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_if_chained.py.ast
@@ -0,0 +1,67 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 1, 34 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 33 ],
+ "expr" : {
+ "kind" : "IfExpr",
+ "location" : [ 1, 1, 1, 33 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 6, 1, 10 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 6, 1, 6 ],
+ "value" : 1
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 10, 1, 10 ],
+ "value" : 2
+ }
+ },
+ "thenExpr" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 1, 1, 1 ],
+ "value" : 3
+ },
+ "elseExpr" : {
+ "kind" : "IfExpr",
+ "location" : [ 1, 17, 1, 33 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 22, 1, 26 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 22, 1, 22 ],
+ "value" : 1
+ },
+ "operator" : "<",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 26, 1, 26 ],
+ "value" : 0
+ }
+ },
+ "thenExpr" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 17, 1, 17 ],
+ "value" : 4
+ },
+ "elseExpr" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 33, 1, 33 ],
+ "value" : 5
+ }
+ }
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/expr_index.py b/src/test/data/pa1/sample/expr_index.py
new file mode 100644
index 0000000..8e95ff2
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_index.py
@@ -0,0 +1 @@
+a + b[i][j]
diff --git a/src/test/data/pa1/sample/expr_index.py.ast b/src/test/data/pa1/sample/expr_index.py.ast
new file mode 100644
index 0000000..a5f97ee
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_index.py.ast
@@ -0,0 +1,47 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 1, 12 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 11 ],
+ "expr" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 1, 1, 11 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 1 ],
+ "name" : "a"
+ },
+ "operator" : "+",
+ "right" : {
+ "kind" : "IndexExpr",
+ "location" : [ 1, 5, 1, 11 ],
+ "list" : {
+ "kind" : "IndexExpr",
+ "location" : [ 1, 5, 1, 8 ],
+ "list" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 5, 1, 5 ],
+ "name" : "b"
+ },
+ "index" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 7, 1, 7 ],
+ "name" : "i"
+ }
+ },
+ "index" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 10, 1, 10 ],
+ "name" : "j"
+ }
+ }
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/expr_plus.py b/src/test/data/pa1/sample/expr_plus.py
new file mode 100644
index 0000000..8138b36
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_plus.py
@@ -0,0 +1 @@
+1 + 2 + 3
diff --git a/src/test/data/pa1/sample/expr_plus.py.ast b/src/test/data/pa1/sample/expr_plus.py.ast
new file mode 100644
index 0000000..f924e67
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_plus.py.ast
@@ -0,0 +1,39 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 1, 10 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 9 ],
+ "expr" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 1, 1, 9 ],
+ "left" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 1, 1, 5 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 1, 1, 1 ],
+ "value" : 1
+ },
+ "operator" : "+",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 5, 1, 5 ],
+ "value" : 2
+ }
+ },
+ "operator" : "+",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 9, 1, 9 ],
+ "value" : 3
+ }
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/expr_unary.py b/src/test/data/pa1/sample/expr_unary.py
new file mode 100644
index 0000000..3a2e3f4
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_unary.py
@@ -0,0 +1 @@
+-1
diff --git a/src/test/data/pa1/sample/expr_unary.py.ast b/src/test/data/pa1/sample/expr_unary.py.ast
new file mode 100644
index 0000000..e4ef8d2
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_unary.py.ast
@@ -0,0 +1,24 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 1, 3 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 2 ],
+ "expr" : {
+ "kind" : "UnaryExpr",
+ "location" : [ 1, 1, 1, 2 ],
+ "operator" : "-",
+ "operand" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 2, 1, 2 ],
+ "value" : 1
+ }
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/global.py b/src/test/data/pa1/sample/global.py
new file mode 100644
index 0000000..779d3bb
--- /dev/null
+++ b/src/test/data/pa1/sample/global.py
@@ -0,0 +1,5 @@
+x:int = 1
+
+x = 2
+
+print(x)
diff --git a/src/test/data/pa1/sample/global.py.ast b/src/test/data/pa1/sample/global.py.ast
new file mode 100644
index 0000000..84b42b1
--- /dev/null
+++ b/src/test/data/pa1/sample/global.py.ast
@@ -0,0 +1,63 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 5, 9 ],
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 1, 1, 1, 9 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 1, 1, 1, 5 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 1 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 3, 1, 5 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 9, 1, 9 ],
+ "value" : 1
+ }
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 3, 1, 3, 5 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 3, 1, 3, 1 ],
+ "name" : "x"
+ } ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 5, 3, 5 ],
+ "value" : 2
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 5, 1, 5, 8 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 5, 1, 5, 8 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 1, 5, 5 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "Identifier",
+ "location" : [ 5, 7, 5, 7 ],
+ "name" : "x"
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/literals.py b/src/test/data/pa1/sample/literals.py
new file mode 100644
index 0000000..081863e
--- /dev/null
+++ b/src/test/data/pa1/sample/literals.py
@@ -0,0 +1,7 @@
+True
+False
+1
+None
+"This is a string"
+[1, 2, 3]
+
diff --git a/src/test/data/pa1/sample/literals.py.ast b/src/test/data/pa1/sample/literals.py.ast
new file mode 100644
index 0000000..d6fd3bc
--- /dev/null
+++ b/src/test/data/pa1/sample/literals.py.ast
@@ -0,0 +1,70 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 6, 10 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 4 ],
+ "expr" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 1, 1, 1, 4 ],
+ "value" : true
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 2, 1, 2, 5 ],
+ "expr" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 2, 1, 2, 5 ],
+ "value" : false
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 3, 1, 3, 1 ],
+ "expr" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 1, 3, 1 ],
+ "value" : 1
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 4, 1, 4, 4 ],
+ "expr" : {
+ "kind" : "NoneLiteral",
+ "location" : [ 4, 1, 4, 4 ]
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 5, 1, 5, 18 ],
+ "expr" : {
+ "kind" : "StringLiteral",
+ "location" : [ 5, 1, 5, 18 ],
+ "value" : "This is a string"
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 6, 1, 6, 9 ],
+ "expr" : {
+ "kind" : "ListExpr",
+ "location" : [ 6, 1, 6, 9 ],
+ "elements" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 6, 2, 6, 2 ],
+ "value" : 1
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 6, 5, 6, 5 ],
+ "value" : 2
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 6, 8, 6, 8 ],
+ "value" : 3
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_call.py b/src/test/data/pa1/sample/stmt_call.py
new file mode 100644
index 0000000..b917a72
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_call.py
@@ -0,0 +1 @@
+print(1)
diff --git a/src/test/data/pa1/sample/stmt_call.py.ast b/src/test/data/pa1/sample/stmt_call.py.ast
new file mode 100644
index 0000000..4d0ef38
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_call.py.ast
@@ -0,0 +1,28 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 1, 9 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 8 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 1, 1, 1, 8 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 5 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 7, 1, 7 ],
+ "value" : 1
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_for.py b/src/test/data/pa1/sample/stmt_for.py
new file mode 100644
index 0000000..6f65c5f
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_for.py
@@ -0,0 +1,4 @@
+x:int = 0
+for x in [1, 2, 3]:
+ print(x)
+
diff --git a/src/test/data/pa1/sample/stmt_for.py.ast b/src/test/data/pa1/sample/stmt_for.py.ast
new file mode 100644
index 0000000..ba0847b
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_for.py.ast
@@ -0,0 +1,76 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 5, 1 ],
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 1, 1, 1, 9 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 1, 1, 1, 5 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 1 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 3, 1, 5 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 9, 1, 9 ],
+ "value" : 0
+ }
+ } ],
+ "statements" : [ {
+ "kind" : "ForStmt",
+ "location" : [ 2, 1, 5, 1 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 5 ],
+ "name" : "x"
+ },
+ "iterable" : {
+ "kind" : "ListExpr",
+ "location" : [ 2, 10, 2, 18 ],
+ "elements" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 11, 2, 11 ],
+ "value" : 1
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 14, 2, 14 ],
+ "value" : 2
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 17, 2, 17 ],
+ "value" : 3
+ } ]
+ },
+ "body" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 3, 5, 3, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 3, 5, 3, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 3, 5, 3, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "Identifier",
+ "location" : [ 3, 11, 3, 11 ],
+ "name" : "x"
+ } ]
+ }
+ } ]
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_if.py b/src/test/data/pa1/sample/stmt_if.py
new file mode 100644
index 0000000..b87c003
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_if.py
@@ -0,0 +1,3 @@
+if True:
+ False
+
diff --git a/src/test/data/pa1/sample/stmt_if.py.ast b/src/test/data/pa1/sample/stmt_if.py.ast
new file mode 100644
index 0000000..2b08a8f
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_if.py.ast
@@ -0,0 +1,29 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 4, 1 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 1, 1, 4, 1 ],
+ "condition" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 1, 4, 1, 7 ],
+ "value" : true
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 2, 5, 2, 9 ],
+ "expr" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 2, 5, 2, 9 ],
+ "value" : false
+ }
+ } ],
+ "elseBody" : [ ]
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_if_elif.py b/src/test/data/pa1/sample/stmt_if_elif.py
new file mode 100644
index 0000000..7fa86dd
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_if_elif.py
@@ -0,0 +1,6 @@
+if 1 > 2:
+ print(1)
+elif 3 == 4:
+ print(2)
+elif True:
+ print(3)
diff --git a/src/test/data/pa1/sample/stmt_if_elif.py.ast b/src/test/data/pa1/sample/stmt_if_elif.py.ast
new file mode 100644
index 0000000..11dcd2e
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_if_elif.py.ast
@@ -0,0 +1,112 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 7, 1 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 1, 1, 7, 1 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 4, 1, 8 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 4, 1, 4 ],
+ "value" : 1
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 8, 1, 8 ],
+ "value" : 2
+ }
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 2, 5, 2, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 2, 5, 2, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 11, 2, 11 ],
+ "value" : 1
+ } ]
+ }
+ } ],
+ "elseBody" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 3, 1, 7, 1 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 3, 6, 3, 11 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 6, 3, 6 ],
+ "value" : 3
+ },
+ "operator" : "==",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 11, 3, 11 ],
+ "value" : 4
+ }
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 4, 5, 4, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 5, 4, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 5, 4, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 11, 4, 11 ],
+ "value" : 2
+ } ]
+ }
+ } ],
+ "elseBody" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 5, 1, 7, 1 ],
+ "condition" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 5, 6, 5, 9 ],
+ "value" : true
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 6, 5, 6, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 6, 5, 6, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 6, 5, 6, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 6, 11, 6, 11 ],
+ "value" : 3
+ } ]
+ }
+ } ],
+ "elseBody" : [ ]
+ } ]
+ } ]
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_if_elif_else.py b/src/test/data/pa1/sample/stmt_if_elif_else.py
new file mode 100644
index 0000000..161d9d9
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_if_elif_else.py
@@ -0,0 +1,8 @@
+if 1 > 2:
+ print(1)
+elif 3 == 4:
+ print(2)
+elif True:
+ print(3)
+else:
+ print(4)
diff --git a/src/test/data/pa1/sample/stmt_if_elif_else.py.ast b/src/test/data/pa1/sample/stmt_if_elif_else.py.ast
new file mode 100644
index 0000000..dc25855
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_if_elif_else.py.ast
@@ -0,0 +1,129 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 9, 1 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 1, 1, 9, 1 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 4, 1, 8 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 4, 1, 4 ],
+ "value" : 1
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 8, 1, 8 ],
+ "value" : 2
+ }
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 2, 5, 2, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 2, 5, 2, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 11, 2, 11 ],
+ "value" : 1
+ } ]
+ }
+ } ],
+ "elseBody" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 3, 1, 9, 1 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 3, 6, 3, 11 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 6, 3, 6 ],
+ "value" : 3
+ },
+ "operator" : "==",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 11, 3, 11 ],
+ "value" : 4
+ }
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 4, 5, 4, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 5, 4, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 5, 4, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 11, 4, 11 ],
+ "value" : 2
+ } ]
+ }
+ } ],
+ "elseBody" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 5, 1, 9, 1 ],
+ "condition" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 5, 6, 5, 9 ],
+ "value" : true
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 6, 5, 6, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 6, 5, 6, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 6, 5, 6, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 6, 11, 6, 11 ],
+ "value" : 3
+ } ]
+ }
+ } ],
+ "elseBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 8, 5, 8, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 8, 5, 8, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 5, 8, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 8, 11, 8, 11 ],
+ "value" : 4
+ } ]
+ }
+ } ]
+ } ]
+ } ]
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_ifelse.py b/src/test/data/pa1/sample/stmt_ifelse.py
new file mode 100644
index 0000000..f138957
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_ifelse.py
@@ -0,0 +1,5 @@
+if True:
+ False
+else:
+ True
+
diff --git a/src/test/data/pa1/sample/stmt_ifelse.py.ast b/src/test/data/pa1/sample/stmt_ifelse.py.ast
new file mode 100644
index 0000000..8e23d16
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_ifelse.py.ast
@@ -0,0 +1,37 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 6, 1 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 1, 1, 6, 1 ],
+ "condition" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 1, 4, 1, 7 ],
+ "value" : true
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 2, 5, 2, 9 ],
+ "expr" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 2, 5, 2, 9 ],
+ "value" : false
+ }
+ } ],
+ "elseBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 4, 5, 4, 8 ],
+ "expr" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 4, 5, 4, 8 ],
+ "value" : true
+ }
+ } ]
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_list_assign.py b/src/test/data/pa1/sample/stmt_list_assign.py
new file mode 100644
index 0000000..e9e31d9
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_list_assign.py
@@ -0,0 +1,4 @@
+x:int = None
+
+x = [1, 2, 3]
+x[0] = x[1]
diff --git a/src/test/data/pa1/sample/stmt_list_assign.py.ast b/src/test/data/pa1/sample/stmt_list_assign.py.ast
new file mode 100644
index 0000000..b65848c
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_list_assign.py.ast
@@ -0,0 +1,88 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 4, 12 ],
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 1, 1, 1, 12 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 1, 1, 1, 5 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 1 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 3, 1, 5 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "NoneLiteral",
+ "location" : [ 1, 9, 1, 12 ]
+ }
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 3, 1, 3, 13 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 3, 1, 3, 1 ],
+ "name" : "x"
+ } ],
+ "value" : {
+ "kind" : "ListExpr",
+ "location" : [ 3, 5, 3, 13 ],
+ "elements" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 6, 3, 6 ],
+ "value" : 1
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 9, 3, 9 ],
+ "value" : 2
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 12, 3, 12 ],
+ "value" : 3
+ } ]
+ }
+ }, {
+ "kind" : "AssignStmt",
+ "location" : [ 4, 1, 4, 11 ],
+ "targets" : [ {
+ "kind" : "IndexExpr",
+ "location" : [ 4, 1, 4, 4 ],
+ "list" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 1, 4, 1 ],
+ "name" : "x"
+ },
+ "index" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 3, 4, 3 ],
+ "value" : 0
+ }
+ } ],
+ "value" : {
+ "kind" : "IndexExpr",
+ "location" : [ 4, 8, 4, 11 ],
+ "list" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 8, 4, 8 ],
+ "name" : "x"
+ },
+ "index" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 10, 4, 10 ],
+ "value" : 1
+ }
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_while.py b/src/test/data/pa1/sample/stmt_while.py
new file mode 100644
index 0000000..1aaefd8
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_while.py
@@ -0,0 +1,3 @@
+while True:
+ pass
+
diff --git a/src/test/data/pa1/sample/stmt_while.py.ast b/src/test/data/pa1/sample/stmt_while.py.ast
new file mode 100644
index 0000000..a564490
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_while.py.ast
@@ -0,0 +1,20 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 4, 1 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "WhileStmt",
+ "location" : [ 1, 1, 4, 1 ],
+ "condition" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 1, 7, 1, 10 ],
+ "value" : true
+ },
+ "body" : [ ]
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/student_contributed/bad.py b/src/test/data/pa1/student_contributed/bad.py
new file mode 100644
index 0000000..95bf0f0
--- /dev/null
+++ b/src/test/data/pa1/student_contributed/bad.py
@@ -0,0 +1,39 @@
+1 2 3
+
+def fun5():
+ c = 6
+ def fun6():
+ print("Hello")
+ c = 4 + 5 # Indentation error
+
+# Global statements in between definitions
+# (not allowed in the language manual)
+if True:
+ if True:
+ print("Hello")
+ if True:
+ print("Maybe")
+ else:
+ print("World")
+else:
+ print("Again")
+else:
+ print("And Again") # Unmatched Else
+
+class Thor(object):
+ y:int = 0
+ print("Right place?") # Statement in class
+
+class Stones(object):
+ y:int = 0
+ def fun(x:int):
+ print("Right place?")
+ def bar():
+ return 2+3
+ print("Wrong Place")
+
+# Functions without `statements'
+# (not allowed in the language manual)
+def fun1():
+ def fun2():
+ print("Hello")
diff --git a/src/test/data/pa1/student_contributed/good.py b/src/test/data/pa1/student_contributed/good.py
new file mode 100644
index 0000000..874fa40
--- /dev/null
+++ b/src/test/data/pa1/student_contributed/good.py
@@ -0,0 +1,82 @@
+class Foo(object):
+ x:int = 0
+
+ def __init__(self:"Foo", x:int):
+ self.x = x
+
+ def bar(y:int):
+ print("Hello World!",self.x+y)
+ y = 10
+
+def get_stones(name:str)->str:
+ def map_name(nm:str)->str:
+ return stones[color.index(nm)]
+ color=["Red","Blue"]
+ stones=["Mind","Soul"]
+ return map_name(name)
+
+def funa():
+ def funb():
+ print("Hello")
+ funb()
+
+def fund():
+ def fune():
+ print("Hello")
+ c = 4 + 5
+
+def funf():
+ def fung():
+ print("Hello")
+ c = 6
+ c = 4 + 5
+
+
+if True:
+ if True:
+ if True:
+ print("Hello")
+print("World")
+
+if True:
+ if True:
+ if True:
+ print("Hello")
+ print("World")
+
+if True:
+ if True:
+ if True:
+ print("Hello")
+ print("World")
+
+if True:
+ if True:
+ if True:
+ print("Hello")
+ else:
+ print("World")
+
+if True:
+ if True:
+ if True:
+ print("Hello")
+else:
+ print("World")
+
+
+
+f = Foo(1)
+print(f.x)
+f.bar(4)
+
+a=[[[1],[2]],[[3],[4]]]
+print(a[0][0][1]*a[1][1][0])
+
+multiline_string="Hi World,\
+Here I am"
+
+expr_precedence = -a + b * (c + d)
+
+stone="Blue"
+print(get_stones(stone))
\ No newline at end of file
diff --git a/src/test/data/pa2/student_contributed/bad_semantic.py b/src/test/data/pa2/student_contributed/bad_semantic.py
index a7a1b23..490a475 100644
--- a/src/test/data/pa2/student_contributed/bad_semantic.py
+++ b/src/test/data/pa2/student_contributed/bad_semantic.py
@@ -2,3 +2,13 @@ x:int = 1
x:int = 2
x
+
+def fun_1() -> bool:
+ if True:
+ if True:
+ return True
+ # All path should return, not just one
+
+
+fun_1()
+
diff --git a/src/test/data/pa2/student_contributed/bad_types.py b/src/test/data/pa2/student_contributed/bad_types.py
index 7d76df7..91ba352 100644
--- a/src/test/data/pa2/student_contributed/bad_types.py
+++ b/src/test/data/pa2/student_contributed/bad_types.py
@@ -1,2 +1,5 @@
x:int = True
x + [1]
+
+y:bool = False
+x = y = z = "Error"
diff --git a/src/test/data/pa2/student_contributed/good.py b/src/test/data/pa2/student_contributed/good.py
index a036d62..c16c124 100644
--- a/src/test/data/pa2/student_contributed/good.py
+++ b/src/test/data/pa2/student_contributed/good.py
@@ -1,2 +1,83 @@
-x:int = 1
-x * 1
+# Below this point we have all the same test cases from PA1 for validation purposes.
+class Foo(object):
+ x:int = 0
+
+ def __init__(self:"Foo", x:int):
+ self.x = x
+
+ def bar(y:int):
+ print("Hello World!",self.x+y)
+ y = 10
+
+def get_stones(name:str)->str:
+ def map_name(nm:str)->str:
+ return stones[color.index(nm)]
+ color=["Red","Blue"]
+ stones=["Mind","Soul"]
+ return map_name(name)
+
+def funa():
+ def funb():
+ print("Hello")
+ funb()
+
+def fund():
+ def fune():
+ print("Hello")
+ c = 4 + 5
+
+def funf():
+ def fung():
+ print("Hello")
+ c = 6
+ c = 4 + 5
+
+
+if True:
+ if True:
+ if True:
+ print("Hello")
+print("World")
+
+if True:
+ if True:
+ if True:
+ print("Hello")
+ print("World")
+
+if True:
+ if True:
+ if True:
+ print("Hello")
+ print("World")
+
+if True:
+ if True:
+ if True:
+ print("Hello")
+ else:
+ print("World")
+
+if True:
+ if True:
+ if True:
+ print("Hello")
+else:
+ print("World")
+
+
+
+f = Foo(1)
+print(f.x)
+f.bar(4)
+
+a=[[[1],[2]],[[3],[4]]]
+print(a[0][0][1]*a[1][1][0])
+
+multiline_string="Hi World,\
+Here I am"
+
+expr_precedence = -a + b * (c + d)
+
+stone="Blue"
+print(get_stones(stone))
diff --git a/test_py_file.sh b/test_py_file.sh
new file mode 100755
index 0000000..4e47b37
--- /dev/null
+++ b/test_py_file.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+FILENAME=$1
+
+if [ -z "$1" ] ; then
+ echo "Usage for individual test cases: test.sh FILEPATH, where FILEPATH is the location of the python file"
+ exit 1
+fi
+
+echo "Testing file ${FILENAME}"
+
+java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy --pass=sr \
+ ${FILENAME} --out=${FILENAME}.ast.typed
+
+java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy \
+ --pass=ss --test ${FILENAME}
diff --git a/test_sample.sh b/test_sample.sh
new file mode 100755
index 0000000..45a1a40
--- /dev/null
+++ b/test_sample.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+
+echo "Running all test cases inside src/test/data/pa2/sample/ folder)"
+java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy --pass=ss --test --dir src/test/data/pa2/sample/
diff --git a/test_student_contributed.sh b/test_student_contributed.sh
new file mode 100755
index 0000000..34a9693
--- /dev/null
+++ b/test_student_contributed.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+echo "Running all test cases inside src/test/data/pa2/sample/ folder)"
+java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy --pass=ss --test --dir src/test/data/pa2/student_contributed/