commit
9f1681bb23
@ -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
|
||||
*~
|
@ -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.
|
@ -0,0 +1,52 @@
|
||||
# NYU Compiler Construction CSCI-GA.2130/Spring 2021: Programming Assignment 3
|
||||
|
||||
This assignment is adapted from https://github.com/cs164berkeley/pa3-chocopy-code-generation with the authors' permission.
|
||||
|
||||
See the PA3 document on Piazza for a detailed specification.
|
||||
|
||||
## Quickstart
|
||||
|
||||
Run the following commands to compile your code generator and run the tests:
|
||||
```
|
||||
mvn clean package
|
||||
java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy \
|
||||
--pass=..s --test --run --dir src/test/data/pa3/sample/
|
||||
```
|
||||
|
||||
The dots in `--pass` make the compiler skip parsing and semantic analysis and go straight to code generation.
|
||||
`--pass=..s` uses your (`s` for `student`) generator to generate code from an annotated AST (the `.ast.typed` files under `src/test/data/pa3/sample/`).
|
||||
With the starter code, only one test should pass.
|
||||
Your main objective is to build a code generator that passes all the provided tests.
|
||||
|
||||
`--pass=..r` uses the reference (`r` for `reference`) generator, 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) generator with:
|
||||
```
|
||||
java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy \
|
||||
--pass=..s src/test/data/pa3/sample/op_add.py.ast.typed
|
||||
```
|
||||
|
||||
You can also run all passes on the original `.py` file:
|
||||
```
|
||||
java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy \
|
||||
--pass=rrr src/test/data/pa3/sample/op_add.py
|
||||
```
|
||||
|
||||
Once you merge your semantic analysis code from assignment 2, you should be able to use `--pass=sss`.
|
||||
|
||||
## Generating vs Running
|
||||
|
||||
The above should be familiar from previous assignments.
|
||||
A new aspect of PA3 is the distinction between generating and running the code.
|
||||
|
||||
The following outputs the generated RISC-V assembly (with the usual option to save to a file with `--out`):
|
||||
```
|
||||
java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy \
|
||||
--pass=rrr src/test/data/pa3/sample/op_add.py
|
||||
```
|
||||
|
||||
The following (note the `--run` option) generates the assembly and then _runs it on the bundled RISC-V emulator_:
|
||||
```
|
||||
java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy \
|
||||
--pass=rrr --run src/test/data/pa3/sample/op_add.py
|
||||
```
|
Binary file not shown.
@ -0,0 +1,330 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>chocopy</groupId>
|
||||
<artifactId>chocopy</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>2.2-SNAPSHOT</version>
|
||||
<name>chocopy</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<!-- Set this property to true on the command-line for very verbose output -->
|
||||
<properties>
|
||||
<chocopy.debug>false</chocopy.debug>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<!-- Specify JFlex and CUP plugins here; execute in profiles -->
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>de.jflex</groupId>
|
||||
<artifactId>jflex-maven-plugin</artifactId>
|
||||
<version>1.6.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.vbmacher</groupId>
|
||||
<artifactId>cup-maven-plugin</artifactId>
|
||||
<version>11b-20160615</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.7.1</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<finalName>assignment</finalName>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase> <!-- bind to the packaging phase -->
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<parameters>true</parameters>
|
||||
<debug>true</debug>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/asm</directory>
|
||||
<includes>
|
||||
<include>**/*.s</include>
|
||||
<include>**/*.os</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/reference/*.s</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>reference</id>
|
||||
<activation>
|
||||
<!-- This profile is activated whenever we have the reference sources available -->
|
||||
<file>
|
||||
<exists>src/main/java/chocopy/reference/</exists>
|
||||
</file>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Do not include student skeletons in the reference JAR -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/pa1/*</exclude>
|
||||
<exclude>**/pa2/*</exclude>
|
||||
<exclude>**/pa3/*</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Name the generated JAR differently so that it is different from the student version -->
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<finalName>chocopy-ref</finalName>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Run JFlex to generate reference lexer -->
|
||||
<plugin>
|
||||
<groupId>de.jflex</groupId>
|
||||
<artifactId>jflex-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>jflex-reference</id>
|
||||
<goals>
|
||||
<goal>generate</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<lexDefinitions>
|
||||
<lexDefinition>src/main/jflex/chocopy/reference/ChocoPy.jflex</lexDefinition>
|
||||
</lexDefinitions>
|
||||
<dump>${chocopy.debug}</dump>
|
||||
<verbose>true</verbose>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- Run CUP to generate reference parser -->
|
||||
<plugin>
|
||||
<groupId>com.github.vbmacher</groupId>
|
||||
<artifactId>cup-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>cup-reference</id>
|
||||
<goals>
|
||||
<goal>generate</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<cupDefinition>src/main/cup/chocopy/reference/ChocoPy.cup</cupDefinition>
|
||||
<packageName>chocopy.reference</packageName>
|
||||
<className>ChocoPyParser</className>
|
||||
<symbolsName>ChocoPyTokens</symbolsName>
|
||||
<dumpTables>${chocopy.debug}</dumpTables>
|
||||
<dumpStates>${chocopy.debug}</dumpStates>
|
||||
<dumpGrammar>${chocopy.debug}</dumpGrammar>
|
||||
<locations>true</locations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- No debug -->
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<debug>true</debug>
|
||||
<debuglevel>none</debuglevel>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Copy dependencies to target/ -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-dependencies</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>pa1</id>
|
||||
<activation>
|
||||
<!-- This profile is activated whenever we are in a PA1 distribution -->
|
||||
<file>
|
||||
<exists>src/main/java/chocopy/pa1</exists>
|
||||
</file>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Run JFlex on the student version -->
|
||||
<plugin>
|
||||
<groupId>de.jflex</groupId>
|
||||
<artifactId>jflex-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>jflex-pa1</id>
|
||||
<goals>
|
||||
<goal>generate</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<lexDefinitions>
|
||||
<lexDefinition>src/main/jflex/chocopy/pa1/ChocoPy.jflex</lexDefinition>
|
||||
</lexDefinitions>
|
||||
<dump>${chocopy.debug}</dump>
|
||||
<verbose>true</verbose>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- Run CUP on the student version -->
|
||||
<plugin>
|
||||
<groupId>com.github.vbmacher</groupId>
|
||||
<artifactId>cup-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>cup-pa1</id>
|
||||
<goals>
|
||||
<goal>generate</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<cupDefinition>src/main/cup/chocopy/pa1/ChocoPy.cup</cupDefinition>
|
||||
<packageName>chocopy.pa1</packageName>
|
||||
<className>ChocoPyParser</className>
|
||||
<symbolsName>ChocoPyTokens</symbolsName>
|
||||
<dumpTables>${chocopy.debug}</dumpTables>
|
||||
<dumpStates>${chocopy.debug}</dumpStates>
|
||||
<dumpGrammar>${chocopy.debug}</dumpGrammar>
|
||||
<locations>true</locations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>pa2</id>
|
||||
<activation>
|
||||
<!-- This profile is activated whenever we are in a PA2 distribution -->
|
||||
<file>
|
||||
<exists>src/main/java/chocopy/pa2</exists>
|
||||
</file>
|
||||
</activation>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>pa3</id>
|
||||
<activation>
|
||||
<!-- This profile is activated whenever we are in a PA3 distribution -->
|
||||
<file>
|
||||
<exists>src/main/java/chocopy/pa3</exists>
|
||||
</file>
|
||||
</activation>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>venus164-repo</id>
|
||||
<name>Repository for Venus164</name>
|
||||
<url>https://raw.githubusercontent.com/chocopy/venus/maven-repository/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.argparse4j</groupId>
|
||||
<artifactId>argparse4j</artifactId>
|
||||
<version>0.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.9.10</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.module</groupId>
|
||||
<artifactId>jackson-module-parameter-names</artifactId>
|
||||
<version>2.9.10</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.vbmacher</groupId>
|
||||
<artifactId>java-cup-runtime</artifactId>
|
||||
<version>11b-20160615</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/de.jflex/jflex -->
|
||||
<dependency>
|
||||
<groupId>de.jflex</groupId>
|
||||
<artifactId>jflex</artifactId>
|
||||
<version>1.6.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
<version>1.2.71</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.berkeley.eecs.venus164</groupId>
|
||||
<artifactId>venus164</artifactId>
|
||||
<version>0.2.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.proguard</groupId>
|
||||
<artifactId>proguard-base</artifactId>
|
||||
<version>6.0.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,12 @@
|
||||
# Runtime support function abort (does not return).
|
||||
mv t0, a0 # Save exit code in temp
|
||||
li a0, @print_string # Code for print_string ecall
|
||||
ecall # Print error message in a1
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for print_char ecall
|
||||
ecall # Print newline
|
||||
mv a1, t0 # Move exit code to a1
|
||||
li a0, @exit2 # Code for exit2 ecall
|
||||
ecall # Exit with code
|
||||
abort_17: # Infinite loop
|
||||
j abort_17 # Prevent fallthrough
|
@ -0,0 +1,4 @@
|
||||
# Runtime support function alloc.
|
||||
# Prototype address is in a0.
|
||||
lw a1, 4(a0) # Get size of object in words
|
||||
j alloc2 # Allocate object with exact size
|
@ -0,0 +1,27 @@
|
||||
# Runtime support function alloc2 (realloc).
|
||||
# Prototype address is in a0.
|
||||
# Number of words to allocate is in a1.
|
||||
li a2, 4 # Word size in bytes
|
||||
mul a2, a1, a2 # Calculate number of bytes to allocate
|
||||
add a2, gp, a2 # Estimate where GP will move
|
||||
bgeu a2, s11, alloc2_15 # Go to OOM handler if too large
|
||||
lw t0, @.__obj_size__(a0) # Get size of object in words
|
||||
mv t2, a0 # Initialize src ptr
|
||||
mv t3, gp # Initialize dest ptr
|
||||
alloc2_16: # Copy-loop header
|
||||
lw t1, 0(t2) # Load next word from src
|
||||
sw t1, 0(t3) # Store next word to dest
|
||||
addi t2, t2, 4 # Increment src
|
||||
addi t3, t3, 4 # Increment dest
|
||||
addi t0, t0, -1 # Decrement counter
|
||||
bne t0, zero, alloc2_16 # Loop if more words left to copy
|
||||
mv a0, gp # Save new object's address to return
|
||||
sw a1, @.__obj_size__(a0) # Set size of new object in words
|
||||
# (same as requested size)
|
||||
mv gp, a2 # Set next free slot in the heap
|
||||
jr ra # Return to caller
|
||||
alloc2_15: # OOM handler
|
||||
li a0, @error_oom # Exit code for: Out of memory
|
||||
la a1, STRING["Out of memory"] # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
@ -0,0 +1,5 @@
|
||||
# Runtime support function heap.init.
|
||||
mv a1, a0 # Move requested size to A1
|
||||
li a0, @sbrk # Code for ecall: sbrk
|
||||
ecall # Request A1 bytes
|
||||
jr ra # Return to caller
|
@ -0,0 +1,40 @@
|
||||
# Function input
|
||||
addi sp, sp, -16 # Reserve stack
|
||||
sw ra, 12(sp) # Save registers
|
||||
sw fp, 8(sp)
|
||||
sw s1, 4(sp)
|
||||
addi fp, sp, 16 # Set fp
|
||||
|
||||
li a0, @fill_line_buffer # Fill the internal line buffer.
|
||||
ecall
|
||||
bgez a0, input_nonempty # More input found
|
||||
la a0, $str$prototype # EOF: Return empty string.
|
||||
j input_done
|
||||
|
||||
input_nonempty:
|
||||
mv s1, a0
|
||||
addi t0, s1, 5 # Compute bytes for string (+NL+NUL),
|
||||
addi t0, t0, @.__str__ # Including header.
|
||||
srli a1, t0, 2 # Convert to words.
|
||||
la a0, $str$prototype # Load address of string prototype.
|
||||
jal ra, alloc2 # Allocate string.
|
||||
sw s1, @.__len__(a0) # Store string length.
|
||||
mv a2, s1 # Pass length.
|
||||
mv s1, a0 # Save string object address.
|
||||
addi a1, a0, @.__str__ # Pass address of string data.
|
||||
li a0, @read_string # ecall to read from internal buffer.
|
||||
ecall
|
||||
addi a0, a0, 1 # Actual length (including NL).
|
||||
sw a0, @.__len__(s1) # Store actual length.
|
||||
add t0, a0, s1
|
||||
li t1, 10 # Store newline and null byte
|
||||
sb t1, @.__str__-1(t0)
|
||||
sb zero, @.__str__(t0) # Store null byte at end.
|
||||
mv a0, s1 # Return string object.
|
||||
|
||||
input_done:
|
||||
lw s1, -12(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 16
|
||||
jr ra
|
@ -0,0 +1,20 @@
|
||||
# Function len
|
||||
# We do not save/restore fp/ra for this function
|
||||
# because we know that it does not use the stack or does not
|
||||
# call other functions.
|
||||
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, len_12 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, len_13 # Go to len(str)
|
||||
li t1, -1 # Load type tag for list objects
|
||||
beq t0, t1, len_13 # Go to len(list)
|
||||
len_12: # Invalid argument
|
||||
li a0, @error_arg # Exit code for: Invalid argument
|
||||
la a1, STRING["Invalid argument"] # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
len_13: # Get length of string
|
||||
lw a0, @.__len__(a0) # Load attribute: __len__
|
||||
jr ra # Return to caller
|
@ -0,0 +1,3 @@
|
||||
# Init method for type object.
|
||||
mv a0, zero # `None` constant
|
||||
jr ra # Return
|
@ -0,0 +1,52 @@
|
||||
# Function print
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, print_6 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 1 # Load type tag of `int`
|
||||
beq t0, t1, print_7 # Go to print(int)
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, print_8 # Go to print(str)
|
||||
li t1, 2 # Load type tag of `bool`
|
||||
beq t0, t1, print_9 # Go to print(bool)
|
||||
print_6: # Invalid argument
|
||||
li a0, 1 # Exit code for: Invalid argument
|
||||
la a1, STRING["Invalid argument"] # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
# Printing bools
|
||||
print_9: # Print bool object in A0
|
||||
lw a0, @.__bool__(a0) # Load attribute __bool__
|
||||
beq a0, zero, print_10 # Go to: print(False)
|
||||
la a0, STRING["True"] # String representation: True
|
||||
j print_8 # Go to: print(str)
|
||||
print_10: # Print False object in A0
|
||||
la a0, STRING["False"] # String representation: False
|
||||
j print_8 # Go to: print(str)
|
||||
|
||||
# Printing strs.
|
||||
print_8: # Print str object in A0
|
||||
addi a1, a0, @.__str__ # Load address of attribute __str__
|
||||
j print_11 # Print the null-terminated string is now in A1
|
||||
mv a0, zero # Load None
|
||||
j print_5 # Go to return
|
||||
print_11: # Print null-terminated string in A1
|
||||
li a0, @print_string # Code for ecall: print_string
|
||||
ecall # Print string
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
j print_5 # Go to return
|
||||
|
||||
# Printing ints.
|
||||
print_7: # Print int object in A0
|
||||
lw a1, @.__int__(a0) # Load attribute __int__
|
||||
li a0, @print_int # Code for ecall: print_int
|
||||
ecall # Print integer
|
||||
li a1, 10 # Load newline character
|
||||
li a0, 11 # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
|
||||
print_5: # End of function
|
||||
mv a0, zero # Load None
|
||||
jr ra # Return to caller
|
@ -0,0 +1,54 @@
|
||||
package chocopy.common;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
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.
|
||||
*
|
||||
* <p>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, Charset.forName("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();
|
||||
}
|
||||
}
|
@ -0,0 +1,174 @@
|
||||
package chocopy.common.analysis;
|
||||
|
||||
import chocopy.common.astnodes.*;
|
||||
|
||||
/**
|
||||
* An empty implementation of the {@link NodeAnalyzer} that simply returns does nothing and returns
|
||||
* null for every AST node type.
|
||||
*
|
||||
* <p>T is the type of analysis result.
|
||||
*/
|
||||
public class AbstractNodeAnalyzer<T> implements NodeAnalyzer<T> {
|
||||
@Override
|
||||
public T analyze(AssignStmt node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(BinaryExpr node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(BooleanLiteral node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(CallExpr node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(ClassDef node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(ClassType node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(CompilerError node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(Errors node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(ExprStmt node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(ForStmt node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(FuncDef node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(GlobalDecl node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(Identifier node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(IfExpr node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(IfStmt node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(IndexExpr node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(IntegerLiteral node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(ListExpr node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(ListType node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(MemberExpr node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(MethodCallExpr node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(NoneLiteral node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(NonLocalDecl node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(Program node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(ReturnStmt node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(StringLiteral node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(TypedVar node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(UnaryExpr node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(VarDef node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T analyze(WhileStmt node) {
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault(T value) {
|
||||
defaultValue = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T defaultAction(Node node) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/** Default value for non-overridden methods. */
|
||||
private T defaultValue = null;
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
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.
|
||||
*
|
||||
* <p>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<T> 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.
|
||||
*
|
||||
* <p>The class AbstractNodeAnalyzer provides empty default implementations for these methods.
|
||||
*
|
||||
* <p>The type T is the type of result returned by the encapsulated analysis.
|
||||
*/
|
||||
public interface NodeAnalyzer<T> {
|
||||
|
||||
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);
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package chocopy.common.analysis;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A block-structured symbol table a mapping identifiers to information about them of type T in a
|
||||
* given declarative region.
|
||||
*/
|
||||
public class SymbolTable<T> {
|
||||
|
||||
/** Contents of the current (innermost) region. */
|
||||
private final Map<String, T> tab = new HashMap<>();
|
||||
/** Enclosing block. */
|
||||
private final SymbolTable<T> parent;
|
||||
|
||||
/** A table representing a region nested in that represented by PARENT0. */
|
||||
public SymbolTable(SymbolTable<T> parent0) {
|
||||
parent = parent0;
|
||||
}
|
||||
|
||||
/** A top-level symbol table. */
|
||||
public SymbolTable() {
|
||||
this.parent = null;
|
||||
}
|
||||
|
||||
/** Returns the mapping of NAME in the innermost nested region containing this one. */
|
||||
public T get(String name) {
|
||||
if (tab.containsKey(name)) {
|
||||
return tab.get(name);
|
||||
} else if (parent != null) {
|
||||
return parent.get(name);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new mapping of NAME -> VALUE to the current region, possibly shadowing mappings in the
|
||||
* enclosing parent. Returns modified table.
|
||||
*/
|
||||
public SymbolTable<T> put(String name, T value) {
|
||||
tab.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Returns whether NAME has a mapping in this region (ignoring enclosing regions. */
|
||||
public boolean declares(String name) {
|
||||
return tab.containsKey(name);
|
||||
}
|
||||
|
||||
/** Returns all the names declared this region (ignoring enclosing regions). */
|
||||
public Set<String> getDeclaredSymbols() {
|
||||
return tab.keySet();
|
||||
}
|
||||
|
||||
/** Returns the parent, or null if this is the top level. */
|
||||
public SymbolTable<T> getParent() {
|
||||
return this.parent;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package chocopy.common.analysis.types;
|
||||
|
||||
import chocopy.common.astnodes.ClassType;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/** Represents the semantic value of a simple class reference. */
|
||||
public class ClassValueType extends ValueType {
|
||||
|
||||
/** The name of the class. */
|
||||
private final String className;
|
||||
|
||||
/** A class type for the class named CLASSNAME. */
|
||||
@JsonCreator
|
||||
public ClassValueType(@JsonProperty String className) {
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
/** A class type for the class referenced by CLASSTYPEANNOTATION. */
|
||||
public ClassValueType(ClassType classTypeAnnotation) {
|
||||
this.className = classTypeAnnotation.className;
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonProperty
|
||||
public String className() {
|
||||
return className;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
ClassValueType classType = (ClassValueType) o;
|
||||
return Objects.equals(className, classType.className);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(className);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return className;
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package chocopy.common.analysis.types;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Semantic information for a function or method. */
|
||||
public class FuncType extends Type {
|
||||
|
||||
/** Types of parameters. */
|
||||
public final List<ValueType> parameters;
|
||||
/** Function's return type. */
|
||||
public final ValueType returnType;
|
||||
|
||||
/** Create a FuncType returning RETURNTYPE0, initially parameterless. */
|
||||
public FuncType(ValueType returnType0) {
|
||||
this(new ArrayList<>(), returnType0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a FuncType for NAME0 with formal parameter types PARAMETERS0, returning type
|
||||
* RETURNTYPE0.
|
||||
*/
|
||||
@JsonCreator
|
||||
public FuncType(List<ValueType> parameters0, ValueType returnType0) {
|
||||
this.parameters = parameters0;
|
||||
this.returnType = returnType0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFuncType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Return the type of the K-th parameter. */
|
||||
public ValueType getParamType(int k) {
|
||||
return parameters.get(k);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<function>";
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package chocopy.common.analysis.types;
|
||||
|
||||
import chocopy.common.astnodes.ListType;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/** Represents a semantic value of a list type denotation. */
|
||||
public class ListValueType extends ValueType {
|
||||
|
||||
/** This ListValueType represents [ELEMENTTYPE]. */
|
||||
public final ValueType elementType;
|
||||
|
||||
/** Represents [ELEMENTTYPE]. */
|
||||
@JsonCreator
|
||||
public ListValueType(Type elementType) {
|
||||
this.elementType = (ValueType) elementType;
|
||||
}
|
||||
|
||||
/** Represents [<type>], where <type> is that denoted in TYPEANNOTATION. */
|
||||
public ListValueType(ListType typeAnnotation) {
|
||||
elementType = ValueType.annotationToValueType(typeAnnotation.elementType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
ListValueType listType = (ListValueType) o;
|
||||
return Objects.equals(elementType, listType.elementType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(elementType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + elementType.toString() + "]";
|
||||
}
|
||||
|
||||
/** Returns true iff I represent [T]. */
|
||||
@Override
|
||||
public boolean isListType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueType elementType() {
|
||||
return elementType;
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package chocopy.common.analysis.types;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
/**
|
||||
* Representation for the static type of symbols and expressions during type-checking.
|
||||
*
|
||||
* <p>Symbols such as variables and attributes will typically map to a {@link ValueType}.
|
||||
*
|
||||
* <p>Symbols such as classes will typically map to a more complex Type.
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "kind")
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(FuncType.class),
|
||||
@JsonSubTypes.Type(ClassValueType.class),
|
||||
@JsonSubTypes.Type(ListValueType.class)
|
||||
})
|
||||
public abstract class Type {
|
||||
|
||||
/** The type object. */
|
||||
public static final ClassValueType OBJECT_TYPE = new ClassValueType("object");
|
||||
/** The type int. */
|
||||
public static final ClassValueType INT_TYPE = new ClassValueType("int");
|
||||
/** The type str. */
|
||||
public static final ClassValueType STR_TYPE = new ClassValueType("str");
|
||||
/** The type bool. */
|
||||
public static final ClassValueType BOOL_TYPE = new ClassValueType("bool");
|
||||
|
||||
/** The type of None. */
|
||||
public static final ClassValueType NONE_TYPE = new ClassValueType("<None>");
|
||||
/** The type of []. */
|
||||
public static final ClassValueType EMPTY_TYPE = new ClassValueType("<Empty>");
|
||||
|
||||
/** Returns the name of the class, if this is a class type, Otherwise null. */
|
||||
public String className() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Return true iff this is a type that does not include the value None. */
|
||||
@JsonIgnore
|
||||
public boolean isSpecialType() {
|
||||
return equals(INT_TYPE) || equals(BOOL_TYPE) || equals(STR_TYPE);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isListType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isFuncType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Return true iff this type represents a kind of assignable value. */
|
||||
@JsonIgnore
|
||||
public boolean isValueType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** For list types, return the type of the elements; otherwise null. */
|
||||
@JsonIgnore
|
||||
public ValueType elementType() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package chocopy.common.analysis.types;
|
||||
|
||||
import chocopy.common.astnodes.ClassType;
|
||||
import chocopy.common.astnodes.ListType;
|
||||
import chocopy.common.astnodes.TypeAnnotation;
|
||||
|
||||
/**
|
||||
* A ValueType references types that are assigned to variables and expressions.
|
||||
*
|
||||
* <p>In particular, ValueType can be a {@link ClassValueType} (e.g. "int") or a {@link
|
||||
* ListValueType} (e.g. "[int]").
|
||||
*/
|
||||
public abstract class ValueType extends Type {
|
||||
|
||||
/** Returns the type corresponding to ANNOTATION. */
|
||||
public static ValueType annotationToValueType(TypeAnnotation annotation) {
|
||||
if (annotation instanceof ClassType) {
|
||||
return new ClassValueType((ClassType) annotation);
|
||||
} else {
|
||||
assert annotation instanceof ListType;
|
||||
return new ListValueType((ListType) annotation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValueType() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
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<Expr> 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<Expr> targets, Expr value) {
|
||||
super(left, right);
|
||||
this.targets = targets;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public <T> T dispatch(NodeAnalyzer<T> analyzer) {
|
||||
return analyzer.analyze(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package chocopy.common.astnodes;
|
||||
|
||||
import chocopy.common.analysis.NodeAnalyzer;
|
||||
import java_cup.runtime.ComplexSymbolFactory.Location;
|
||||
|
||||
/** <operand> <operator> <operand>. */
|
||||
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> T dispatch(NodeAnalyzer<T> analyzer) {
|
||||
return analyzer.analyze(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
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, boo |