Skip to content

Commit

Permalink
Reaching definition analysis (#17)
Browse files Browse the repository at this point in the history
Co-authored-by: Santo Cariotti <[email protected]>
Co-authored-by: geno <[email protected]>
Co-authored-by: geno <[email protected]>
  • Loading branch information
4 people authored Jul 14, 2024
1 parent 57599a4 commit ce49d20
Show file tree
Hide file tree
Showing 46 changed files with 1,151 additions and 204 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ trees/
.project
.vscode/
src/parser/.antlr/
code.asm
code.asm
optimized.py
130 changes: 124 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,130 @@

Project for the AA 2023/2024 **Complementi di programmazione**'s course of the Master Degree in Computer Science.

# How to start
## How to build

You first need to build the project using the Makefile.

```
make build
```

## Run

You can run the software using the following command

```
java -cp lib/antlr-4.13.1-complete.jar:out Main <file.py>
```

you also can use three flags on the execution:

- `--optimize`: runs the optimizer for the file `<file.py>`. The optimized
version is auto saved at `./optimized.py`.

- `--tree`: shows the AST on video and on JFrame.

- `--exec`: executes the SVM for the Assembly code generated in `code.asm`.

You can use all the three flags togheter if you want to.

## Example

- Optimizer

```shell
make
make run
make runall
```
$ java -cp lib/antlr-4.13.1-complete.jar:out Main test/2a.py --optimize
n=int(input())
x=int(input())
m=1
tmp=2 * x
while n>1:
For archlinux users, add the following env variable to visualize the window: `export _JAVA_AWT_WM_NONREPARENTING=1`
m=m*tmp
n=n-1
print(m+tmp)
Saving optimized file...
Everything is OK!
```

- Tree

```
$ java -cp lib/antlr-4.13.1-complete.jar:out Main test/2a.py --tree
Root
SimpleStmts
SimpleStmt
Assignment
ExprList
Expr
AtomNode: n
Augassign(=)
ExprList
Expr
AtomNode: int
TrailerNode
ArglistNode
Expr
Assignment [40/225]
[...]
SimpleStmt
Expr
AtomNode: print
TrailerNode
ArglistNode
Expr
Expr
AtomNode: m
Expr
AtomNode: tmp
Op(+)
Everything is OK!
```

- Exec

```
$ java -cp lib/antlr-4.13.1-complete.jar:out Main test/3-1.py --exec
Creating VM code...
Executing assemply code...
0: 17 ----- SP = 999, FP = 999, AL = 998, RA = 0, A0 = 0, T1 = 0
1: 17 999 ----- SP = 998, FP = 999, AL = 998, RA = 0, A0 = 0, T1 = 0
2: 17 999 998 ----- SP = 997, FP = 999, AL = 998, RA = 0, A0 = 0, T1 = 0
3: 7 999 998 999 ----- SP = 996, FP = 999, AL = 998, RA = 0, A0 = 0, T1 = 0
4: 9 999 998 999 ----- SP = 996, FP = 996, AL = 998, RA = 0, A0 = 0, T1 = 0
5: 7 999 998 999 ----- SP = 996, FP = 997, AL = 998, RA = 0, A0 = 0, T1 = 0
[...]
216: 18 999 998 999 998 29 2 14 997 996 29 3 140 992 991 ----- SP = 985, FP = 987, AL = 986, RA = 140, A0 = 1, T1 = 1
217: 5 999 998 999 998 29 2 14 997 996 29 3 140 992 ----- SP = 986, FP = 987, AL = 986, RA = 140, A0 = 1, T1 = 1
218: 7 999 998 999 998 29 2 14 997 996 29 3 140 992 ----- SP = 986, FP = 992, AL = 986, RA = 140, A0 = 1, T1 = 1
219: 11 999 998 999 998 29 2 14 997 996 29 3 140 992 ----- SP = 986, FP = 992, AL = 992, RA = 140, A0 = 1, T1 = 1
220: 18 999 998 999 998 29 2 14 997 996 29 3 140 992 ----- SP = 986, FP = 992, AL = 991, RA = 140, A0 = 1, T1 = 1
221: 24 999 998 999 998 29 2 14 997 996 29 3 140 ----- SP = 987, FP = 992, AL = 991, RA = 140, A0 = 1, T1 = 1
222: 19 999 998 999 998 29 2 14 997 996 29 3 140 ----- SP = 987, FP = 992, AL = 991, RA = 140, A0 = 1, T1 = 1
223: 9 999 998 999 998 29 2 14 997 996 29 3 ----- SP = 988, FP = 992, AL = 991, RA = 140, A0 = 1, T1 = 1
224: 18 999 998 999 998 29 2 14 997 996 ----- SP = 990, FP = 992, AL = 991, RA = 140, A0 = 1, T1 = 1
225: 5 999 998 999 998 29 2 14 997 ----- SP = 991, FP = 992, AL = 991, RA = 140, A0 = 1, T1 = 1
226: 7 999 998 999 998 29 2 14 997 ----- SP = 991, FP = 997, AL = 991, RA = 140, A0 = 1, T1 = 1
227: 11 999 998 999 998 29 2 14 997 ----- SP = 991, FP = 997, AL = 997, RA = 140, A0 = 1, T1 = 1
228: 18 999 998 999 998 29 2 14 997 ----- SP = 991, FP = 997, AL = 996, RA = 140, A0 = 1, T1 = 1
229: 24 999 998 999 998 29 2 14 ----- SP = 992, FP = 997, AL = 996, RA = 140, A0 = 1, T1 = 1
230: 19 999 998 999 998 29 2 14 ----- SP = 992, FP = 997, AL = 996, RA = 140, A0 = 1, T1 = 1
231: 9 999 998 999 998 29 2 ----- SP = 993, FP = 997, AL = 996, RA = 14, A0 = 1, T1 = 1
232: 18 999 998 999 998 ----- SP = 995, FP = 997, AL = 996, RA = 14, A0 = 1, T1 = 1
233: 5 999 998 999 ----- SP = 996, FP = 997, AL = 996, RA = 14, A0 = 1, T1 = 1
234: 7 999 998 999 ----- SP = 996, FP = 999, AL = 996, RA = 14, A0 = 1, T1 = 1
235: 11 999 998 999 ----- SP = 996, FP = 999, AL = 999, RA = 14, A0 = 1, T1 = 1
236: 18 999 998 999 ----- SP = 996, FP = 999, AL = 998, RA = 14, A0 = 1, T1 = 1
237: 24 999 998 ----- SP = 997, FP = 999, AL = 998, RA = 14, A0 = 1, T1 = 1
238: 18 999 998 ----- SP = 997, FP = 999, AL = 998, RA = 14, A0 = 1, T1 = 1
239: 18 999 ----- SP = 998, FP = 999, AL = 998, RA = 14, A0 = 1, T1 = 1
240: 25 ----- SP = 999, FP = 999, AL = 998, RA = 14, A0 = 1, T1 = 1
Result: 1
Everything is OK!
```
9 changes: 7 additions & 2 deletions progs/test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
n = int(input())
x = int(input())
m = 1
for i in range(10):
m = m + 1
while n > 1:
tmp = 2 * x
m = m * tmp
n = n - 1
print(m + tmp)
128 changes: 88 additions & 40 deletions src/Main.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

import java.util.ArrayList;
import java.util.Arrays;

import javax.swing.*;
import org.antlr.v4.gui.TreeViewer;
import org.antlr.v4.runtime.*;
Expand All @@ -11,52 +12,77 @@
import java.nio.file.Paths;
import ast.*;
import ast.nodes.*;
import parser.Python3Lexer;
import parser.Python3Parser;
import parser.*;
import semanticanalysis.*;
import svm.*;

public class Main {

private static boolean execute = false;
private static boolean treeFlag = false;
private static boolean optimize = false;

public static void main(String[] args) {
if (args.length != 1) {
if (args.length < 1) {
System.err
.println(
"You must execute this program with a file parameter.\nUsage: java -cp lib/antlr-4.13.1-complete.jar:out Main <file.py>");
return;
}

try {
for (int i = 0; i < args.length; i++) {
if (args[i].equals("--exec")) {
execute = true;
}

if (args[i].equals("--tree")) {
treeFlag = true;
}

if (args[i].equals("--optimize")) {
optimize = true;
}
}

String fileStr = args[0];
System.out.println(fileStr);
System.out.println(Share.readFile(fileStr));
CharStream cs = CharStreams.fromFileName(fileStr);
Python3Lexer lexer = new Python3Lexer(cs);
CommonTokenStream tokens = new CommonTokenStream(lexer);
Python3Parser parser = new Python3Parser(tokens);
Python3Parser.RootContext tree = parser.root();

JFrame frame = new JFrame("Parse Tree");
JPanel panel = new JPanel();
TreeViewer viewer = new TreeViewer(Arrays.asList(parser.getRuleNames()),
tree);
viewer.setScale(1); // Zoom factor
panel.add(viewer);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setVisible(true);
if (tree == null) {
System.err.println("The tree is null.");
return;
}

if (parser.getNumberOfSyntaxErrors() > 0) {
System.err.println("Error on program parsing.");
return;
}
Python3VisitorImpl visitor = new Python3VisitorImpl();
SymbolTable ST = new SymbolTable();

Python3VisitorImpl visitor = new Python3VisitorImpl(tokens, optimize);
Node ast = visitor.visit(tree);
SymbolTable ST = new SymbolTable();

if (optimize) {
// first visit to optimize
cs = CharStreams.fromString(visitor.getRewriter());
System.out.println(cs);
lexer = new Python3Lexer(cs);
tokens = new CommonTokenStream(lexer);
parser = new Python3Parser(tokens);
tree = parser.root();
ST = new SymbolTable();

ast = visitor.visit(tree);

System.out.println("Saving optimized file...");
String astToPrint = ast.toPrint("");
Share.saveFile("optimized.py", astToPrint);
}

ArrayList<SemanticError> errorsWithDup = ast.checkSemantics(ST, 0, null);
ArrayList<SemanticError> errors = Share.removeDuplicates(errorsWithDup);
if (!errors.isEmpty()) {
Expand All @@ -65,35 +91,57 @@ public static void main(String[] args) {
System.out.println("\t" + e);
}
} else {
System.out.println("Visualizing AST...");
System.out.println(ast.toPrint(""));
System.out.println("Creating VM code...");
String prog = ast.codeGeneration();
String asmFile = "code.asm";
Path file = Paths.get(asmFile);
if (!Files.exists(file)) {
Files.createFile(file);
if (treeFlag) {
JFrame frame = new JFrame("Parse Tree");
JPanel panel = new JPanel();
TreeViewer viewer = new TreeViewer(Arrays.asList(parser.getRuleNames()),
tree);
viewer.setScale(1); // Zoom factor
panel.add(viewer);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setVisible(true);

System.out.println(ast.printAST(""));
}

if (execute) {
System.out.println("Creating VM code...");
String asmFile = "code.asm";
String prog = ast.codeGeneration();
Share.saveFile(asmFile, prog);
executeVMFile(asmFile);
}
Files.write(file, prog.getBytes(), StandardOpenOption.TRUNCATE_EXISTING);
System.out.println("Done!");

CharStream inputASM = CharStreams.fromFileName(asmFile);
SVMLexer lexerASM = new SVMLexer(inputASM);
CommonTokenStream tokensASM = new CommonTokenStream(lexerASM);
SVMParser parserASM = new SVMParser(tokensASM);
System.out.println("Everything is OK!");
}
} catch (Exception e) {
e.printStackTrace();
}
}

SVMVisitorImpl visitorSVM = new SVMVisitorImpl();
visitorSVM.visit(parserASM.assembly());
private static void executeVMFile(String fileName) {
try {
CharStream inputASM = CharStreams.fromFileName(fileName);
SVMLexer lexerASM = new SVMLexer(inputASM);
CommonTokenStream tokensASM = new CommonTokenStream(lexerASM);
SVMParser parserASM = new SVMParser(tokensASM);

System.out.println("You had: " + lexerASM.lexicalErrors + " lexical errors and "
+ parserASM.getNumberOfSyntaxErrors() + " syntax errors.");
if (lexerASM.lexicalErrors > 0 || parserASM.getNumberOfSyntaxErrors() > 0)
System.exit(1);
SVMVisitorImpl visitorSVM = new SVMVisitorImpl();
visitorSVM.visit(parserASM.assembly());

System.out.println("Starting Virtual Machine...");
ExecuteVM vm = new ExecuteVM(visitorSVM.code);
vm.cpu();
int nLexicalErrors = lexerASM.lexicalErrors;
int nSyntaxErrors = parserASM.getNumberOfSyntaxErrors();
if (nLexicalErrors > 0 || nSyntaxErrors > 0) {
System.out.println("You had " + nLexicalErrors + " lexical errors and "
+ nSyntaxErrors + " syntax errors in the asm file.");
System.exit(1);
}

System.out.println("Executing assemply code...");
ExecuteVM vm = new ExecuteVM(visitorSVM.code);
vm.cpu();
} catch (Exception e) {
e.printStackTrace();
}
Expand Down
2 changes: 1 addition & 1 deletion src/ParseAll.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public static void main(String[] args) {
Python3Parser.RootContext tree = parser.root();
String treeStr = tree.toStringTree();

Python3VisitorImpl visitor = new Python3VisitorImpl();
Python3VisitorImpl visitor = new Python3VisitorImpl(tokenStream, false);
SymbolTable ST = new SymbolTable();
Node ast = visitor.visit(tree);
ArrayList<SemanticError> errorsWithDup = ast.checkSemantics(ST, 0, null);
Expand Down
Loading

0 comments on commit ce49d20

Please sign in to comment.