commit 54e35e2b89ce44c15a3b5e13128ccbc22a9a6792 Author: github-classroom[bot] <66690702+github-classroom[bot]@users.noreply.github.com> Date: Tue Feb 9 10:56:17 2021 +0000 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..21cc758 --- /dev/null +++ b/.gitignore @@ -0,0 +1,149 @@ +.DS_Store +__pycache__ +target + +# Created by https://www.gitignore.io/api/java,eclipse,intellij,emacs,vim + +### Java ### +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + + +### Eclipse ### +*.pydevproject +.metadata +.gradle +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific +.buildpath + +# sbteclipse plugin +.target + +# TeXlipse plugin +.texlipse + + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio + +*.iml + +## Directory-based project format: +.idea/ +# if you remove the above rule, at least ignore the following: + +# User-specific stuff: +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/dictionaries + +# Sensitive or high-churn files: +# .idea/dataSources.ids +# .idea/dataSources.xml +# .idea/sqlDataSources.xml +# .idea/dynamic.xml +# .idea/uiDesigner.xml + +# Gradle: +# .idea/gradle.xml +# .idea/libraries + +# Mongo Explorer plugin: +# .idea/mongoSettings.xml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties + + +### Emacs ### +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ + + +### Vim ### +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist +*~ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0808d4b --- /dev/null +++ b/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2017-2018 The Regents of the University of California + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f6e4b4a --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# NYU Compiler Construction CSCI-GA.2130/Spring 2021: Programming Assignment 1 + +This assignment is adapted from https://github.com/cs164berkeley/pa1-chocopy-parser/ with the authors' permission. + +See the PA1 document on Piazza for a detailed specification. + +## Quickstart + +Run the following commands to generate and compile your parser and run the tests: +``` +mvn clean package +java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy \ + --pass=s --test --dir src/test/data/pa1/sample/ +``` + +`--pass=s` uses your parser (`s` for `student`), and with the starter code, only one test should pass. +`--pass=r` uses the reference parser (`r` for `reference`), which should pass all tests. + +In addition to running in test mode with `--test`, you can also observe the actual output +of your (or reference) parser with: +``` +java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy \ + --pass=s src/test/data/pa1/sample/expr_plus.py +``` diff --git a/chocopy-ref.jar b/chocopy-ref.jar new file mode 100644 index 0000000..31646a6 Binary files /dev/null and b/chocopy-ref.jar differ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..1766e51 --- /dev/null +++ b/pom.xml @@ -0,0 +1,330 @@ + + 4.0.0 + chocopy + chocopy + jar + 2.2-SNAPSHOT + chocopy + http://maven.apache.org + + + + false + + + + + + + + de.jflex + jflex-maven-plugin + 1.6.1 + + + com.github.vbmacher + cup-maven-plugin + 11b-20160615 + + + maven-assembly-plugin + 3.1.0 + + + maven-jar-plugin + 3.1.0 + + + maven-site-plugin + 3.7.1 + + + + + + + maven-assembly-plugin + + + jar-with-dependencies + + assignment + false + + + + make-assembly + package + + single + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + UTF-8 + 1.8 + 1.8 + true + true + + + + + + + src/main/asm + + **/*.s + **/*.os + + + **/reference/*.s + + + + + + + + reference + + + + src/main/java/chocopy/reference/ + + + + + + + maven-jar-plugin + + + **/pa1/* + **/pa2/* + **/pa3/* + + + + + + maven-assembly-plugin + + + jar-with-dependencies + + chocopy-ref + false + + + + + de.jflex + jflex-maven-plugin + + + jflex-reference + + generate + + + + src/main/jflex/chocopy/reference/ChocoPy.jflex + + ${chocopy.debug} + true + + + + + + + com.github.vbmacher + cup-maven-plugin + + + cup-reference + + generate + + + src/main/cup/chocopy/reference/ChocoPy.cup + chocopy.reference + ChocoPyParser + ChocoPyTokens + ${chocopy.debug} + ${chocopy.debug} + ${chocopy.debug} + true + + + + + + + maven-compiler-plugin + + true + none + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + copy-dependencies + package + + copy-dependencies + + + + + + + + + + pa1 + + + + src/main/java/chocopy/pa1 + + + + + + + de.jflex + jflex-maven-plugin + + + jflex-pa1 + + generate + + + + src/main/jflex/chocopy/pa1/ChocoPy.jflex + + ${chocopy.debug} + true + + + + + + + com.github.vbmacher + cup-maven-plugin + + + cup-pa1 + + generate + + + src/main/cup/chocopy/pa1/ChocoPy.cup + chocopy.pa1 + ChocoPyParser + ChocoPyTokens + ${chocopy.debug} + ${chocopy.debug} + ${chocopy.debug} + true + + + + + + + + + pa2 + + + + src/main/java/chocopy/pa2 + + + + + pa3 + + + + src/main/java/chocopy/pa3 + + + + + + + + + venus164-repo + Repository for Venus164 + https://raw.githubusercontent.com/chocopy/venus/maven-repository/ + + + + + + net.sourceforge.argparse4j + argparse4j + 0.8.1 + + + com.fasterxml.jackson.core + jackson-databind + [2.9.10.1,) + + + com.fasterxml.jackson.module + jackson-module-parameter-names + 2.9.10 + + + com.github.vbmacher + java-cup-runtime + 11b-20160615 + + + + de.jflex + jflex + 1.6.1 + + + org.jetbrains.kotlin + kotlin-stdlib + 1.2.71 + + + edu.berkeley.eecs.venus164 + venus164 + 0.2.4 + + + junit + junit + 4.12 + test + + + net.sf.proguard + proguard-base + 6.0.3 + + + diff --git a/src/main/cup/chocopy/pa1/ChocoPy.cup b/src/main/cup/chocopy/pa1/ChocoPy.cup new file mode 100644 index 0000000..d4ff444 --- /dev/null +++ b/src/main/cup/chocopy/pa1/ChocoPy.cup @@ -0,0 +1,214 @@ +import java.util.ArrayList; +import java.util.List; + +import java_cup.runtime.*; +import chocopy.common.astnodes.*; + +/* The following code section is copied verbatim to the generated + * parser class. */ +parser code {: + + /* The following fields and methods deal with error reporting + * Avoid changing these unless you know what you are doing. */ + + /** Node that accumulates error messages to be added to the Program + * node produced as a result. */ + public final Errors errors = new Errors(new ArrayList<>()); + + /** Return the Program node that results from parsing the stream of + * tokens produced by lexical analysis. In the case of syntax errors, + * the program may be empty, but will have error messages. */ + public Program parseProgram(boolean debug) { + try { + Symbol result = debug ? debug_parse() : parse(); + if (result == null || !(result.value instanceof Program)) { + return new Program(new Location(0, 0), new Location(0, 0), + new ArrayList(), + new ArrayList(), + errors); + } else { + return (Program) result.value; + } + } catch (RuntimeException excp) { + throw excp; + } catch (Exception excp) { + String msg = + String.format("Internal parser error detected: %s%n", excp); + throw new AssertionError(msg); + } + } + + @Override + public SymbolFactory getSymbolFactory() { + return ((ChocoPyLexer) getScanner()).symbolFactory; + } + + @Override + public void syntax_error(Symbol cur_token) { + String token = symbl_name_from_id(cur_token.sym); + String text = ((ChocoPyLexer) getScanner()).yytext(); + errors.syntaxError( + ((ComplexSymbolFactory.ComplexSymbol) cur_token).xleft, + ((ComplexSymbolFactory.ComplexSymbol) cur_token).xright, + "Parse error near token %s: %s", token, text); + } + + @Override + public void unrecovered_syntax_error(Symbol cur_token) { + /* Do not die */ + } +:} + + +/************************************************************************** + * FEEL FREE TO MODIFY ANYTHING BELOW THIS LINE + * + * The rules provided below parse expressions of the form + + ... + * You can re-use these rules or edit them as you wish. The start rule + * should return a node of type Program. + * + * Tips: Production rules are usually followed by action code that will be + * copied to the generated parser to be executed immediately after a reduce + * operation; that is, when a production rule has been matched. You can name + * a nonterminal or terminal symbol in a production rule using the colon + * notation, e.g. expr_stmt ::= expr:e, to get the AST node for the matched + * expression. In the action code, `e` will be a variable of whatever type + * has been declared for the corresponding nonterminal, such as `Expr`. + * Therefore, you can construct an AST Node of type `ExprStmt` with `e` in the + * constructor: `new ExprStmt(exleft, exright, e)` + * + * The variables `exleft` and `exright` are automatically generated by CUP + * and contain Location objects for the start and end of the expression `e`. + * You can collect start and line number info for AST nodes by taking the + * location of the left end of the leftmost symbol in a rule and the + * location of the right end of the rightmost symbol. The auto-generated + * variables have names `xleft` and `xright`, where is the + * name given to the symbol using the colon notation. + * + * When you have nonterminals that are lists of things, e.g. List or + * List, it is helpful to get the leftmost and rightmost + * source location from within this list; we have provided some utility + * functions below to do just that. + **************************************************************************/ + + +/* The following code section is copied verbatim to the class that performs + * production-rule actions. */ +action code {: + + /** Return a mutable list initially containing the single value ITEM. */ + List single(T item) { + List list = new ArrayList<>(); + if (item != null) { + list.add(item); + } + return list; + } + + /** If ITEM is non-null, appends it to the end of LIST. Then returns + * LIST. */ + List combine(List list, T item) { + if (item != null) { + list.add(item); + } + return list; + } + + /** Return a mutable empty list. */ + List empty() { + return new ArrayList(); + } + + /** Return the leftmost non-whitespace location in NODES, or null if NODES + * is empty. Assumes that the nodes of NODES are ordered in increasing + * order of location, from left to right. */ + ComplexSymbolFactory.Location getLeft(List nodes) { + if (nodes.isEmpty()) { + return null; + } + Node first = nodes.get(0); + return new ComplexSymbolFactory.Location(first.getLocation()[0], + first.getLocation()[1]); + } + +:} + +/* Terminal symbols (tokens returned by the lexer). The declaration + * terminal , , ...; + * declares each as the denotation of a distinct type terminal + * symbol for use in the grammar. The declaration + * terminal , ...; + * does the same, and in addition indicates that the lexer supplies a + * semantic value of type for these symbols that may be referenced + * in actions ( {: ... :} ). + */ +terminal NEWLINE; +terminal String PLUS; +terminal Integer NUMBER; +/* Returned by the lexer for erroneous tokens. Since it does not appear in + * the grammar, it indicates a syntax error. */ +terminal UNRECOGNIZED; + +/* Nonterminal symbols (defined in production rules below). + * As for terminal symbols, + * non terminal , ..., ; + * defines the listed nonterminal identifier symbols to have semantic values + * of type . */ +non terminal Program program; +non terminal List program_head; +non terminal List stmt_list, opt_stmt_list; +non terminal Stmt stmt, expr_stmt; +non terminal Expr expr, binary_expr; + +/* Precedences (lowest to highest) for resolving what would otherwise be + * ambiguities in the form of shift/reduce conflicts.. */ +precedence left PLUS; + +/* The start symbol. */ +start with program; + + +/***** GRAMMAR RULES *****/ + +program ::= program_head:d opt_stmt_list:s + {: RESULT = new Program(d.isEmpty() ? getLeft(s) : getLeft(d), + sxright, d, s, errors); + :} + ; + +/* Initial list of declarations. */ +program_head ::= /* not implemented; currently matches empty string */ + {: RESULT = empty(); :} + ; + +opt_stmt_list ::= {: RESULT = empty(); :} + | stmt_list:s {: RESULT = s; :} + ; + +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. */ + ; + +stmt ::= expr_stmt:s NEWLINE {: RESULT = s; :} + ; + +expr_stmt ::= expr:e {: RESULT = new ExprStmt(exleft, exright, e); :} + ; + +expr ::= binary_expr:e {: RESULT = e; :} + | NUMBER:n {: RESULT = new IntegerLiteral(nxleft, nxright, n); :} + ; + + +/* A binary expression, illustrating how to find the left and right + * source position of a phrase. */ +binary_expr ::= expr:e1 PLUS:op expr:e2 + {: RESULT = new BinaryExpr(e1xleft, e2xright, + e1, op, e2); :} + ; diff --git a/src/main/java/chocopy/common/Utils.java b/src/main/java/chocopy/common/Utils.java new file mode 100644 index 0000000..661dfd3 --- /dev/null +++ b/src/main/java/chocopy/common/Utils.java @@ -0,0 +1,64 @@ +package chocopy.common; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.stream.Collectors; + + +/** + * Utility functions for general use. + */ +public class Utils { + + /** + * Return resource file FILENAME's contents as a string. FILENAME + * can refer to a file within the class hierarchy, so that a text + * resource in file resource.txt in the chocopy.common.codegen + * package, for example, could be referred to with FILENAME + * chocopy/common/codegen/resource.txt. + *

+ * Credit: Lucio Paiva. + */ + public static String getResourceFileAsString(String fileName) { + InputStream is = + Utils.class.getClassLoader().getResourceAsStream(fileName); + if (is != null) { + BufferedReader reader = + new BufferedReader + (new InputStreamReader(is, StandardCharsets.UTF_8)); + return reader.lines().collect + (Collectors.joining(System.lineSeparator())); + } + return null; + } + + /** + * Return an exception signalling a fatal error having a message + * formed from MSGFORMAT and ARGS, as for String.format. + */ + public static Error fatal(String msgFormat, Object... args) { + return new Error(String.format(msgFormat, args)); + } + + /** + * Return the string S padded with FILL to TOLEN characters. Padding + * is on the left if PADONLEFT, and otherwise on the right. If S is + * already at least TOLEN characters, returns S. + */ + public static String pad(String s, Character fill, int toLen, + boolean padOnLeft) { + StringBuilder result = new StringBuilder(toLen); + if (!padOnLeft) { + result.append(s); + } + for (int n = s.length(); n < toLen; n += 1) { + result.append(fill); + } + if (padOnLeft) { + result.append(s); + } + return result.toString(); + } +} diff --git a/src/main/java/chocopy/common/analysis/NodeAnalyzer.java b/src/main/java/chocopy/common/analysis/NodeAnalyzer.java new file mode 100644 index 0000000..5ea8a6c --- /dev/null +++ b/src/main/java/chocopy/common/analysis/NodeAnalyzer.java @@ -0,0 +1,100 @@ +package chocopy.common.analysis; + +import chocopy.common.astnodes.*; + +/** + * 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. + */ +public interface NodeAnalyzer { + + T analyze(AssignStmt node); + + T analyze(BinaryExpr node); + + T analyze(BooleanLiteral node); + + T analyze(CallExpr node); + + T analyze(ClassDef node); + + T analyze(ClassType node); + + T analyze(CompilerError node); + + T analyze(Errors node); + + T analyze(ExprStmt node); + + T analyze(ForStmt node); + + T analyze(FuncDef node); + + T analyze(GlobalDecl node); + + T analyze(Identifier node); + + T analyze(IfExpr node); + + T analyze(IfStmt node); + + T analyze(IndexExpr node); + + T analyze(IntegerLiteral node); + + T analyze(ListExpr node); + + T analyze(ListType node); + + T analyze(MemberExpr node); + + T analyze(MethodCallExpr node); + + T analyze(NoneLiteral node); + + T analyze(NonLocalDecl node); + + T analyze(Program node); + + T analyze(ReturnStmt node); + + T analyze(StringLiteral node); + + T analyze(TypedVar node); + + T analyze(UnaryExpr node); + + T analyze(VarDef node); + + T analyze(WhileStmt node); + + /** + * Set the default value returned by calls to analyze that are not + * overridden to VALUE. By default, this is null. + */ + void setDefault(T value); + + /** + * Default value for non-overridden methods. + */ + T defaultAction(Node node); +} diff --git a/src/main/java/chocopy/common/astnodes/AssignStmt.java b/src/main/java/chocopy/common/astnodes/AssignStmt.java new file mode 100644 index 0000000..8b3f49c --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/AssignStmt.java @@ -0,0 +1,36 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +import java.util.List; + +/** + * Single and multiple assignments. + */ +public class AssignStmt extends Stmt { + /** + * List of left-hand sides. + */ + public final List targets; + /** + * Right-hand-side value to be assigned. + */ + public final Expr value; + + /** + * AST for TARGETS[0] = TARGETS[1] = ... = VALUE spanning source locations + * [LEFT..RIGHT]. + */ + public AssignStmt(Location left, Location right, + List targets, Expr value) { + super(left, right); + this.targets = targets; + this.value = value; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/BinaryExpr.java b/src/main/java/chocopy/common/astnodes/BinaryExpr.java new file mode 100644 index 0000000..3ef3d46 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/BinaryExpr.java @@ -0,0 +1,40 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +/** + * . + */ +public class BinaryExpr extends Expr { + + /** + * Left operand. + */ + public final Expr left; + /** + * Operator name. + */ + public final String operator; + /** + * Right operand. + */ + public final Expr right; + + /** + * An AST for expressions of the form LEFTEXPR OP RIGHTEXPR + * from text in range [LEFTLOC..RIGHTLOC]. + */ + public BinaryExpr(Location leftLoc, Location rightLoc, Expr leftExpr, + String op, Expr rightExpr) { + super(leftLoc, rightLoc); + left = leftExpr; + operator = op; + right = rightExpr; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/BooleanLiteral.java b/src/main/java/chocopy/common/astnodes/BooleanLiteral.java new file mode 100644 index 0000000..bf13f08 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/BooleanLiteral.java @@ -0,0 +1,29 @@ +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 { + + /** + * True iff I represent True. + */ + public final boolean value; + + /** + * An AST for the token True or False at [LEFT..RIGHT], depending on + * VALUE. + */ + public BooleanLiteral(Location left, Location right, boolean value) { + super(left, right); + this.value = value; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/CallExpr.java b/src/main/java/chocopy/common/astnodes/CallExpr.java new file mode 100644 index 0000000..80272ee --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/CallExpr.java @@ -0,0 +1,36 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +import java.util.List; + +/** + * A function call. + */ +public class CallExpr extends Expr { + + /** + * The called function. + */ + public final Identifier function; + /** + * The actual parameter expressions. + */ + public final List args; + + /** + * AST for FUNCTION(ARGS) at [LEFT..RIGHT]. + */ + public CallExpr(Location left, Location right, Identifier function, + List args) { + super(left, right); + this.function = function; + this.args = args; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/ClassDef.java b/src/main/java/chocopy/common/astnodes/ClassDef.java new file mode 100644 index 0000000..982d128 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/ClassDef.java @@ -0,0 +1,50 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +import java.util.List; + +/** + * A class definition. + */ +public class ClassDef extends Declaration { + + /** + * Name of the declared class. + */ + public final Identifier name; + /** + * Name of the parent class. + */ + public final Identifier superClass; + /** + * Body of the class. + */ + public final List declarations; + + /** + * An AST for class + * NAME(SUPERCLASS): + * DECLARATIONS. + * spanning source locations [LEFT..RIGHT]. + */ + public ClassDef(Location left, Location right, + Identifier name, Identifier superClass, + List declarations) { + super(left, right); + this.name = name; + this.superClass = superClass; + this.declarations = declarations; + } + + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + + @Override + public Identifier getIdentifier() { + return this.name; + } +} diff --git a/src/main/java/chocopy/common/astnodes/ClassType.java b/src/main/java/chocopy/common/astnodes/ClassType.java new file mode 100644 index 0000000..eab39af --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/ClassType.java @@ -0,0 +1,28 @@ +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 { + + /** + * The denotation of the class in source. + */ + public final String className; + + /** + * An AST denoting a type named CLASSNAME0 at [LEFT..RIGHT]. + */ + public ClassType(Location left, Location right, String className0) { + super(left, right); + className = className0; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/CompilerError.java b/src/main/java/chocopy/common/astnodes/CompilerError.java new file mode 100644 index 0000000..c61617e --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/CompilerError.java @@ -0,0 +1,64 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import com.fasterxml.jackson.annotation.JsonInclude; +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 { + + /** + * Represents an error with message MESSAGE. Iff SYNTAX, it is a + * syntactic error. The error applies to source text at [LEFT..RIGHT]. + */ + public CompilerError(Location left, Location right, String message, + boolean syntax) { + super(left, right); + this.message = message; + this.syntax = syntax; + } + + @JsonInclude(JsonInclude.Include.NON_DEFAULT) + public boolean isSyntax() { + return syntax; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CompilerError that = (CompilerError) o; + return Objects.equals(message, that.message) + && Arrays.equals(getLocation(), that.getLocation()); + } + + @Override + public int hashCode() { + int result = Objects.hash(message); + result = 31 * result + Arrays.hashCode(getLocation()); + return result; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + + /** + * The error message. + */ + public final String message; + /** + * True if this is a syntax error. + */ + private final boolean syntax; +} diff --git a/src/main/java/chocopy/common/astnodes/Declaration.java b/src/main/java/chocopy/common/astnodes/Declaration.java new file mode 100644 index 0000000..769ece3 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/Declaration.java @@ -0,0 +1,23 @@ +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 { + + /** + * A definition or declaration spanning source locations [LEFT..RIGHT]. + */ + public Declaration(Location left, Location right) { + 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 new file mode 100644 index 0000000..cea2c5b --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/Errors.java @@ -0,0 +1,90 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +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 { + + /** + * The accumulated error messages in the order added. + */ + public final List errors; + + /** + * True iff multiple semantic errors allowed on a node. + */ + @JsonIgnore + private boolean allowMultipleErrors; + + /** + * An Errors whose list of CompilerErrors is ERRORS. The list should be + * modified using this.add. + */ + @JsonCreator + public Errors(List errors) { + super(null, null); + this.errors = errors; + 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; + } + + /** + * Add a new semantic error message attributed to NODE, with message + * String.format(MESSAGEFORM, ARGS). + */ + public void semError(Node node, String messageForm, Object... args) { + if (allowMultipleErrors || !node.hasError()) { + String msg = String.format(messageForm, args); + CompilerError err = new CompilerError(null, null, msg, false); + err.setLocation(node.getLocation()); + add(err); + if (!node.hasError()) { + node.setErrorMsg(msg); + } + } + } + + /** + * Add a new syntax error message attributed to the source text + * between LEFT and RIGHT, and with message + * String.format(MESSAGEFORM, ARGS). + */ + public void syntaxError(Location left, Location right, + String messageForm, Object... args) { + add(new CompilerError(left, right, String.format(messageForm, args), + true)); + } + + /** + * Add ERR to the list of errors. + */ + public void add(CompilerError err) { + errors.add(err); + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/Expr.java b/src/main/java/chocopy/common/astnodes/Expr.java new file mode 100644 index 0000000..c5cb884 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/Expr.java @@ -0,0 +1,22 @@ +package chocopy.common.astnodes; + +import java_cup.runtime.ComplexSymbolFactory.Location; + +/** + * Base of all AST nodes representing expressions. + *

+ * There is nothing in this class, but there will be many AST + * node types that have fields that are *any expression*. For those + * cases, having a field of this type will encompass all types of + * expressions such as binary expressions and literals that subclass + * this class. + */ +public abstract class Expr extends Node { + + /** + * A Python expression spanning source locations [LEFT..RIGHT]. + */ + public Expr(Location left, Location right) { + super(left, right); + } +} diff --git a/src/main/java/chocopy/common/astnodes/ExprStmt.java b/src/main/java/chocopy/common/astnodes/ExprStmt.java new file mode 100644 index 0000000..177c407 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/ExprStmt.java @@ -0,0 +1,29 @@ +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 { + + /** + * The expression I evaluate. + */ + public final Expr expr; + + /** + * The AST for EXPR spanning source locations [LEFT..RIGHT] + * in a statement context. + */ + public ExprStmt(Location left, Location right, Expr expr) { + super(left, right); + this.expr = expr; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/ForStmt.java b/src/main/java/chocopy/common/astnodes/ForStmt.java new file mode 100644 index 0000000..8463da1 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/ForStmt.java @@ -0,0 +1,43 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +import java.util.List; + +/** + * For statements. + */ +public class ForStmt extends Stmt { + /** + * Control variable. + */ + public final Identifier identifier; + /** + * Source of values of control statement. + */ + public final Expr iterable; + /** + * Repeated statements. + */ + public final List body; + + /** + * The AST for + * for IDENTIFIER in ITERABLE: + * BODY + * spanning source locations [LEFT..RIGHT]. + */ + public ForStmt(Location left, Location right, + Identifier identifier, Expr iterable, List body) { + super(left, right); + this.identifier = identifier; + this.iterable = iterable; + this.body = body; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/FuncDef.java b/src/main/java/chocopy/common/astnodes/FuncDef.java new file mode 100644 index 0000000..42f67bf --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/FuncDef.java @@ -0,0 +1,61 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +import java.util.List; + +/** + * Def statements. + */ +public class FuncDef extends Declaration { + + /** + * Defined name. + */ + public final Identifier name; + /** + * Formal parameters. + */ + public final List params; + /** + * Return type annotation. + */ + public final TypeAnnotation returnType; + /** + * Local-variable,inner-function, global, and nonlocal declarations. + */ + public final List declarations; + /** + * Other statements. + */ + public final List statements; + + /** + * The AST for + * def NAME(PARAMS) -> RETURNTYPE: + * DECLARATIONS + * STATEMENTS + * spanning source locations [LEFT..RIGHT]. + */ + public FuncDef(Location left, Location right, + Identifier name, List params, + TypeAnnotation returnType, + List declarations, List statements) { + super(left, right); + this.name = name; + this.params = params; + this.returnType = returnType; + this.declarations = declarations; + this.statements = statements; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + + @Override + public Identifier getIdentifier() { + return this.name; + } +} diff --git a/src/main/java/chocopy/common/astnodes/GlobalDecl.java b/src/main/java/chocopy/common/astnodes/GlobalDecl.java new file mode 100644 index 0000000..3bac547 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/GlobalDecl.java @@ -0,0 +1,34 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +/** + * Declaration of global variable. + */ +public class GlobalDecl extends Declaration { + + /** + * The declared variable. + */ + public final Identifier variable; + + /** + * The AST for the declaration + * global VARIABLE + * spanning source locations [LEFT..RIGHT]. + */ + public GlobalDecl(Location left, Location right, Identifier variable) { + super(left, right); + this.variable = variable; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + + @Override + public Identifier getIdentifier() { + return this.variable; + } +} diff --git a/src/main/java/chocopy/common/astnodes/Identifier.java b/src/main/java/chocopy/common/astnodes/Identifier.java new file mode 100644 index 0000000..b1aeea5 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/Identifier.java @@ -0,0 +1,29 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +/** + * A simple identifier. + */ +public class Identifier extends Expr { + + /** + * Text of the identifier. + */ + public final String name; + + /** + * An AST for the variable, method, or parameter named NAME, spanning + * source locations [LEFT..RIGHT]. + */ + public Identifier(Location left, Location right, String name) { + super(left, right); + this.name = name; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/IfExpr.java b/src/main/java/chocopy/common/astnodes/IfExpr.java new file mode 100644 index 0000000..67d5b13 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/IfExpr.java @@ -0,0 +1,40 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +/** + * Conditional expressions. + */ +public class IfExpr extends Expr { + /** + * Boolean condition. + */ + public final Expr condition; + /** + * True branch. + */ + public final Expr thenExpr; + /** + * False branch. + */ + public final Expr elseExpr; + + /** + * The AST for + * THENEXPR if CONDITION else ELSEEXPR + * spanning source locations [LEFT..RIGHT]. + */ + public IfExpr(Location left, Location right, + Expr condition, Expr thenExpr, Expr elseExpr) { + super(left, right); + this.condition = condition; + this.thenExpr = thenExpr; + this.elseExpr = elseExpr; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/IfStmt.java b/src/main/java/chocopy/common/astnodes/IfStmt.java new file mode 100644 index 0000000..16da823 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/IfStmt.java @@ -0,0 +1,45 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +import java.util.List; + +/** + * Conditional statement. + */ +public class IfStmt extends Stmt { + /** + * Test condition. + */ + public final Expr condition; + /** + * "True" branch. + */ + public final List thenBody; + /** + * "False" branch. + */ + public final List elseBody; + + /** + * The AST for + * if CONDITION: + * THENBODY + * else: + * ELSEBODY + * spanning source locations [LEFT..RIGHT]. + */ + public IfStmt(Location left, Location right, + Expr condition, List thenBody, List elseBody) { + super(left, right); + this.condition = condition; + this.thenBody = thenBody; + this.elseBody = elseBody; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/IndexExpr.java b/src/main/java/chocopy/common/astnodes/IndexExpr.java new file mode 100644 index 0000000..8038c3f --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/IndexExpr.java @@ -0,0 +1,35 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +/** + * List-indexing expression. + */ +public class IndexExpr extends Expr { + + /** + * Indexed list. + */ + public final Expr list; + /** + * Expression for index value. + */ + public final Expr index; + + /** + * The AST for + * LIST[INDEX]. + * spanning source locations [LEFT..RIGHT]. + */ + public IndexExpr(Location left, Location right, Expr list, Expr index) { + super(left, right); + this.list = list; + this.index = index; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/IntegerLiteral.java b/src/main/java/chocopy/common/astnodes/IntegerLiteral.java new file mode 100644 index 0000000..d383472 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/IntegerLiteral.java @@ -0,0 +1,29 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +/** + * Integer numerals. + */ +public final class IntegerLiteral extends Literal { + + /** + * Value denoted. + */ + public final int value; + + /** + * The AST for the literal VALUE, spanning source + * locations [LEFT..RIGHT]. + */ + public IntegerLiteral(Location left, Location right, int value) { + super(left, right); + this.value = value; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/ListExpr.java b/src/main/java/chocopy/common/astnodes/ListExpr.java new file mode 100644 index 0000000..226d42b --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/ListExpr.java @@ -0,0 +1,32 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +import java.util.List; + +/** + * List displays. + */ +public final class ListExpr extends Expr { + + /** + * List of element expressions. + */ + public final List elements; + + /** + * The AST for + * [ ELEMENTS ]. + * spanning source locations [LEFT..RIGHT]. + */ + public ListExpr(Location left, Location right, List elements) { + super(left, right); + this.elements = elements; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/ListType.java b/src/main/java/chocopy/common/astnodes/ListType.java new file mode 100644 index 0000000..0cbf0a0 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/ListType.java @@ -0,0 +1,30 @@ +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 { + + /** + * The element of list element. + */ + public final TypeAnnotation elementType; + + /** + * The AST for the type annotation + * [ ELEMENTTYPE ]. + * spanning source locations [LEFT..RIGHT]. + */ + public ListType(Location left, Location right, TypeAnnotation elementType) { + super(left, right); + this.elementType = elementType; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/Literal.java b/src/main/java/chocopy/common/astnodes/Literal.java new file mode 100644 index 0000000..ac2c026 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/Literal.java @@ -0,0 +1,18 @@ +package chocopy.common.astnodes; + +import java_cup.runtime.ComplexSymbolFactory.Location; + +/** + * Base of all the literal nodes. + *

+ * There is nothing in this class, but it is useful to isolate + * expressions that are constant literals. + */ +public abstract class Literal extends Expr { + /** + * A literal spanning source locations [LEFT..RIGHT]. + */ + public Literal(Location left, Location right) { + super(left, right); + } +} diff --git a/src/main/java/chocopy/common/astnodes/MemberExpr.java b/src/main/java/chocopy/common/astnodes/MemberExpr.java new file mode 100644 index 0000000..a59abe7 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/MemberExpr.java @@ -0,0 +1,36 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +/** + * Attribute accessor. + */ +public class MemberExpr extends Expr { + + /** + * Object selected from. + */ + public final Expr object; + /** + * Name of attribute (instance variable or method). + */ + public final Identifier member; + + /** + * The AST for + * OBJECT.MEMBER. + * spanning source locations [LEFT..RIGHT]. + */ + public MemberExpr(Location left, Location right, + Expr object, Identifier member) { + super(left, right); + this.object = object; + this.member = member; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/MethodCallExpr.java b/src/main/java/chocopy/common/astnodes/MethodCallExpr.java new file mode 100644 index 0000000..7674a13 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/MethodCallExpr.java @@ -0,0 +1,38 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +import java.util.List; + +/** + * Method calls. + */ +public class MethodCallExpr extends Expr { + + /** + * Expression for the bound method to be called. + */ + public final MemberExpr method; + /** + * Actual parameters. + */ + public final List args; + + /** + * The AST for + * METHOD(ARGS). + * spanning source locations [LEFT..RIGHT]. + */ + public MethodCallExpr(Location left, Location right, + MemberExpr method, List args) { + super(left, right); + this.method = method; + this.args = args; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/Node.java b/src/main/java/chocopy/common/astnodes/Node.java new file mode 100644 index 0000000..d84345b --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/Node.java @@ -0,0 +1,204 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; +import java_cup.runtime.ComplexSymbolFactory.Location; + +import java.io.IOException; + +/** + * Root of the AST class hierarchy. Every node has a left and right + * location, indicating the start and end of the represented construct + * in the source text. + *

+ * Every node can be marked with an error message, which serves two purposes: + * 1. It indicates that an error message has been issued for this + * Node, allowing tne program to reduce cascades of error + * messages. + * 2. It aids in debugging by making it convenient to see which + * Nodes have caused an error. + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.EXISTING_PROPERTY, + property = "kind") +/* List of all concrete subclasses of Node. */ +@JsonSubTypes({ + @JsonSubTypes.Type(AssignStmt.class), + @JsonSubTypes.Type(BinaryExpr.class), + @JsonSubTypes.Type(BooleanLiteral.class), + @JsonSubTypes.Type(CallExpr.class), + @JsonSubTypes.Type(ClassDef.class), + @JsonSubTypes.Type(ClassType.class), + @JsonSubTypes.Type(CompilerError.class), + @JsonSubTypes.Type(Errors.class), + @JsonSubTypes.Type(ExprStmt.class), + @JsonSubTypes.Type(ForStmt.class), + @JsonSubTypes.Type(FuncDef.class), + @JsonSubTypes.Type(GlobalDecl.class), + @JsonSubTypes.Type(Identifier.class), + @JsonSubTypes.Type(IfExpr.class), + @JsonSubTypes.Type(IfStmt.class), + @JsonSubTypes.Type(IndexExpr.class), + @JsonSubTypes.Type(IntegerLiteral.class), + @JsonSubTypes.Type(ListExpr.class), + @JsonSubTypes.Type(ListType.class), + @JsonSubTypes.Type(MemberExpr.class), + @JsonSubTypes.Type(MethodCallExpr.class), + @JsonSubTypes.Type(NoneLiteral.class), + @JsonSubTypes.Type(NonLocalDecl.class), + @JsonSubTypes.Type(Program.class), + @JsonSubTypes.Type(ReturnStmt.class), + @JsonSubTypes.Type(StringLiteral.class), + @JsonSubTypes.Type(TypedVar.class), + @JsonSubTypes.Type(UnaryExpr.class), + @JsonSubTypes.Type(VarDef.class), + @JsonSubTypes.Type(WhileStmt.class), +}) +public abstract class Node { + + /** + * Node-type indicator for JSON form. + */ + public final String kind; + + /** + * Source position information: 0: line number of start, 1: column number + * of start, 2: line number of end, 3: column number of end. + */ + private final int[] location = new int[4]; + + /** + * First error message "blamed" on this Node. When non-null, indicates + * that an error has been found in this 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) { + location[0] = left.getLine(); + location[1] = left.getColumn(); + } + if (right != null) { + location[2] = right.getLine(); + location[3] = right.getColumn(); + } + this.kind = getClass().getSimpleName(); + this.errorMsg = null; + } + + /** + * Return my source location as + * { , , , }. + * Result should not be modified, and contents will change after + * setLocation(). + */ + public int[] getLocation() { + return location; + } + + /** + * Copy LOCATION as getLocation(). + */ + public void setLocation(final int[] location) { + System.arraycopy(location, 0, this.location, 0, 4); + } + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String msg) { + this.errorMsg = msg; + } + + /** + * Return true iff I have been marked with an error message. + */ + @JsonIgnore + public boolean hasError() { + return this.errorMsg != null; + } + + /** + * Invoke ANALYZER on me as a node of static type T. See the comment + * on NodeAnalyzer. Returns modified Node. + */ + public abstract T dispatch(NodeAnalyzer analyzer); + + /** + * Print out the AST in JSON format. + */ + @Override + public String toString() { + try { + return toJSON(); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + /** + * 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(); + + static { + mapper.enable(SerializationFeature.INDENT_OUTPUT); + 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); + } + + /** + * Returns the result of converting JSON, a JSon-serialization of + * a Node value, into the value it serializes. + */ + public static Node fromJSON(String json) + throws IOException { + return fromJSON(json, Node.class); + } + + /** + * Returns the result of converting TREE to the value of type T + * that it represents, where CLAS reflects T. + */ + public static T fromJSON(JsonNode tree, Class clas) + throws IOException { + return mapper.treeToValue(tree, clas); + } + + /** + * Returns the translation of serialized value SRC into the + * corresponding JSON tree. + */ + public static JsonNode readTree(String src) throws IOException { + return mapper.readTree(src); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/NonLocalDecl.java b/src/main/java/chocopy/common/astnodes/NonLocalDecl.java new file mode 100644 index 0000000..d03508e --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/NonLocalDecl.java @@ -0,0 +1,34 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +/** + * Nonlocal declaration. + */ +public class NonLocalDecl extends Declaration { + + /** + * Name of identifier being declared. + */ + public final Identifier variable; + + /** + * The AST for + * nonlocal VARIABLE + * spanning source locations [LEFT..RIGHT]. + */ + public NonLocalDecl(Location left, Location right, Identifier variable) { + super(left, right); + this.variable = variable; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + + @Override + public Identifier getIdentifier() { + return this.variable; + } +} diff --git a/src/main/java/chocopy/common/astnodes/NoneLiteral.java b/src/main/java/chocopy/common/astnodes/NoneLiteral.java new file mode 100644 index 0000000..d38211c --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/NoneLiteral.java @@ -0,0 +1,21 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +/** + * The expression 'None'. + */ +public final class NoneLiteral extends Literal { + + /** + * The AST for None, spanning source locations [LEFT..RIGHT]. + */ + public NoneLiteral(Location left, Location right) { + super(left, right); + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } +} diff --git a/src/main/java/chocopy/common/astnodes/Program.java b/src/main/java/chocopy/common/astnodes/Program.java new file mode 100644 index 0000000..29dd28e --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/Program.java @@ -0,0 +1,70 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import com.fasterxml.jackson.annotation.JsonIgnore; +import java_cup.runtime.ComplexSymbolFactory.Location; + +import java.util.ArrayList; +import java.util.List; + +/** + * An entire ChocoPy program. + */ +public class Program extends Node { + + /** + * Initial variable, class, and function declarations. + */ + public final List declarations; + /** + * Trailing statements. + */ + public final List statements; + /** + * Accumulated errors. + */ + public final Errors errors; + + /** + * The AST for the program + * DECLARATIONS + * STATEMENTS + * spanning source locations [LEFT..RIGHT]. + *

+ * ERRORS is the container for all error messages applying to the + * program. + */ + public Program(Location left, Location right, + List declarations, List statements, + Errors errors) { + super(left, right); + this.declarations = declarations; + this.statements = statements; + if (errors == null) { + this.errors = new Errors(new ArrayList<>()); + } else { + this.errors = errors; + } + } + + public T dispatch(NodeAnalyzer analyzer) { + 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() { + return errors.errors; + } +} diff --git a/src/main/java/chocopy/common/astnodes/ReturnStmt.java b/src/main/java/chocopy/common/astnodes/ReturnStmt.java new file mode 100644 index 0000000..f4751c7 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/ReturnStmt.java @@ -0,0 +1,30 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +/** + * Return from function. + */ +public class ReturnStmt extends Stmt { + + /** + * Returned value. + */ + public final Expr value; + + /** + * The AST for + * return VALUE + * spanning source locations [LEFT..RIGHT]. + */ + public ReturnStmt(Location left, Location right, Expr value) { + super(left, right); + this.value = value; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/Stmt.java b/src/main/java/chocopy/common/astnodes/Stmt.java new file mode 100644 index 0000000..a2642fd --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/Stmt.java @@ -0,0 +1,21 @@ +package chocopy.common.astnodes; + +import java_cup.runtime.ComplexSymbolFactory.Location; + +/** + * Base of all AST nodes representing statements. + *

+ * There is nothing in this class, but there will be some AST + * node types that have fields that are *any statement* or a + * list of statements. For those cases, having a field of this type will + * encompass all types of statements such as expression statements, + * if statements, while statements, etc. + */ +public abstract class Stmt extends Node { + /** + * A statement spanning source locations [LEFT..RIGHT]. + */ + public Stmt(Location left, Location right) { + super(left, right); + } +} diff --git a/src/main/java/chocopy/common/astnodes/StringLiteral.java b/src/main/java/chocopy/common/astnodes/StringLiteral.java new file mode 100644 index 0000000..5adb024 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/StringLiteral.java @@ -0,0 +1,29 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +/** + * String constants. + */ +public final class StringLiteral extends Literal { + + /** + * Contents of the literal, not including quotation marks. + */ + public final String value; + + /** + * The AST for a string literal containing VALUE, spanning source + * locations [LEFT..RIGHT]. + */ + public StringLiteral(Location left, Location right, String value) { + super(left, right); + this.value = value; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/TypeAnnotation.java b/src/main/java/chocopy/common/astnodes/TypeAnnotation.java new file mode 100644 index 0000000..1002a86 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/TypeAnnotation.java @@ -0,0 +1,16 @@ +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]. + */ + public TypeAnnotation(Location left, Location right) { + super(left, right); + } +} diff --git a/src/main/java/chocopy/common/astnodes/TypedVar.java b/src/main/java/chocopy/common/astnodes/TypedVar.java new file mode 100644 index 0000000..7593775 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/TypedVar.java @@ -0,0 +1,36 @@ +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 { + + /** + * The typed identifier. + */ + public final Identifier identifier; + /** + * The declared type. + */ + public final TypeAnnotation type; + + /** + * The AST for + * IDENTIFIER : TYPE. + * spanning source locations [LEFT..RIGHT]. + */ + public TypedVar(Location left, Location right, + Identifier identifier, TypeAnnotation type) { + super(left, right); + this.identifier = identifier; + this.type = type; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/UnaryExpr.java b/src/main/java/chocopy/common/astnodes/UnaryExpr.java new file mode 100644 index 0000000..10ba57f --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/UnaryExpr.java @@ -0,0 +1,36 @@ +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 { + + /** + * The text representation of the operator. + */ + public final String operator; + /** + * The operand to which it is applied. + */ + public final Expr operand; + + /** + * The AST for + * OPERATOR OPERAND + * spanning source locations [LEFT..RIGHT]. + */ + public UnaryExpr(Location left, Location right, + String operator, Expr operand) { + super(left, right); + this.operator = operator; + this.operand = operand; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + +} diff --git a/src/main/java/chocopy/common/astnodes/VarDef.java b/src/main/java/chocopy/common/astnodes/VarDef.java new file mode 100644 index 0000000..047b63b --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/VarDef.java @@ -0,0 +1,42 @@ +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. + */ + public final TypedVar var; + /** + * The initial value assigned. + */ + public final Literal value; + + /** + * The AST for + * VAR = VALUE + * where VAR has a type annotation, and spanning source + * locations [LEFT..RIGHT]. + */ + public VarDef(Location left, Location right, TypedVar var, Literal value) { + super(left, right); + this.var = var; + this.value = value; + } + + public T dispatch(NodeAnalyzer analyzer) { + return analyzer.analyze(this); + } + + /** + * The identifier defined by this declaration. + */ + @Override + public Identifier getIdentifier() { + return this.var.identifier; + } +} diff --git a/src/main/java/chocopy/common/astnodes/WhileStmt.java b/src/main/java/chocopy/common/astnodes/WhileStmt.java new file mode 100644 index 0000000..2936771 --- /dev/null +++ b/src/main/java/chocopy/common/astnodes/WhileStmt.java @@ -0,0 +1,39 @@ +package chocopy.common.astnodes; + +import chocopy.common.analysis.NodeAnalyzer; +import java_cup.runtime.ComplexSymbolFactory.Location; + +import java.util.List; + +/** + * Indefinite repetition construct. + */ +public class WhileStmt extends Stmt { + /** + * Test for whether to continue. + */ + public final Expr condition; + /** + * Loop body. + */ + public final List body; + + /** + * The AST for + * while CONDITION: + * BODY + * spanning source locations [LEFT..RIGHT]. + */ + public WhileStmt(Location left, Location right, + Expr condition, List body) { + super(left, right); + this.condition = condition; + 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/jflex/chocopy/pa1/ChocoPy.jflex b/src/main/jflex/chocopy/pa1/ChocoPy.jflex new file mode 100644 index 0000000..9aafe7f --- /dev/null +++ b/src/main/jflex/chocopy/pa1/ChocoPy.jflex @@ -0,0 +1,82 @@ +package chocopy.pa1; +import java_cup.runtime.*; + +%% + +/*** Do not change the flags below unless you know what you are doing. ***/ + +%unicode +%line +%column + +%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(); + + /** 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); + } + +%} + +/* Macros (regexes used in rules below) */ + +WhiteSpace = [ \t] +LineBreak = \r|\n|\r\n + +IntegerLiteral = 0 | [1-9][0-9]* + +%% + + + { + + /* Delimiters. */ + {LineBreak} { return symbol(ChocoPyTokens.NEWLINE); } + + /* Literals. */ + {IntegerLiteral} { return symbol(ChocoPyTokens.NUMBER, + Integer.parseInt(yytext())); } + + /* Operators. */ + "+" { return symbol(ChocoPyTokens.PLUS, yytext()); } + + /* Whitespace. */ + {WhiteSpace} { /* ignore */ } +} + +<> { 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..b85905e --- /dev/null +++ b/src/test/data/pa1/student_contributed/bad.py @@ -0,0 +1 @@ +1 2 3 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..8138b36 --- /dev/null +++ b/src/test/data/pa1/student_contributed/good.py @@ -0,0 +1 @@ +1 + 2 + 3