Compare commits

...

97 Commits

Author SHA1 Message Date
9801f8a5ae Merge branch 'targetBytecode' of ssh://gitea.hb.dhbw-stuttgart.de:2221/JavaTX/JavaCompilerCore into targetBytecode
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 5m39s
2024-08-07 13:34:03 +02:00
f0b9bea23e Fix #343 (le null check) 2024-08-07 13:33:40 +02:00
ce4347dd96 Fix Y Test #341
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 5m20s
2024-08-06 12:42:09 +02:00
7785c2d0aa Fix equals method of ClassOrInterface
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 6m48s
2024-08-05 11:54:13 +02:00
a654f55deb Fix yTest
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 4m45s
2024-07-25 17:05:27 +02:00
pl@gohorb.ba-horb.de
7037bdf9ef modified: src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 5m16s
2024-07-24 23:31:13 +02:00
pl@gohorb.ba-horb.de
d9860497df Merge branch 'targetBytecode' of ssh://gitea.hb.dhbw-stuttgart.de:2222/JavaTX/JavaCompilerCore into targetBytecode
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 5m38s
src/test/java/AllgemeinTest.java
2024-07-24 23:25:07 +02:00
pl@gohorb.ba-horb.de
fdffc11580 modified: resources/AllgemeinTest/Box.jav
deleted:    resources/bytecode/javFiles/Box.java
	modified:   src/test/java/AllgemeinTest.java
2024-07-24 23:23:39 +02:00
pl@gohorb.ba-horb.de
c10de35ca2 new file: resources/AllgemeinTest/Bar.java
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 5m25s
2024-07-24 18:28:07 +02:00
pl@gohorb.ba-horb.de
56b73332c0 modified: pom.xml
new file:   resources/AllgemeinTest/Foo.jav
	modified:   src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java
2024-07-24 18:27:32 +02:00
pl@gohorb.ba-horb.de
bdcd5ea3cf Merge branch 'targetBytecode' of https://gitea.hb.dhbw-stuttgart.de/JavaTX/JavaCompilerCore into targetBytecode 2024-07-24 12:35:43 +02:00
edafbbc5a0 Fix #340
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 44s
2024-07-23 15:33:09 +02:00
ba8810e5df I don't know why isFunctionalInterface returns true on things that aren't even interfaces but here we go
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m0s
2024-07-19 18:04:33 +02:00
63493ed0f7 Make lambdas castable
Some checks are pending
Build and Test with Maven / Build-and-test-with-Maven (push) Waiting to run
2024-07-19 17:26:39 +02:00
pl@gohorb.ba-horb.de
4dba867f9e Merge branch 'targetBytecode' of ssh://gitea.hb.dhbw-stuttgart.de:2222/JavaTX/JavaCompilerCore into targetBytecode 2024-06-14 11:28:05 +02:00
pl@gohorb.ba-horb.de
06caf0ff66 Merge branch 'targetBytecode' of ssh://gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into targetBytecode 2024-06-14 11:27:14 +02:00
ec92b5d5e1 Work on Bug #332
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 46s
2024-06-13 17:23:19 +02:00
091a6b8f1f Fix merge conflict
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 43s
2024-06-07 12:16:03 +02:00
60a1f3b220 Merge branch 'targetBytecode' of https://gitea.hb.dhbw-stuttgart.de/JavaTX/JavaCompilerCore into targetBytecode
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 47s
2024-06-07 12:04:01 +02:00
7e6aeaf728 Make Function Types implement others to allow Subtyping, fixes #337 2024-06-07 12:03:16 +02:00
Ruben
ea217d16d5 Revert "feat: changes in Grammar and Parser so typeless Recs get recognised"
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 6m35s
This reverts commit 7650813bb7.
2024-06-06 12:07:32 +02:00
Ruben
7650813bb7 feat: changes in Grammar and Parser so typeless Recs get recognised
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
2024-06-06 12:06:28 +02:00
pl@gohorb.ba-horb.de
5d03995f10 Merge branch 'targetBytecode' of https://gitea.hb.dhbw-stuttgart.de/JavaTX/JavaCompilerCore into targetBytecode 2024-05-27 17:44:29 +02:00
pl@gohorb.ba-horb.de
1bc58573c7 modified: src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java
modified:   src/test/java/AllgemeinTest.java
2024-05-27 17:35:59 +02:00
4880527d4d Give an exception if a method has been duplicated
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 9m6s
2024-05-27 15:51:48 +02:00
50f2a29e1e Merge branch 'targetBytecode' of https://gitea.hb.dhbw-stuttgart.de/JavaTX/JavaCompilerCore into targetBytecode
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 8m1s
2024-05-27 12:17:24 +02:00
99f219de3b Work on #338, partially fixed 2024-05-27 12:14:00 +02:00
12bb613eb0 Fix test cases
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 7m42s
2024-05-24 12:46:26 +02:00
141e1cbc94 Make wildcard imports work again #330
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 7m6s
2024-05-23 11:39:56 +02:00
julian
5b4ea5a0c5 fix #327 and add support for glob syntax in classpath input
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 5m37s
2024-05-22 23:47:50 +02:00
b824680508 Fix #335
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 6m34s
2024-05-22 12:55:47 +02:00
295bf079b9 Add continue and do-while, close #331
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 6m15s
2024-05-21 12:14:12 +02:00
974582f7e5 Fix #333
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 5m57s
2024-05-17 10:49:45 +02:00
2ded0c9044 Add public
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 6m27s
2024-05-15 16:46:15 +02:00
pl@gohorb.ba-horb.de
c3343959c5 modified: ../resources/AllgemeinTest/Box.jav
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 6m43s
modified:   ../resources/bytecode/javFiles/Box.jav
	modified:   ../src/test/java/AllgemeinTest.java
	modified:   ../src/test/java/TestComplete.java
2024-05-15 14:26:42 +02:00
pl@gohorb.ba-horb.de
39f04b1a1b Merge branch 'targetBytecode' of ssh://gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into targetBytecode 2024-05-14 22:53:52 +02:00
Pluemicke Martin
3d2b935c60 Merge branch 'targetBytecode' of https://gitea.hb.dhbw-stuttgart.de/JavaTX/JavaCompilerCore into targetBytecode 2024-05-14 22:53:08 +02:00
Pluemicke Martin
db01b0c8dd new file: resources/AllgemeinTest/Box.jav 2024-05-14 22:50:20 +02:00
662756ac18 Merge branch 'targetBytecode' of https://gitea.hb.dhbw-stuttgart.de/JavaTX/JavaCompilerCore into targetBytecode
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 5m26s
2024-05-10 16:51:10 +02:00
b0bf41968e Bug325 2024-05-10 16:50:06 +02:00
pl@gohorb.ba-horb.de
2221b559ca Implementierungen von Interfaces eingefuegt und Overriding ersetzt durch implementierung
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 6m2s
modified:   ../src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java

Overriding ersetzt durch implementierung (Umbennennung)
	modified:   ../resources/bytecode/javFiles/Matrix.jav
	modified:   ../src/main/java/de/dhbwstuttgart/syntaxtree/Method.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
2024-05-10 14:16:23 +02:00
pl@gohorb.ba-horb.de
021b7ec9fe Fehler vom vorigen korriert Commit
modified:   ../resources/bytecode/javFiles/Matrix.jav
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java
	modified:   ../src/test/java/TestComplete.java
2024-05-08 09:07:22 +02:00
pl@gohorb.ba-horb.de
154d4823e4 isOverridden eingefuegt.
Problem beim Konvertioeren
	modified:   ../src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java
	modified:   ../src/main/java/de/dhbwstuttgart/syntaxtree/Method.java
	modified:   ../src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java
2024-05-08 00:14:21 +02:00
pl@gohorb.ba-horb.de
71dfe5d9e1 Bei diesem und vorigen Commit wurde der Bug #328
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 11m55s
JavaTX/JavaCompilerCore#328
geloest.

1. src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
in der Methode copute wurden die methodSignatureConstraints der bereits zu Beginn
aufegloesten einer Oder Constraints in die Methodconstraints der Unifikation geschrieben
2. Elementtyp der linken Seiten der methodSignatureConstraints wurden von RefTypeOrTPHOrWildcardOrGeneric auf TypePlaceholder geaendert, weil dort nur TypePlaceholder geaendert.
3. src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java
in der Methode prepareBlock wurde der Typ des Rückgabewerts des supercalls von Void auf eine
Freshtpevar gesetzt.
4. src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
in der unify2-Methode wurde am Ende der Aufruf der Substitution nach Hinzufuegen der
Methodconstraints auskommentiert -> hat zu nicht geloesten Constraints gefuehrt.

	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
	modified:   src/test/java/TestComplete.java
2024-05-02 16:33:37 +02:00
pl@gohorb.ba-horb.de
58110c474a mathStrucInteger.jav funktioniert gerade nicht
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 12m21s
modified:   resources/bytecode/javFiles/Matrix.jav
	modified:   src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java
	modified:   src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java
	modified:   src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java
	modified:   src/main/java/de/dhbwstuttgart/syntaxtree/statement/NewClass.java
	modified:   src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java
	modified:   src/main/java/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java
2024-05-02 00:13:45 +02:00
df2ec4b1ba Fix #326, convert captures to correct types
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 3m9s
2024-04-30 16:55:40 +02:00
2c66a1d6e6 add class file
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 3m58s
2024-04-29 10:27:23 +02:00
c76ee355d8 Add bug for #328
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
2024-04-29 10:25:01 +02:00
a5c314c5c5 Fix #328
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m50s
2024-04-28 19:25:20 +02:00
cba35a4bec Don't load source files twice
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m51s
2024-04-27 23:08:15 +02:00
b774281cbb Add Ternary, fix #324
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m48s
2024-04-22 12:17:53 +02:00
9358130468 Fix package weirdness? See #322
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 3m3s
2024-04-18 11:51:08 +02:00
708aa64283 Fix current directory not being added to path
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m50s
2024-04-18 10:31:12 +02:00
c21e5202d6 Fix #323
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 3m14s
2024-04-18 10:20:35 +02:00
b3bd5cde10 Fix tests
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 3m58s
2024-04-15 16:44:34 +02:00
df78937ef3 Fix test case a bit
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 3m35s
2024-04-15 16:18:25 +02:00
7fb4824f8d Add modulo, fix #319
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m53s
2024-04-12 15:40:22 +02:00
e0d71a6003 fix console
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m37s
2024-04-12 14:17:15 +02:00
49803385cf Fix optional parameters
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m44s
2024-04-12 13:58:11 +02:00
39d02f792c Deal with multiple source files properly, don't throw all the constraints together
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m21s
2024-04-12 10:48:13 +02:00
4fc78f494c More poking around
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 3m1s
2024-04-10 10:22:34 +02:00
b752219d8c Throw exception if class doesn't exist
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 3m11s
2024-04-10 10:03:59 +02:00
ec890356e4 Don't trim stack trace because some tests randomly fail and we need to know why
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m59s
2024-04-10 09:58:01 +02:00
d405b0c3a2 Merge branch 'targetBytecode' of ssh://gitea.hb.dhbw-stuttgart.de:2222/JavaTX/JavaCompilerCore into targetBytecode
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m51s
2024-04-10 09:42:47 +02:00
6c8657b7a8 Work on #308 2024-04-10 09:42:31 +02:00
pl@gohorb.ba-horb.de
bcce4cee19 modified: src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntacticSugar.java
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m21s
Im Visitor ReturnFinder wuder nicht beruecksichtigt, dass auch in einem Lambda-Ausdruck ein Reurn stehen kann, welchen die umgebenden Block nicht beendet.
2024-04-09 18:25:26 +02:00
e6cd4038e2 Fix bytecode error when calling interface functions
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m48s
2024-04-09 15:52:44 +02:00
e50f941b79 Merge branch 'targetBytecode' of ssh://gitea.hb.dhbw-stuttgart.de:2222/JavaTX/JavaCompilerCore into targetBytecode
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m33s
2024-04-09 14:59:16 +02:00
cb7d0e22cc Fix #314 2024-04-09 14:58:43 +02:00
pl@gohorb.ba-horb.de
0d5be89310 modified: ../src/main/java/de/dhbwstuttgart/typeinference/unify/Match.java
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m50s
modified:   ../src/test/java/TestComplete.java
2024-04-09 01:50:42 +02:00
0b7f07108f Fix #313
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m43s
2024-04-08 14:25:41 +02:00
6b0816c1c4 Add test for #309
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m47s
2024-04-08 14:02:57 +02:00
f66b9099f3 Fix #311
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m55s
2024-04-08 13:51:49 +02:00
da74898f9d Fix #312
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m45s
2024-04-08 13:18:27 +02:00
46a7f61234 Fix #310
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m49s
2024-04-08 11:52:52 +02:00
e59accf7ee Fix #308
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
2024-04-08 11:40:46 +02:00
pl@gohorb.ba-horb.de
4b110244f2 new file: ../../AllgemeinTest/List.jav
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m46s
2024-04-07 17:31:05 +02:00
pl@gohorb.ba-horb.de
e37040f367 Bug 307 gefixt
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m51s
Changes to be committed:
	modified:   src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
	modified:   src/test/java/TestComplete.java
2024-04-03 00:11:01 +02:00
6850a8fa21 Decouple unify from the rest of the code
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 3m22s
2024-03-28 10:35:34 +01:00
877e5ed38a Reversing alone would disturb the parameters (#298)
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m2s
2024-03-27 14:52:15 +01:00
82b4450857 Fix 298 for real this time?
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m3s
2024-03-27 14:39:43 +01:00
b70e435120 Work on issue
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 59s
2024-03-27 12:21:57 +01:00
3b14cd609f Revert "Get rid of mutable state, hopefully fix #307"
This reverts commit bc61fc2e1d.
2024-03-27 09:57:21 +01:00
8fdfbf875b Fix #298 maybe?
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m42s
2024-03-26 17:31:48 +01:00
bc61fc2e1d Get rid of mutable state, hopefully fix #307
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m57s
2024-03-26 16:54:24 +01:00
62f2e05f35 Add test case for #307
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m37s
2024-03-26 11:04:03 +01:00
606ce8b82d Implement AND/OR/XOR, fix #305
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m26s
2024-03-26 10:54:32 +01:00
c84befae51 Add Negation operator (fixes #304)
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m41s
2024-03-25 17:05:20 +01:00
7f3c1686ec Fix #303
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m37s
2024-03-25 15:10:47 +01:00
43da2ffbdc Fix #302
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m47s
2024-03-25 14:49:18 +01:00
9472b5c86f Types are weird in this one
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m23s
2024-03-25 13:51:56 +01:00
7cb0e9dbb7 Taking the super methods parameters should only happen for the types, fix #306
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m23s
2024-03-25 13:43:30 +01:00
e07521d9b6 Fix #298
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m33s
2024-03-25 12:14:03 +01:00
c2ee12397f Work on issue
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m53s
2024-03-22 14:54:23 +01:00
e6321ff8bc Fix gtvs being strange, #301 2024-03-21 17:40:42 +01:00
786e0a7a23 Fix #300 and also call private methods correctly
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m35s
2024-03-21 11:49:16 +01:00
1c63321b30 Fix #294
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 2m35s
2024-03-20 14:37:15 +01:00
109 changed files with 2206 additions and 767 deletions

14
pom.xml
View File

@ -29,14 +29,14 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<version>2.6</version> <version>2.6</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>io.github.classgraph</groupId>
<artifactId>guava</artifactId> <artifactId>classgraph</artifactId>
<version>22.0</version> <version>4.8.172</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.reflections</groupId> <groupId>com.google.guava</groupId>
<artifactId>reflections</artifactId> <artifactId>guava</artifactId>
<version>0.9.11</version> <version>33.2.0-jre</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm --> <!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
<dependency> <dependency>
@ -66,7 +66,7 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<redirectTestOutputToFile>true</redirectTestOutputToFile> <redirectTestOutputToFile>true</redirectTestOutputToFile>
<reportsDirectory>${project.build.directory}/test-reports</reportsDirectory> <reportsDirectory>${project.build.directory}/test-reports</reportsDirectory>
<argLine>--enable-preview</argLine> <argLine>--enable-preview</argLine>
<trimStackTrace>true</trimStackTrace> <trimStackTrace>false</trimStackTrace>
<excludes> <excludes>
<exclude>**/JavaTXCompilerTest.java</exclude> <exclude>**/JavaTXCompilerTest.java</exclude>
<exclude>**/AllgemeinTest.java</exclude> <exclude>**/AllgemeinTest.java</exclude>

View File

@ -0,0 +1,10 @@
public class Bar{
void visit(Object o){
System.out.println("Object");
}
void visit(Bla f){
System.out.println("Foo");
}
}

View File

@ -0,0 +1,9 @@
public class Box<A> {
A a;
public Box() { }
public Box(A a) {
//this.a = a;
}
}

View File

@ -0,0 +1,6 @@
public class Foo{
public accept(Bar b){
b.visit(this);
}
}

View File

@ -0,0 +1,46 @@
import java.lang.Boolean;
import java.lang.Object;
class List {
elem;
next;
List() {
super();
}
List(elem, next) {
this.elem = elem;
this.next = next;
}
addElement(newElem) {
return new List(newElem, this);
}
append(l) {
if (next == null) {
return l;
}
else {
return new List(elem, next.append(l));
}
}
/*
addAll(l) {
var nextLoc = next;
while (//nextLoc != null
true) {
nextLoc = nextLoc.next;
}
nextLoc = l;
}
void m() {
List<? extends Object> l; // = new List<Integer>(1, null);
List<? extends Object> l2; // = new List<String>("SSS", null);
l.addAll(l2);
}
*/
}

View File

@ -1,7 +1,9 @@
class B { } public class Box<A> {
class Box_Main extends B {
m(b) { A a;
b.m(new Box_Main());
b.m(new B()); public Box() { }
} public Box(A a) {
} //this.a = a;
}
}

View File

@ -1,3 +0,0 @@
class Box<A> {
void m(A a) { }
}

View File

@ -2,18 +2,16 @@ import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.lang.Integer; import java.lang.Integer;
import java.lang.System; import java.lang.System;
import java.lang.Boolean;
import java.io.PrintStream; import java.io.PrintStream;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.function.Function; import java.util.function.Function;
public class Bug298 { public class Bug298 {
public <R, T> Stream<R> takes(Stream<T> s, Function<? super T, ? super R> fun) {
return null;
}
public void m() { public void m() {
List<Integer> list = new ArrayList<>(); List<Integer> list = new ArrayList<>();
Stream<Integer> a = list.stream(); list.stream().map(x -> 2 * x);
takes(a, x -> 2 * x);
Function<Integer, Boolean> filter = x -> true;
} }
} }

View File

@ -0,0 +1,17 @@
import java.lang.String;
class Base {
toString() {
return "Base";
}
}
public class Bug300 extends Base {
public m() {
return super.toString();
}
toString() {
return "Derived";
}
}

View File

@ -0,0 +1,4 @@
import java.util.HashSet;
public class Bug301<A> extends HashSet<A> {
}

View File

@ -0,0 +1,11 @@
import java.util.ArrayList;
import java.util.List;
import java.lang.Integer;
public class Bug302 {
public Bug302(List<Integer> a){}
public static m() {
new Bug302(new ArrayList<Integer>());
}
}

View File

@ -0,0 +1,13 @@
import java.lang.Integer;
import java.util.List;
class Base {
m(List<Integer> a) {}
}
public class Bug306 extends Base {
@Override
m(List<Integer> b) {
b.add(1);
}
}

View File

@ -0,0 +1,46 @@
public class Bug307 {
public void main() {
IVisitor v = new Visitor();
Impl2 f = new Impl2();
Impl1 g = new Impl1();
f.accept(v);
g.accept(v);
}
}
interface IVisitor {
void visit(Impl1 f);
void visit(Impl2 fb);
}
interface IAcceptor {
void accept(IVisitor v);
}
class Visitor implements IVisitor {
@Override
public void visit(Impl1 f) {
}
@Override
public void visit(Impl2 fb) {
}
}
class Impl1 implements IAcceptor {
@Override
public void accept(IVisitor v) {
v.visit(this);
}
}
class Impl2 implements IAcceptor {
@Override
public void accept(IVisitor v) {
v.visit(this);
}
}

View File

@ -0,0 +1,16 @@
import java.util.List;
import java.util.ArrayList;
import java.lang.Integer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.Optional;
public class Bug309 {
public main() {
List<Integer> list = new ArrayList<>(List.of(1,2,3,4,5,6,7,8,9));
var res = list.stream().filter(x -> x == 5).map(x -> x * 2).findFirst();
return res;
}
}

View File

@ -0,0 +1,9 @@
import java.lang.Integer;
import java.lang.String;
public class Bug310 {
Integer i = 3;
public toString() {
return i.toString();
}
}

View File

@ -0,0 +1,10 @@
import java.lang.String;
public class Bug311 {
Bug311A i = new Bug311A();
public toString() {
return i.toString();
}
}
class Bug311A {}

View File

@ -0,0 +1,8 @@
public class Bug312 {
Bug312A i = new Bug312A();
public main() {
if (i == null) {}
}
}
class Bug312A {}

View File

@ -0,0 +1,13 @@
import java.lang.Integer;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Stream;
import java.util.function.Predicate;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Bug314 {
public List<Integer> convert(List<Integer> in) {
return in.stream().filter(x -> x > 5).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,13 @@
import java.lang.Integer;
import java.util.function.Function;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Stream;
public class Bug325 {
public main() {
List<Integer> list = new ArrayList<>(List.of(1,2,3,4,5));
var func = x -> x*2;
return list.stream().map(func).toList();
}
}

View File

@ -0,0 +1,8 @@
import java.lang.Integer;
public class Bug326 {
public Bug326() {
var func = x -> y -> x * y;
return func.apply(3).apply(4);
}
}

View File

@ -0,0 +1,8 @@
import java.lang.Integer;
import Bug328B;
public class Bug328 extends Bug328B {
public Bug328() {
super(1);
}
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
public class Bug328B {
public Bug328B(int a) {}
}

View File

@ -0,0 +1,15 @@
import java.lang.Object;
interface Visitor {
public void visit(Object obj);
public void visit(ClassA a);
}
class ClassA {
void accept(Visitor v) {
v.visit(this);
}
}
public class Bug332 {
}

View File

@ -0,0 +1,11 @@
import java.lang.String;
public class Bug333 {
public static String Bar = "Bar";
}
class Bar {
public bar() {
String s = Bug333.Bar;
}
}

View File

@ -0,0 +1,10 @@
import java.lang.Integer;
import java.lang.Number;
import java.lang.Object;
public class Bug337 {
public void main() {
Fun1$$<Object, Integer> fun1 = x -> x.hashCode() + 1;
Fun1$$<Number, Number> fun2 = fun1;
}
}

View File

@ -0,0 +1,11 @@
import java.util.List;
import java.lang.Integer;
import java.lang.String;
import java.lang.Object;
import java.util.List;
public class Bug338 {
public hashCode() {
return List.of(42);
}
}

View File

@ -0,0 +1,2 @@
public record Bug343() {
}

View File

@ -0,0 +1,16 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.lang.String;
import java.util.stream.Stream;
import java.util.function.Function;
import java.util.function.Predicate;
import java.lang.Integer;
class BugXXX {
public main() {
List<Integer> i = new ArrayList<>(List.of(1,2,3,4,5,6,7,8,9,10));
Optional<Integer> tmp = i.stream().filter(x -> x == 5).map(x -> x*2).findFirst();
return tmp;
}
}

View File

@ -0,0 +1,5 @@
import java.lang.*;
public class ImportWildcard {
m(a, b) { return a * b; }
}

View File

@ -1,16 +0,0 @@
import java.lang.Runnable;
import java.lang.System;
import java.lang.String;
import java.io.PrintStream;
public class LamRunnable {
public LamRunnable() {
Runnable lam = () -> {
System.out.println("lambda");
};
lam.run();
}
}

View File

@ -3,4 +3,6 @@ import java.lang.Character;
public class Literal { public class Literal {
public m() { return null; } public m() { return null; }
public m2() { return 'C'; } public m2() { return 'C'; }
public m3() { return 10L; }
public m4() { return 10.5F; }
} }

View File

@ -1,3 +1,5 @@
import java.util.List;
import java.util.AbstractList;
import java.util.Vector; import java.util.Vector;
import java.lang.Integer; import java.lang.Integer;
//import java.lang.Float; //import java.lang.Float;
@ -30,8 +32,8 @@ public class Matrix extends Vector<Vector<Integer>> {
var erg = 0; var erg = 0;
var k = 0; var k = 0;
while(k < v1.size()) { while(k < v1.size()) {
erg = erg + v1.elementAt(k) erg = erg + v1.get(k)
* m.elementAt(k).elementAt(j); * m.get(k).get(j);
k++; } k++; }
// v2.addElement(new Integer(erg)); // v2.addElement(new Integer(erg));
v2.addElement(erg); v2.addElement(erg);

View File

@ -1,11 +1,34 @@
public class Op1{ import java.lang.Boolean;
public Op1() { import java.lang.Integer;
Runnable lam = () -> { public class Op1 {
String test = ""; public not() {
String b = "b"; var b = false;
test = b; var c = !b;
System.out.println(test);}; return c;
//lam.run();
} }
public or() {
var a = 10;
var b = 20;
return a | b;
}
public and() {
var a = 10;
var b = 20;
return a & b;
}
public xor() {
var a = 10;
var b = 20;
return a ^ b;
}
public mod() {
var a = 10;
var b = 2;
return a % b;
}
} }

View File

@ -0,0 +1,12 @@
import java.lang.Object;
import java.lang.Boolean;
public class OverrideEquals extends OverrideRoot {
public boolean equals(Object o) {
return true;
}
public int method(int var1, float var2) {
return 0;
}
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
public abstract class OverrideRoot {
public abstract int method(int a, float b);
}

View File

@ -11,9 +11,9 @@ record Rec(Integer a, Integer b) {}
}*/ }*/
public class RecordTest { public class RecordTest {
a = new Rec(10, 20); Rec a = new Rec(10, 20);
b = new Rec(10, 20); Rec b = new Rec(10, 20);
c = new Rec(20, 40); Rec c = new Rec(20, 40);
public doesEqual() { return a.equals(b); } public doesEqual() { return a.equals(b); }
public doesNotEqual() { return b.equals(c); } public doesNotEqual() { return b.equals(c); }

View File

@ -0,0 +1,9 @@
import java.lang.Boolean;
import java.lang.String;
import java.lang.Integer;
public class Ternary {
public main(x) {
return x > 10 ? "big" : "small";
}
}

View File

@ -9,4 +9,13 @@ public class While {
} }
return x; return x;
} }
public m2() {
int i = 0;
do {
++i;
} while(i < 10);
return i;
}
} }

View File

@ -2,41 +2,21 @@ import java.lang.Integer;
public class Y { public class Y {
y; y;
//factorial;
public Y() { public Y() {
y = f -> t -> f.apply(y.apply(f)).apply(t); y = f -> t -> f.apply(y.apply(f)).apply(t);
//factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); });
}
/*
getY() {
return y;
}
*/
}
/*
class fac1 {
factorial;
fac1() {
var y;
y = new Y<Integer,Integer,Integer,Integer,Integer>().getY();
factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); });
} }
} }
ergibt Parse-Error public class Fac1 {
class fac1 { public factorial;
factorial; public Fac1() {
fac1() {
var y; var y;
y = new Y<>().y; var tmp = new Y<>(); // TODO Having new Y<>().y on one line doesn't work, see FIXME in StatementGenerator
y = tmp.y;
factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); }); factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); });
} }
public static void main(String args[]) {
System.out.println(new fac1().factorial.apply(3)); public fac(v) {
return factorial.apply(v);
} }
}
}
*/

View File

@ -0,0 +1,3 @@
package pkg.sub;
public interface Interface {}

View File

@ -5,7 +5,11 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.Pattern;
import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
import de.dhbwstuttgart.target.generate.StatementToTargetExpression;
import de.dhbwstuttgart.target.tree.*; import de.dhbwstuttgart.target.tree.*;
import de.dhbwstuttgart.target.tree.expression.*; import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.*; import de.dhbwstuttgart.target.tree.type.*;
@ -14,6 +18,7 @@ import org.objectweb.asm.*;
import java.lang.invoke.*; import java.lang.invoke.*;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.*; import java.util.*;
import java.util.stream.IntStream;
import static org.objectweb.asm.Opcodes.*; import static org.objectweb.asm.Opcodes.*;
import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*; import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*;
@ -26,17 +31,25 @@ public class Codegen {
private int lambdaCounter = 0; private int lambdaCounter = 0;
private final HashMap<TargetLambdaExpression, TargetMethod> lambdas = new HashMap<>(); private final HashMap<TargetLambdaExpression, TargetMethod> lambdas = new HashMap<>();
private final JavaTXCompiler compiler; private final JavaTXCompiler compiler;
private final ASTToTargetAST converter;
public Codegen(TargetStructure clazz, JavaTXCompiler compiler) { private class CustomClassWriter extends ClassWriter {
public CustomClassWriter() {
super(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
}
@Override
protected ClassLoader getClassLoader() {
return compiler.getClassLoader();
}
}
public Codegen(TargetStructure clazz, JavaTXCompiler compiler, ASTToTargetAST converter) {
this.clazz = clazz; this.clazz = clazz;
this.className = clazz.qualifiedName().getClassName(); this.className = clazz.qualifiedName().getClassName();
this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) { this.cw = new CustomClassWriter();
@Override
protected ClassLoader getClassLoader() {
return compiler.getClassLoader();
}
};
this.compiler = compiler; this.compiler = compiler;
this.converter = converter;
} }
private record LocalVar(int index, String name, TargetType type) { private record LocalVar(int index, String name, TargetType type) {
@ -77,8 +90,6 @@ public class Codegen {
int localCounter; int localCounter;
MethodVisitor mv; MethodVisitor mv;
TargetType returnType; TargetType returnType;
// This is used to remember the type from lambda expressions
TargetType contextType;
Stack<BreakEnv> breakStack = new Stack<>(); Stack<BreakEnv> breakStack = new Stack<>();
Stack<Integer> switchResultValue = new Stack<>(); Stack<Integer> switchResultValue = new Stack<>();
@ -265,13 +276,43 @@ public class Codegen {
mv.visitInsn(I2F); mv.visitInsn(I2F);
else if (dest.equals(TargetType.Double)) else if (dest.equals(TargetType.Double))
mv.visitInsn(I2D); mv.visitInsn(I2D);
} else if (isFunctionalInterface(source) && isFunctionalInterface(dest) &&
!(source instanceof TargetFunNType && dest instanceof TargetFunNType)) {
boxFunctionalInterface(state, source, dest);
} else if (!(dest instanceof TargetGenericType)) { } else if (!(dest instanceof TargetGenericType)) {
boxPrimitive(state, source); //boxPrimitive(state, source);
mv.visitTypeInsn(CHECKCAST, dest.getInternalName()); mv.visitTypeInsn(CHECKCAST, dest.getInternalName());
unboxPrimitive(state, dest); unboxPrimitive(state, dest);
} }
} }
record TypePair(TargetType from, TargetType to) {}
private Map<TypePair, String> funWrapperClasses = new HashMap<>();
private void boxFunctionalInterface(State state, TargetType source, TargetType dest) {
var mv = state.mv;
var className = "FunWrapper$$" +
source.name().replaceAll("\\.", "\\$") +
"$_$" +
dest.name().replaceAll("\\.", "\\$");
funWrapperClasses.put(new TypePair(source, dest), className);
mv.visitTypeInsn(NEW, className);
mv.visitInsn(DUP_X1);
mv.visitInsn(SWAP);
mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(" + source.toDescriptor() + ")V", false);
}
private boolean isFunctionalInterface(TargetType type) {
if (type instanceof TargetFunNType) return true;
if (type instanceof TargetRefType) {
var clazz = compiler.getClass(new JavaClassName(type.name()));
return (clazz.getModifiers() & Modifier.INTERFACE) != 0 && clazz.isFunctionalInterface();
}
return false;
}
private TargetType largerType(TargetType left, TargetType right) { private TargetType largerType(TargetType left, TargetType right) {
if (left.equals(TargetType.String) || right.equals(TargetType.String)) { if (left.equals(TargetType.String) || right.equals(TargetType.String)) {
return TargetType.String; return TargetType.String;
@ -281,9 +322,12 @@ public class Codegen {
return TargetType.Float; return TargetType.Float;
} else if (left.equals(TargetType.Long) || right.equals(TargetType.Long)) { } else if (left.equals(TargetType.Long) || right.equals(TargetType.Long)) {
return TargetType.Long; return TargetType.Long;
} else { } else if (left.equals(TargetType.Integer) || right.equals(TargetType.Integer)) {
return TargetType.Integer; return TargetType.Integer;
} else if (left.equals(TargetType.Short) || right.equals(TargetType.Short)) {
return TargetType.Short;
} }
return left;
} }
private void generateBinaryOp(State state, TargetBinaryOp op) { private void generateBinaryOp(State state, TargetBinaryOp op) {
@ -718,15 +762,23 @@ public class Codegen {
private void generateLambdaExpression(State state, TargetLambdaExpression lambda) { private void generateLambdaExpression(State state, TargetLambdaExpression lambda) {
var mv = state.mv; var mv = state.mv;
String methodName = "apply";
TargetMethod.Signature signature = new TargetMethod.Signature(Set.of(),
lambda.signature().parameters().stream().map(
par -> par.withType(TargetType.Object)).toList(),
lambda.signature().returnType() != null ? TargetType.Object : null);
var parameters = new ArrayList<>(lambda.captures());
parameters.addAll(signature.parameters());
var implSignature = new TargetMethod.Signature(Set.of(), parameters, lambda.signature().returnType());
TargetMethod impl; TargetMethod impl;
if (lambdas.containsKey(lambda)) { if (lambdas.containsKey(lambda)) {
impl = lambdas.get(lambda); impl = lambdas.get(lambda);
} else { } else {
var name = "lambda$" + lambdaCounter++; var name = "lambda$" + lambdaCounter++;
var parameters = new ArrayList<>(lambda.captures());
parameters.addAll(lambda.params().stream().map(param -> param.pattern().type() instanceof TargetGenericType ? param.withType(TargetType.Object) : param).toList());
impl = new TargetMethod(0, name, lambda.block(), new TargetMethod.Signature(Set.of(), parameters, lambda.returnType() instanceof TargetGenericType ? TargetType.Object : lambda.returnType()), null); impl = new TargetMethod(0, name, lambda.block(), implSignature, null);
generateMethod(impl); generateMethod(impl);
lambdas.put(lambda, impl); lambdas.put(lambda, impl);
} }
@ -734,35 +786,55 @@ public class Codegen {
var mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class); var mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class);
var bootstrap = new Handle(H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", mt.toMethodDescriptorString(), false); var bootstrap = new Handle(H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", mt.toMethodDescriptorString(), false);
var handle = new Handle(H_INVOKEVIRTUAL, clazz.getName(), impl.name(), impl.getDescriptor(), false); var handle = new Handle(H_INVOKEVIRTUAL, clazz.getName(), impl.name(), implSignature.getDescriptor(), false);
// TODO maybe make this a function?
var desugared = "(";
for (var param : lambda.params())
desugared += "Ljava/lang/Object;";
desugared += ")";
if (lambda.returnType() != null)
desugared += "Ljava/lang/Object;";
else
desugared += "V";
var params = new ArrayList<TargetType>(); var params = new ArrayList<TargetType>();
params.add(new TargetRefType(clazz.qualifiedName().getClassName())); params.add(new TargetRefType(clazz.qualifiedName().getClassName()));
params.addAll(lambda.captures().stream().map(mp -> mp.pattern().type()).toList()); params.addAll(lambda.captures().stream().map(mp -> mp.pattern().type()).toList());
var descriptor = TargetMethod.getDescriptor(state.contextType, params.toArray(TargetType[]::new));
mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0);
for (var capture : lambda.captures()) { for (var index = 0; index < lambda.captures().size(); index++) {
var capture = lambda.captures().get(index);
var pattern = (TargetTypePattern) capture.pattern(); var pattern = (TargetTypePattern) capture.pattern();
mv.visitVarInsn(ALOAD, state.scope.get(pattern.name()).index); var variable = state.scope.get(pattern.name());
mv.visitVarInsn(ALOAD, variable.index);
mv.visitTypeInsn(CHECKCAST, capture.pattern().type().getInternalName());
} }
String methodName; var descriptor = TargetMethod.getDescriptor(lambda.type(), params.toArray(TargetType[]::new));
var intf = compiler.getClass(new JavaClassName(state.contextType.name())); mv.visitInvokeDynamicInsn(methodName, descriptor, bootstrap, Type.getType(signature.getSignature()), handle, Type.getType(signature.getDescriptor()));
if (intf == null) methodName = "apply"; // TODO Weird fallback logic here }
else methodName = intf.getMethods().stream().filter(m -> Modifier.isAbstract(m.modifier)).findFirst().orElseThrow().getName();
mv.visitInvokeDynamicInsn(methodName, descriptor, bootstrap, Type.getType(desugared), handle, Type.getType(TargetMethod.getDescriptor(impl.signature().returnType(), lambda.params().stream().map(mp -> mp.pattern().type()).toArray(TargetType[]::new)))); private int findReturnCode(TargetType returnType) {
if (returnType.equals(TargetType.boolean_)
|| returnType.equals(TargetType.char_)
|| returnType.equals(TargetType.int_)
|| returnType.equals(TargetType.short_)
|| returnType.equals(TargetType.byte_))
return IRETURN;
else if (returnType.equals(TargetType.long_))
return LRETURN;
else if (returnType.equals(TargetType.float_))
return FRETURN;
else if (returnType.equals(TargetType.double_))
return DRETURN;
return ARETURN;
}
private int findLoadCode(TargetType loadType) {
if (loadType.equals(TargetType.boolean_)
|| loadType.equals(TargetType.char_)
|| loadType.equals(TargetType.int_)
|| loadType.equals(TargetType.short_)
|| loadType.equals(TargetType.byte_))
return ILOAD;
else if (loadType.equals(TargetType.long_))
return LLOAD;
else if (loadType.equals(TargetType.float_))
return FLOAD;
else if (loadType.equals(TargetType.double_))
return DLOAD;
return ALOAD;
} }
private void generate(State state, TargetExpression expr) { private void generate(State state, TargetExpression expr) {
@ -789,10 +861,7 @@ public class Codegen {
break; break;
} }
case TargetCast cast: case TargetCast cast:
var ctx = state.contextType;
state.contextType = cast.type();
generate(state, cast.expr()); generate(state, cast.expr());
state.contextType = ctx;
convertTo(state, cast.expr().type(), cast.type()); convertTo(state, cast.expr().type(), cast.type());
break; break;
case TargetInstanceOf instanceOf: case TargetInstanceOf instanceOf:
@ -837,10 +906,7 @@ public class Codegen {
case TargetAssign assign: { case TargetAssign assign: {
switch (assign.left()) { switch (assign.left()) {
case TargetLocalVar localVar -> { case TargetLocalVar localVar -> {
var ctype = state.contextType;
state.contextType = localVar.type();
generate(state, assign.right()); generate(state, assign.right());
state.contextType = ctype;
convertTo(state, assign.right().type(), localVar.type()); convertTo(state, assign.right().type(), localVar.type());
boxPrimitive(state, localVar.type()); boxPrimitive(state, localVar.type());
@ -853,10 +919,7 @@ public class Codegen {
if (!(dot.left() instanceof TargetThis && dot.isStatic())) if (!(dot.left() instanceof TargetThis && dot.isStatic()))
generate(state, dot.left()); generate(state, dot.left());
var ctype = state.contextType;
state.contextType = fieldType;
generate(state, assign.right()); generate(state, assign.right());
state.contextType = ctype;
convertTo(state, assign.right().type(), fieldType); convertTo(state, assign.right().type(), fieldType);
boxPrimitive(state, fieldType); boxPrimitive(state, fieldType);
@ -873,6 +936,8 @@ public class Codegen {
case TargetLocalVar localVar: { case TargetLocalVar localVar: {
LocalVar local = state.scope.get(localVar.name()); LocalVar local = state.scope.get(localVar.name());
mv.visitVarInsn(ALOAD, local.index()); mv.visitVarInsn(ALOAD, local.index());
// This is a bit weird but sometimes the types don't match (see lambda expressions)
convertTo(state, local.type(), localVar.type());
unboxPrimitive(state, local.type()); unboxPrimitive(state, local.type());
break; break;
} }
@ -946,6 +1011,27 @@ public class Codegen {
mv.visitLabel(end); mv.visitLabel(end);
break; break;
} }
case TargetDo _do: {
Label start = new Label();
Label end = new Label();
Label check = new Label();
var env = new BreakEnv();
env.startLabel = check;
env.endLabel = end;
mv.visitLabel(start);
state.breakStack.push(env);
generate(state, _do.body());
state.breakStack.pop();
mv.visitLabel(check);
generate(state, _do.cond());
mv.visitJumpInsn(IFEQ, end);
mv.visitJumpInsn(GOTO, start);
mv.visitLabel(end);
break;
}
case TargetIf _if: { case TargetIf _if: {
generate(state, _if.cond()); generate(state, _if.cond());
Label _else = new Label(); Label _else = new Label();
@ -962,13 +1048,17 @@ public class Codegen {
} }
case TargetReturn ret: { case TargetReturn ret: {
if (ret.expression() != null && state.returnType != null) { if (ret.expression() != null && state.returnType != null) {
var ctype = state.contextType; if (state.returnType instanceof TargetPrimitiveType) {
state.contextType = state.returnType; generate(state, ret.expression());
generate(state, ret.expression());
state.contextType = ctype; unboxPrimitive(state, state.returnType);
boxPrimitive(state, ret.expression().type()); mv.visitInsn(findReturnCode(state.returnType));
convertTo(state, ret.expression().type(), state.returnType); } else {
mv.visitInsn(ARETURN); generate(state, ret.expression());
boxPrimitive(state, ret.expression().type());
convertTo(state, ret.expression().type(), state.returnType);
mv.visitInsn(ARETURN);
}
} else } else
mv.visitInsn(RETURN); mv.visitInsn(RETURN);
break; break;
@ -1008,23 +1098,28 @@ public class Codegen {
break; break;
} }
case TargetMethodCall call: { case TargetMethodCall call: {
if (!call.isStatic()) if (!call.isStatic()) {
generate(state, call.expr()); generate(state, call.expr());
boxPrimitive(state, call.expr().type());
}
for (var i = 0; i < call.args().size(); i++) { for (var i = 0; i < call.args().size(); i++) {
var e = call.args().get(i); var e = call.args().get(i);
var arg = call.parameterTypes().get(i); var arg = call.parameterTypes().get(i);
var ctype = state.contextType;
state.contextType = arg;
generate(state, e); generate(state, e);
convertTo(state, e.type(), arg);
if (!(arg instanceof TargetPrimitiveType)) if (!(arg instanceof TargetPrimitiveType))
boxPrimitive(state, e.type()); boxPrimitive(state, e.type());
state.contextType = ctype;
} }
var descriptor = call.getDescriptor(); var descriptor = call.getDescriptor();
if (call.owner() instanceof TargetFunNType) // Decay FunN if (call.owner() instanceof TargetFunNType) // Decay FunN
descriptor = TargetMethod.getDescriptor(call.returnType() == null ? null : TargetType.Object, call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new)); descriptor = TargetMethod.getDescriptor(call.returnType() == null ? null : TargetType.Object, call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new));
mv.visitMethodInsn(call.isInterface() ? INVOKEINTERFACE : call.isStatic() ? INVOKESTATIC : call.name().equals("<init>") ? INVOKESPECIAL : INVOKEVIRTUAL, call.owner().getInternalName(), call.name(), descriptor, call.isInterface()); int insn = INVOKEVIRTUAL;
if (call.isStatic()) insn = INVOKESTATIC;
else if (call.isInterface()) insn = INVOKEINTERFACE;
else if (call.name().equals("<init>") || call.expr() instanceof TargetSuper || call.isPrivate()) insn = INVOKESPECIAL;
mv.visitMethodInsn(insn, call.owner().getInternalName(), call.name(), descriptor, call.isInterface());
if (call.type() != null && call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) { if (call.type() != null && call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) {
if (!call.returnType().equals(call.type()) && !(call.type() instanceof TargetGenericType)) if (!call.returnType().equals(call.type()) && !(call.type() instanceof TargetGenericType))
@ -1051,6 +1146,20 @@ public class Codegen {
mv.visitInsn(ATHROW); mv.visitInsn(ATHROW);
break; break;
} }
case TargetTernary ternary: {
generate(state, ternary.cond());
var iffalse = new Label();
var end = new Label();
mv.visitJumpInsn(IFEQ, iffalse);
generate(state, ternary.iftrue());
convertTo(state, ternary.iftrue().type(), ternary.type());
mv.visitJumpInsn(GOTO, end);
mv.visitLabel(iffalse);
generate(state, ternary.iffalse());
convertTo(state, ternary.iffalse().type(), ternary.type());
mv.visitLabel(end);
break;
}
default: default:
throw new CodeGenException("Unexpected value: " + expr); throw new CodeGenException("Unexpected value: " + expr);
} }
@ -1502,6 +1611,85 @@ public class Codegen {
if (clazz instanceof TargetRecord) if (clazz instanceof TargetRecord)
generateRecordMethods(); generateRecordMethods();
// Generate wrapper classes for function types
for (var pair : funWrapperClasses.keySet()) {
var className = funWrapperClasses.get(pair);
ClassWriter cw2 = new CustomClassWriter();
cw2.visit(V1_8, ACC_PUBLIC, className, null, "java/lang/Object", new String[] { pair.to.getInternalName() });
cw2.visitField(ACC_PRIVATE, "wrapped", pair.from.toDescriptor(), null, null).visitEnd();
// Generate constructor
var ctor = cw2.visitMethod(ACC_PUBLIC, "<init>", "(" + pair.from.toDescriptor() + ")V", null, null);
ctor.visitVarInsn(ALOAD, 0);
ctor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
ctor.visitVarInsn(ALOAD, 0);
ctor.visitVarInsn(ALOAD, 1);
ctor.visitFieldInsn(PUTFIELD, className, "wrapped", pair.from.toDescriptor());
ctor.visitInsn(RETURN);
ctor.visitMaxs(0, 0);
ctor.visitEnd();
String methodName = "apply";
String fromDescriptor = null;
TargetType fromReturn = null;
if (!(pair.from instanceof TargetFunNType funNType)) {
var fromClass = compiler.getClass(new JavaClassName(pair.from.name()));
var fromMethod = fromClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
methodName = fromMethod.name;
fromReturn = converter.convert(fromMethod.getReturnType());
var fromParams = converter.convert(fromMethod.getParameterList(), converter.generics.javaGenerics()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
fromDescriptor = TargetMethod.getDescriptor(fromReturn, fromParams);
} else {
fromReturn = funNType.returnArguments() > 0 ? TargetType.Object : null;
fromDescriptor = funNType.toMethodDescriptor();
}
var toClass = compiler.getClass(new JavaClassName(pair.to.name()));
var toMethod = toClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
var toReturn = converter.convert(toMethod.getReturnType());
var toParams = converter.convert(toMethod.getParameterList(), converter.generics.javaGenerics()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
var toDescriptor = TargetMethod.getDescriptor(toReturn, toParams);
// Generate wrapper method
var mv = cw2.visitMethod(ACC_PUBLIC, toMethod.name, toDescriptor, null, null);
var state = new State(null, mv, 0);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, className, "wrapped", pair.from.toDescriptor());
for (var i = 0; i < toParams.length; i++) {
var arg = toParams[i];
mv.visitVarInsn(findLoadCode(arg), i + 1);
}
mv.visitMethodInsn(INVOKEINTERFACE, pair.from.getInternalName(), methodName, fromDescriptor, true);
if (fromReturn != null) {
if (toReturn instanceof TargetPrimitiveType) {
convertTo(state, fromReturn, TargetType.toWrapper(toReturn));
} else convertTo(state, fromReturn, toReturn);
}
if (toReturn != null)
mv.visitInsn(findReturnCode(toReturn));
else mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
cw2.visitEnd();
var bytes = cw2.toByteArray();
converter.auxiliaries.put(className, bytes);
// TODO These class loading shenanigans happen in a few places, the tests load the classes individually.
// Instead we should just look at the folder.
try {
converter.classLoader.findClass(className);
} catch (ClassNotFoundException e) {
try {
converter.classLoader.loadClass(bytes);
} catch (LinkageError ignored) {}
}
}
cw.visitEnd(); cw.visitEnd();
return cw.toByteArray(); return cw.toByteArray();
} }

View File

@ -1,11 +1,13 @@
package de.dhbwstuttgart.bytecode; package de.dhbwstuttgart.bytecode;
import de.dhbwstuttgart.syntaxtree.statement.Break;
import de.dhbwstuttgart.target.tree.TargetGeneric; import de.dhbwstuttgart.target.tree.TargetGeneric;
import de.dhbwstuttgart.target.tree.type.*; import de.dhbwstuttgart.target.tree.type.*;
import org.objectweb.asm.ClassWriter; import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import java.sql.Array;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -33,6 +35,36 @@ public class FunNGenerator {
public static class GenericParameters { public static class GenericParameters {
int start; int start;
public List<TargetType> parameters = new ArrayList<>(); public List<TargetType> parameters = new ArrayList<>();
final String descriptor;
public final List<TargetType> inParams;
public final List<TargetType> realParams;
public GenericParameters(List<TargetType> params, int numReturns) {
this.realParams = params;
this.inParams = flattenTypeParams(params);
var type = new TargetRefType(FunNGenerator.getSuperClassName(params.size() - 1, numReturns), params);
descriptor = applyDescriptor(type, this);
}
private static List<TargetType> flattenTypeParams(List<TargetType> params) {
var res = new ArrayList<TargetType>();
for (var param : params) {
if (param instanceof TargetSpecializedType tspec) {
res.addAll(flattenTypeParams(tspec.params()));
} else {
res.add(param);
}
}
return res;
}
public TargetType getReturnType() {
return FunNGenerator.getReturnType(realParams);
}
public List<TargetType> getArguments() {
return FunNGenerator.getArguments(realParams);
}
} }
private static String applyDescriptor(TargetType type, GenericParameters gep) { private static String applyDescriptor(TargetType type, GenericParameters gep) {
@ -69,7 +101,7 @@ public class FunNGenerator {
return applyNameDescriptor(type).replace("/", "$").replace(";", "$_$"); return applyNameDescriptor(type).replace("/", "$").replace(";", "$_$");
} }
public static byte[] generateSuperBytecode(int numberArguments) { public static byte[] generateSuperBytecode(int numberArguments, int numReturnTypes) {
StringBuilder superFunNClassSignature = new StringBuilder("<"); StringBuilder superFunNClassSignature = new StringBuilder("<");
StringBuilder superFunNMethodSignature = new StringBuilder("("); StringBuilder superFunNMethodSignature = new StringBuilder("(");
StringBuilder superFunNMethodDescriptor = new StringBuilder("("); StringBuilder superFunNMethodDescriptor = new StringBuilder("(");
@ -80,30 +112,34 @@ public class FunNGenerator {
superFunNMethodDescriptor.append(objectSignature); superFunNMethodDescriptor.append(objectSignature);
} }
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature)); superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
superFunNMethodSignature.append(String.format(")T%s;", returnGeneric)); if (numReturnTypes > 0) {
superFunNMethodDescriptor.append(String.format(")%s", objectSignature)); superFunNMethodSignature.append(String.format(")T%s;", returnGeneric));
superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
} else {
superFunNMethodSignature.append(")V");
superFunNMethodDescriptor.append(")V");
}
System.out.println(superFunNMethodSignature); System.out.println(superFunNMethodSignature);
ClassWriter classWriter = new ClassWriter(0); ClassWriter classWriter = new ClassWriter(0);
MethodVisitor methodVisitor; MethodVisitor methodVisitor;
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSuperClassName(numberArguments), superFunNClassSignature.toString(), objectSuperType, null); classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSuperClassName(numberArguments, numReturnTypes), superFunNClassSignature.toString(), objectSuperType, null);
methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor.toString(), superFunNMethodSignature.toString(), null); methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor.toString(), superFunNMethodSignature.toString(), null);
methodVisitor.visitEnd(); methodVisitor.visitEnd();
classWriter.visitEnd(); classWriter.visitEnd();
return classWriter.toByteArray(); return classWriter.toByteArray();
} }
public static String getSuperClassName(int numberArguments) { public static String getSuperClassName(int numberArguments, int returnArguments) {
return String.format("Fun%d$$", numberArguments); return returnArguments > 0 ? String.format("Fun%d$$", numberArguments) : String.format("FunVoid%d$$", numberArguments);
} }
public static byte[] generateSpecializedBytecode(List<TargetType> argumentTypes, TargetType returnType, GenericParameters gep) { public static byte[] generateSpecializedBytecode(GenericParameters gep, List<String> superInterfaces) {
List<TargetType> parameters = Stream var argumentTypes = gep.getArguments();
.concat(argumentTypes.stream(), Stream.of(returnType)) var returnType = gep.getReturnType();
.toList();
StringBuilder funNClassSignature = new StringBuilder(objectSignature + applyDescriptor(new TargetRefType(getSuperClassName(argumentTypes.size()), parameters), gep)); StringBuilder funNClassSignature = new StringBuilder(objectSignature + gep.descriptor);
boolean containsGeneric = false; boolean containsGeneric = false;
String genericSignature = "<"; String genericSignature = "<";
@ -114,10 +150,18 @@ public class FunNGenerator {
genericSignature += ">"; genericSignature += ">";
if (containsGeneric) funNClassSignature.insert(0, genericSignature); if (containsGeneric) funNClassSignature.insert(0, genericSignature);
System.out.println(funNClassSignature.toString());
for (var superInterface : superInterfaces) {
funNClassSignature.append('L');
funNClassSignature.append(superInterface);
funNClassSignature.append(';');
}
var interfaces = new ArrayList<>(superInterfaces);
interfaces.add(getSuperClassName(argumentTypes.size(), returnType != null ? 1 : 0));
ClassWriter classWriter = new ClassWriter(0); ClassWriter classWriter = new ClassWriter(0);
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSpecializedClassName(argumentTypes, returnType), funNClassSignature.toString(), objectSuperType, new String[]{getSuperClassName(argumentTypes.size())}); classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSpecializedClassName(argumentTypes, returnType), funNClassSignature.toString(), objectSuperType, interfaces.toArray(String[]::new));
classWriter.visitEnd(); classWriter.visitEnd();
return classWriter.toByteArray(); return classWriter.toByteArray();
} }
@ -133,14 +177,24 @@ public class FunNGenerator {
} }
} }
public static String getSpecializedClassName(GenericParameters gep) {
return getSpecializedClassName(gep.getArguments(), gep.getReturnType());
}
public static String getSpecializedClassName(List<TargetType> argumentTypes, TargetType returnType) { public static String getSpecializedClassName(List<TargetType> argumentTypes, TargetType returnType) {
return String.format("Fun%d$$%s%s", var arguments = argumentTypes
.stream()
.map(FunNGenerator::encodeType)
.collect(Collectors.joining());
if (returnType != null)
return String.format("Fun%d$$%s%s",
argumentTypes.size(),
arguments,
encodeType(returnType));
else return String.format("FunVoidImpl%d$$%s",
argumentTypes.size(), argumentTypes.size(),
argumentTypes arguments);
.stream()
.map(FunNGenerator::encodeType)
.collect(Collectors.joining()),
encodeType(returnType));
} }
public static List<TargetType> getArguments(List<TargetType> list) { public static List<TargetType> getArguments(List<TargetType> list) {
@ -151,8 +205,8 @@ public class FunNGenerator {
} }
public static TargetType getReturnType(List<TargetType> list) { public static TargetType getReturnType(List<TargetType> list) {
if(list.size() == 0) if(list.isEmpty())
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
return list.get(list.size() - 1); return list.getLast();
} }
} }

View File

@ -2,6 +2,8 @@ package de.dhbwstuttgart.core;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.*; import java.util.*;
public class ConsoleInterface { public class ConsoleInterface {
private static final String directory = System.getProperty("user.dir"); private static final String directory = System.getProperty("user.dir");
@ -35,9 +37,9 @@ public class ConsoleInterface {
input.add(new File(arg)); input.add(new File(arg));
} }
} }
JavaTXCompiler compiler = new JavaTXCompiler(input, classpath); JavaTXCompiler compiler = new JavaTXCompiler(input, classpath, outputPath != null ? new File(outputPath) : null);
//compiler.typeInference(); //compiler.typeInference();
compiler.generateBytecode(outputPath); compiler.generateBytecode();
} }

View File

@ -1,7 +1,6 @@
//PL 2018-12-19: typeInferenceOld nach typeInference uebertragen //PL 2018-12-19: typeInferenceOld nach typeInference uebertragen
package de.dhbwstuttgart.core; package de.dhbwstuttgart.core;
import com.google.common.collect.Lists;
import de.dhbwstuttgart.bytecode.Codegen; import de.dhbwstuttgart.bytecode.Codegen;
import de.dhbwstuttgart.environment.CompilationEnvironment; import de.dhbwstuttgart.environment.CompilationEnvironment;
import de.dhbwstuttgart.environment.DirectoryClassLoader; import de.dhbwstuttgart.environment.DirectoryClassLoader;
@ -31,7 +30,6 @@ import de.dhbwstuttgart.syntaxtree.type.TypeVisitor;
import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter;
import de.dhbwstuttgart.target.generate.ASTToTargetAST; import de.dhbwstuttgart.target.generate.ASTToTargetAST;
import de.dhbwstuttgart.target.generate.GenericsResult; import de.dhbwstuttgart.target.generate.GenericsResult;
import de.dhbwstuttgart.target.tree.expression.TargetBinaryOp;
import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.constraints.Pair;
@ -51,13 +49,9 @@ import de.dhbwstuttgart.typeinference.unify.UnifyResultListenerImpl;
import de.dhbwstuttgart.typeinference.unify.UnifyResultModel; import de.dhbwstuttgart.typeinference.unify.UnifyResultModel;
import de.dhbwstuttgart.typeinference.unify.UnifyTaskModel; import de.dhbwstuttgart.typeinference.unify.UnifyTaskModel;
import java.io.File; import java.io.*;
import java.io.FileOutputStream; import java.lang.reflect.Modifier;
import java.io.FileWriter; import java.nio.file.Path;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.Array;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.function.Function; import java.util.function.Function;
@ -74,16 +68,17 @@ public class JavaTXCompiler {
Boolean log = false; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll? Boolean log = false; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll?
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel(); public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
private final DirectoryClassLoader classLoader; public final DirectoryClassLoader classLoader;
private final List<File> classPath; public final List<File> classPath;
private final File outputPath;
public DirectoryClassLoader getClassLoader() { public DirectoryClassLoader getClassLoader() {
return classLoader; return classLoader;
} }
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException { public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
this(Arrays.asList(sourceFile), null); this(Arrays.asList(sourceFile), List.of(), new File("."));
} }
public JavaTXCompiler(File sourceFile, Boolean log) throws IOException, ClassNotFoundException { public JavaTXCompiler(File sourceFile, Boolean log) throws IOException, ClassNotFoundException {
@ -92,17 +87,20 @@ public class JavaTXCompiler {
} }
public JavaTXCompiler(List<File> sourceFiles) throws IOException, ClassNotFoundException { public JavaTXCompiler(List<File> sourceFiles) throws IOException, ClassNotFoundException {
this(sourceFiles, null); this(sourceFiles, List.of(), new File("."));
} }
public JavaTXCompiler(List<File> sources, List<File> contextPath) throws IOException, ClassNotFoundException { public JavaTXCompiler(List<File> sources, List<File> contextPath, File outputPath) throws IOException, ClassNotFoundException {
if (contextPath == null || contextPath.isEmpty()) { var path = new ArrayList<>(contextPath);
if (contextPath.isEmpty()) {
// When no contextPaths are given, the working directory is the sources root // When no contextPaths are given, the working directory is the sources root
contextPath = Lists.newArrayList(new File(System.getProperty("user.dir"))); path.add(new File(System.getProperty("user.dir")));
} }
classLoader = new DirectoryClassLoader(contextPath, ClassLoader.getSystemClassLoader()); if (outputPath != null) path.add(outputPath);
environment = new CompilationEnvironment(sources); classLoader = new DirectoryClassLoader(path, ClassLoader.getSystemClassLoader());
classPath = contextPath; environment = new CompilationEnvironment(sources, classLoader);
classPath = path;
this.outputPath = outputPath;
for (File s : sources) { for (File s : sources) {
parse(s); parse(s);
@ -115,6 +113,7 @@ public class JavaTXCompiler {
} }
public ClassOrInterface getClass(JavaClassName name) { public ClassOrInterface getClass(JavaClassName name) {
if (loadedClasses.containsKey(name)) return loadedClasses.get(name).cif();
for (var sf : sourceFiles.values()) { for (var sf : sourceFiles.values()) {
for (var clazz : sf.KlassenVektor) { for (var clazz : sf.KlassenVektor) {
if (clazz.getClassName().equals(name)) return clazz; if (clazz.getClassName().equals(name)) return clazz;
@ -128,32 +127,48 @@ public class JavaTXCompiler {
return null; return null;
} }
public ConstraintSet<Pair> getConstraints() throws ClassNotFoundException, IOException { public ConstraintSet<Pair> getConstraints(File sourceFile) throws ClassNotFoundException, IOException {
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses(); Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
ClassOrInterface objectClass = ASTFactory.createClass(classLoader.loadClass(new JavaClassName("java.lang.Object").toString())); ClassOrInterface objectClass = ASTFactory.createClass(Object.class);
// Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC var recordClass = ASTFactory.createClass(Record.class);
for (Entry<File, SourceFile> source : sourceFiles.entrySet()) { allClasses.add(objectClass);
var importedClasses = new ArrayList<ClassOrInterface>(); allClasses.add(recordClass);
for (JavaClassName name : source.getValue().getImports()) {
importedClasses.addAll(getAvailableClasses(name)); var sf = sourceFiles.get(sourceFile);
} var importedClasses = new ArrayList<ClassOrInterface>();
for (Class c : CompilationEnvironment.loadDefaultPackageClasses(source.getValue().getPkgName(), source.getKey(), this)) { for (JavaClassName name : sf.getImports()) {
ClassOrInterface importedClass = ASTFactory.createClass(c); importedClasses.addAll(getAvailableClasses(name));
importedClasses.add(importedClass);
}
source.getValue().availableClasses.addAll(importedClasses);
} }
for (File f : this.sourceFiles.keySet()) { for (Class c : CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), sourceFile, this)) {
SourceFile sf = sourceFiles.get(f); ClassOrInterface importedClass = ASTFactory.createClass(c);
SourceFile sf_new = new SourceFile(sf.getPkgName(), sf.KlassenVektor.stream().map(cl -> new ClassOrInterface(cl)).collect(Collectors.toCollection(ArrayList::new)), sf.imports); importedClasses.add(importedClass);
// sf enthaelt neues Source-File, neue Klassen-Objekte und neue }
// ArrayListen-Objekte fuer Fields, Construktoren und Methoden sf.availableClasses.addAll(importedClasses);
// Alle anderen Objekte werden nur kopiert.
SourceFile sf_new = new SourceFile(sf.getPkgName(), sf.KlassenVektor.stream().map(cl -> new ClassOrInterface(cl)).collect(Collectors.toCollection(ArrayList::new)), sf.imports);
// sf enthaelt neues Source-File, neue Klassen-Objekte und neue
// ArrayListen-Objekte fuer Fields, Construktoren und Methoden
// Alle anderen Objekte werden nur kopiert.
var isCached = false;
for (var clazz : sf.availableClasses) {
if (loadedClasses.containsKey(clazz.getClassName())) {
allClasses.removeIf(cl -> cl.getClassName().equals(clazz.getClassName()));
var cif = loadedClasses.get(clazz.getClassName()).cif();
allClasses.add(cif);
isCached = true;
}
}
if (!isCached) {
sf_new.KlassenVektor.forEach(cl -> addMethods(sf_new, cl, sf.availableClasses, objectClass)); sf_new.KlassenVektor.forEach(cl -> addMethods(sf_new, cl, sf.availableClasses, objectClass));
allClasses.addAll(sf_new.getClasses()); allClasses.addAll(sf_new.getClasses());
} }
TYPE ty = new TYPE(sourceFiles.values(), allClasses);
return ty.getConstraints(); allClasses.addAll(sf.KlassenVektor);
TYPE ty = new TYPE(sf, allClasses);
var constraints = ty.getConstraints();
return constraints;
} }
void addMethods(SourceFile sf, ClassOrInterface cl, List<ClassOrInterface> importedClasses, ClassOrInterface objectClass) { void addMethods(SourceFile sf, ClassOrInterface cl, List<ClassOrInterface> importedClasses, ClassOrInterface objectClass) {
@ -183,36 +198,35 @@ public class JavaTXCompiler {
while (paraIt.hasNext()) { while (paraIt.hasNext()) {
gtvs.put(tvarVarIt.next().getName(), paraIt.next()); gtvs.put(tvarVarIt.next().getName(), paraIt.next());
} }
Iterator<Method> methodIt = superclass.getMethods().iterator();
// TODO: PL 2020-05-06: Hier müssen ueberschriebene Methoden noch rausgefiltert for (Method m : superclass.getMethods()) {
// werden if (m.isInherited || Modifier.isStatic(m.modifier)) continue;
while (methodIt.hasNext()) { // TODO: Add gtvs from method itself
Method m = methodIt.next();
ParameterList newParaList = new ParameterList(m.getParameterList().getFormalparalist().stream().map(fp -> fp.withType(fp.getType().acceptTV(new TypeExchanger(gtvs)))).collect(Collectors.toCollection(ArrayList::new)), m.getParameterList().getOffset()); ParameterList newParaList = new ParameterList(m.getParameterList().getFormalparalist().stream().map(fp -> fp.withType(fp.getType().acceptTV(new TypeExchanger(gtvs)))).collect(Collectors.toCollection(ArrayList::new)), m.getParameterList().getOffset());
cl.getMethods().add(new Method(m.modifier, m.name, m.getReturnType().acceptTV(new TypeExchanger(gtvs)), newParaList, m.block, cl.getMethods().add(new Method(m.modifier, m.name, m.getReturnType().acceptTV(new TypeExchanger(gtvs)), newParaList, m.block,
// new GenericDeclarationList(newGenericsList, // new GenericDeclarationList(newGenericsList,
// ((GenericDeclarationList)m.getGenerics()).getOffset()), // ((GenericDeclarationList)m.getGenerics()).getOffset()),
(GenericDeclarationList) m.getGenerics(), m.getOffset(), true)); (GenericDeclarationList) m.getGenerics(), m.getOffset(), true, false));
} }
} }
cl.setMethodsAdded(); cl.setMethodsAdded();
} }
private List<ClassOrInterface> getAvailableClasses(JavaClassName name) throws ClassNotFoundException { private Set<ClassOrInterface> getAvailableClasses(JavaClassName name) throws ClassNotFoundException {
Set<ClassOrInterface> allClasses = new HashSet<>(); Set<ClassOrInterface> allClasses = new HashSet<>();
if (loadJavaTXClass(name)) { var clazz = loadJavaTXClass(name);
var file = findFileForClass(name); if (clazz == null) {
var sf = sourceFiles.get(file);
if (sf != null) allClasses.addAll(sf.KlassenVektor);
} else {
ClassOrInterface importedClass = ASTFactory.createClass(classLoader.loadClass(name.toString())); ClassOrInterface importedClass = ASTFactory.createClass(classLoader.loadClass(name.toString()));
allClasses.add(importedClass); allClasses.add(importedClass);
} else {
allClasses.add(clazz);
} }
return new ArrayList<>(allClasses); return allClasses;
} }
public List<ClassOrInterface> getAvailableClasses(SourceFile forSourceFile) throws ClassNotFoundException { public Set<ClassOrInterface> getAvailableClasses(SourceFile forSourceFile) throws ClassNotFoundException {
// PL 2018-09-18: List durch Set ersetzt, damit die Klassen nur einmal // PL 2018-09-18: List durch Set ersetzt, damit die Klassen nur einmal
// hinzugefuegt werden // hinzugefuegt werden
// List<ClassOrInterface> allClasses = new // List<ClassOrInterface> allClasses = new
@ -222,7 +236,7 @@ public class JavaTXCompiler {
for (JavaClassName name : forSourceFile.getImports()) { for (JavaClassName name : forSourceFile.getImports()) {
allClasses.addAll(getAvailableClasses(name)); allClasses.addAll(getAvailableClasses(name));
} }
return new ArrayList<>(allClasses); return allClasses;
} }
/* /*
@ -278,17 +292,21 @@ public class JavaTXCompiler {
allClasses.addAll(CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), this).stream().map(ASTFactory::createClass).collect(Collectors.toList())); allClasses.addAll(CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), this).stream().map(ASTFactory::createClass).collect(Collectors.toList()));
} }
final ConstraintSet<Pair> cons = getConstraints(); final ConstraintSet<Pair> cons = new ConstraintSet<>();
for (var f : this.sourceFiles.keySet()) {
cons.addAll(getConstraints(f));
}
Set<Set<UnifyPair>> results = new HashSet<>(); Set<Set<UnifyPair>> results = new HashSet<>();
UnifyResultModel urm = null; UnifyResultModel urm = null;
// urm.addUnifyResultListener(resultListener); // urm.addUnifyResultListener(resultListener);
try { try {
logFile = logFile == null ? new FileWriter(new File("log_" + sourceFiles.keySet().iterator().next().getName())) : logFile; logFile = logFile == null ? new FileWriter(new File("log_" + sourceFiles.keySet().iterator().next().getName())) : logFile;
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, getClassLoader()); IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, getClassLoader(), this);
System.out.println(finiteClosure); System.out.println(finiteClosure);
urm = new UnifyResultModel(cons, finiteClosure); urm = new UnifyResultModel(cons, finiteClosure);
urm.addUnifyResultListener(resultListener); urm.addUnifyResultListener(resultListener);
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(cons); ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons);
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> { Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
UnifyType lhs, rhs; UnifyType lhs, rhs;
@ -305,8 +323,8 @@ public class JavaTXCompiler {
TypeUnify unify = new TypeUnify(); TypeUnify unify = new TypeUnify();
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen // Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
logFile.write("FC:\\" + finiteClosure.toString() + "\n"); logFile.write("FC:\\" + finiteClosure.toString() + "\n");
for (SourceFile sf : this.sourceFiles.values()) { for (SourceFile f : this.sourceFiles.values()) {
logFile.write(ASTTypePrinter.print(sf)); logFile.write(ASTTypePrinter.print(f));
} }
logFile.flush(); logFile.flush();
@ -399,32 +417,29 @@ public class JavaTXCompiler {
return urm; return urm;
} }
public List<ResultSet> typeInference() throws ClassNotFoundException, IOException { public List<ResultSet> typeInference(File file) throws ClassNotFoundException, IOException {
List<ClassOrInterface> allClasses = new ArrayList<>();// environment.getAllAvailableClasses(); var sf = sourceFiles.get(file);
// Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
for (Entry<File, SourceFile> source : this.sourceFiles.entrySet()) { allClasses.addAll(getAvailableClasses(sf));
SourceFile sf = source.getValue(); allClasses.addAll(sf.getClasses());
allClasses.addAll(getAvailableClasses(sf)); var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), file, this).stream().map(ASTFactory::createClass).collect(Collectors.toSet());
allClasses.addAll(sf.getClasses()); for (var clazz : newClasses) {
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), this).stream().map(ASTFactory::createClass).collect(Collectors.toList()); // Don't load classes that get recompiled
for (var clazz : newClasses) { if (sf.getClasses().stream().anyMatch(nf -> nf.getClassName().equals(clazz.getClassName())))
// Don't load classes that get recompiled continue;
if (sf.getClasses().stream().anyMatch(nf -> nf.getClassName().equals(clazz.getClassName()))) if (allClasses.stream().noneMatch(old -> old.getClassName().equals(clazz.getClassName())))
continue; allClasses.add(clazz);
if (allClasses.stream().noneMatch(old -> old.getClassName().equals(clazz.getClassName())))
allClasses.add(clazz);
}
} }
final ConstraintSet<Pair> cons = getConstraints(); final ConstraintSet<Pair> cons = getConstraints(file);
Set<Set<UnifyPair>> results = new HashSet<>(); Set<Set<UnifyPair>> results = new HashSet<>();
try { try {
var logFolder = new File(System.getProperty("user.dir") + "/logFiles/"); var logFolder = new File(System.getProperty("user.dir") + "/logFiles/");
if (log) logFolder.mkdirs(); if (log) logFolder.mkdirs();
Writer logFile = log ? new FileWriter(new File(logFolder, "log_" + sourceFiles.keySet().iterator().next().getName())) : new OutputStreamWriter(new NullOutputStream()); Writer logFile = log ? new FileWriter(new File(logFolder, "log_" + sourceFiles.keySet().iterator().next().getName())) : new OutputStreamWriter(new NullOutputStream());
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, classLoader); IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses.stream().toList(), logFile, classLoader, this);
System.out.println(finiteClosure); System.out.println(finiteClosure);
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(cons); ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons);
System.out.println("xxx1"); System.out.println("xxx1");
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> { Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
UnifyType lhs, rhs; UnifyType lhs, rhs;
@ -443,10 +458,8 @@ public class JavaTXCompiler {
TypeUnify unify = new TypeUnify(); TypeUnify unify = new TypeUnify();
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen // Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
logFile.write("FC:\\" + finiteClosure.toString() + "\n"); logFile.write("FC:\\" + finiteClosure.toString() + "\n");
for (SourceFile sf : this.sourceFiles.values()) { logFile.write(ASTTypePrinter.print(sf));
logFile.write(ASTTypePrinter.print(sf)); System.out.println(ASTTypePrinter.print(sf));
System.out.println(ASTTypePrinter.print(sf));
}
logFile.flush(); logFile.flush();
Set<String> methodParaTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist().stream().filter(z -> z.getType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce(new HashSet<String>(), (a, b) -> { Set<String> methodParaTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist().stream().filter(z -> z.getType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce(new HashSet<String>(), (a, b) -> {
@ -648,14 +661,20 @@ public class JavaTXCompiler {
public final JavaClassRegistry classRegistry = new JavaClassRegistry(); public final JavaClassRegistry classRegistry = new JavaClassRegistry();
public record ClassEntry(File classFile, ClassOrInterface cif) {}
public final Map<JavaClassName, ClassEntry> loadedClasses = new HashMap<>();
private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException { private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException {
if (sourceFiles.containsKey(sourceFile)) return sourceFiles.get(sourceFile);
SourceFileContext tree = JavaTXParser.parse(sourceFile); SourceFileContext tree = JavaTXParser.parse(sourceFile);
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this); environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), sourceFile.getName()); SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), sourceFile.getName());
var classes = new ArrayList<ClassOrInterface>(); var classes = new ArrayList<ClassOrInterface>();
var sf = new SourceFile(generator.pkgName, classes, generator.imports); var sf = new SourceFile("", classes, generator.imports);
addSourceFile(sourceFile, sf); addSourceFile(sourceFile, sf);
generator.convert(classes, tree, environment.packageCrawler); generator.convert(classes, tree, environment.packageCrawler);
sf.setPackageName(generator.pkgName);
sf.imports.addAll(generator.imports); sf.imports.addAll(generator.imports);
return sf; return sf;
} }
@ -665,25 +684,33 @@ public class JavaTXCompiler {
* if it doesn't exist it's going to compile it and add it to the source files list * if it doesn't exist it's going to compile it and add it to the source files list
* @param name * @param name
*/ */
public boolean loadJavaTXClass(JavaClassName name) { public ClassOrInterface loadJavaTXClass(JavaClassName name) {
var file = findFileForClass(name); var file = findFileForClass(name);
if (file != null) { if (file != null) {
if (classRegistry.contains(name)) return true; if (loadedClasses.containsKey(name)) return loadedClasses.get(name).cif();
try { try {
var tree = JavaTXParser.parse(file); var tree = JavaTXParser.parse(file);
classRegistry.addName(name.toString(), 0); // TODO This gets overwritten later, is it bad if we don't know this right away? classRegistry.addName(name.toString(), 0); // TODO This gets overwritten later, is it bad if we don't know this right away?
environment.addClassesToRegistry(classRegistry, tree, file, this); environment.addClassesToRegistry(classRegistry, tree, file, this);
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), file.getName()); SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), file.getName());
var classes = new ArrayList<ClassOrInterface>(); var classes = new ArrayList<ClassOrInterface>();
var sf = new SourceFile(generator.pkgName, classes, generator.imports); var sf = new SourceFile("", classes, generator.imports);
addSourceFile(file, sf); addSourceFile(file, sf);
generator.convert(classes, tree, environment.packageCrawler); generator.convert(classes, tree, environment.packageCrawler);
return true; sf.setPackageName(generator.pkgName);
var classFiles = generateBytecode(file);
sf.setGenerated();
writeClassFile(classFiles, outputPath != null ? outputPath : new File("."), false);
var clazz = classLoader.loadClass(name.toString());
var classOrInterface = ASTFactory.createClass(clazz);
loadedClasses.put(name, new ClassEntry(new File(outputPath, clazz.getName() + ".class"), classOrInterface));
return classOrInterface;
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
return false; return null;
} }
public File findFileForClass(JavaClassName name) { public File findFileForClass(JavaClassName name) {
@ -697,25 +724,26 @@ public class JavaTXCompiler {
} }
public void generateBytecode() throws ClassNotFoundException, IOException { public void generateBytecode() throws ClassNotFoundException, IOException {
generateBytecode((File) null); for (var file : sourceFiles.keySet()) {
} var sf = sourceFiles.get(file);
if (sf.isGenerated()) continue;
/** var classes = generateBytecode(file);
* @param path - can be null, then class file output is in the same directory as the parsed source files sf.setGenerated();
*/ writeClassFile(classes, outputPath == null ? file.getParentFile() : outputPath, outputPath == null);
public void generateBytecode(String path) throws ClassNotFoundException, IOException { }
if (path != null)
generateBytecode(new File(path));
else
generateBytecode();
} }
/** /**
* @param path - output-Directory can be null, then class file output is in the same directory as the parsed source files * @param path - output-Directory can be null, then class file output is in the same directory as the parsed source files
* @return
*/ */
public void generateBytecode(File path) throws ClassNotFoundException, IOException { public Map<JavaClassName, byte[]> generateBytecode(File sourceFile) throws ClassNotFoundException, IOException {
List<ResultSet> typeinferenceResult = this.typeInference(); var sf = sourceFiles.get(sourceFile);
generateBytecode(path, typeinferenceResult); if (sf.isGenerated()) return null;
List<ResultSet> typeinferenceResult = this.typeInference(sourceFile);
var classes = generateBytecode(sf, typeinferenceResult);
sf.setGenerated();
return classes;
} }
private Map<SourceFile, List<GenericsResult>> generatedGenerics = new HashMap<>(); private Map<SourceFile, List<GenericsResult>> generatedGenerics = new HashMap<>();
@ -733,15 +761,13 @@ public class JavaTXCompiler {
for (File f : sourceFiles.keySet()) { for (File f : sourceFiles.keySet()) {
HashMap<JavaClassName, byte[]> classFiles = new HashMap<>(); HashMap<JavaClassName, byte[]> classFiles = new HashMap<>();
SourceFile sf = sourceFiles.get(f); SourceFile sf = sourceFiles.get(f);
File path; File path = outputPath;
if (outputPath == null) { if (outputPath == null) {
path = f.getParentFile(); // Set path to path of the parsed .jav file path = f.getParentFile(); // Set path to path of the parsed .jav file
} else {
path = new File(outputPath, sf.getPkgName().replace(".", "/")); // add package path to root path
} }
var generatedClasses = generateBytecode(sf, typeinferenceResult); var generatedClasses = generateBytecode(sf, typeinferenceResult);
writeClassFile(generatedClasses, path); writeClassFile(generatedClasses, path, outputPath == null);
} }
} }
@ -749,7 +775,7 @@ public class JavaTXCompiler {
var converter = new ASTToTargetAST(this, typeInferenceResult, sf, classLoader); var converter = new ASTToTargetAST(this, typeInferenceResult, sf, classLoader);
var generatedClasses = new HashMap<JavaClassName, byte[]>(); var generatedClasses = new HashMap<JavaClassName, byte[]>();
for (var clazz : sf.getClasses()) { for (var clazz : sf.getClasses()) {
var codegen = new Codegen(converter.convert(clazz), this); var codegen = new Codegen(converter.convert(clazz), this, converter);
var code = codegen.generate(); var code = codegen.generate();
generatedClasses.put(clazz.getClassName(), code); generatedClasses.put(clazz.getClassName(), code);
converter.auxiliaries.forEach((name, source) -> { converter.auxiliaries.forEach((name, source) -> {
@ -757,18 +783,19 @@ public class JavaTXCompiler {
}); });
} }
generatedGenerics.put(sf, converter.javaGenerics()); generatedGenerics.put(sf, converter.javaGenerics());
converter.generateFunNTypes();
return generatedClasses; return generatedClasses;
} }
public synchronized void writeClassFile(Map<JavaClassName, byte[]> classFiles, File path) throws IOException { public synchronized void writeClassFile(Map<JavaClassName, byte[]> classFiles, File path, boolean preserveHierarchy) throws IOException {
FileOutputStream output; FileOutputStream output;
for (JavaClassName name : classFiles.keySet()) { for (JavaClassName name : classFiles.keySet()) {
byte[] bytecode = classFiles.get(name); byte[] bytecode = classFiles.get(name);
System.out.println("generating " + name + ".class file ..."); System.out.println("generating " + name + ".class file ...");
// output = new FileOutputStream(new File(System.getProperty("user.dir") + var subPath = preserveHierarchy ? path : Path.of(path.toString(), name.getPackageName().split("\\.")).toFile();
// "/testBytecode/generatedBC/" +name+".class")); File outputFile = new File(subPath, name.getClassName() + ".class");
File outputFile = new File(path, name.getClassName() + ".class");
outputFile.getAbsoluteFile().getParentFile().mkdirs(); outputFile.getAbsoluteFile().getParentFile().mkdirs();
System.out.println(outputFile);
output = new FileOutputStream(outputFile); output = new FileOutputStream(outputFile);
output.write(bytecode); output.write(bytecode);
output.close(); output.close();

View File

@ -34,7 +34,7 @@ public class CompilationEnvironment {
* *
* @param sourceFiles die zu kompilierenden Dateien * @param sourceFiles die zu kompilierenden Dateien
*/ */
public CompilationEnvironment(List<File> sourceFiles) { public CompilationEnvironment(List<File> sourceFiles, DirectoryClassLoader classLoader) {
/** /**
* Java 9 bringt einige Änderungen am Classloader So funktioniert der BootClassLoader nicht mehr. hier gibts ein paar Quellen zum nachlesen: http://java9.wtf/class-loading/ https://stackoverflow.com/questions/46494112/classloaders-hierarchy-in-java-9 * Java 9 bringt einige Änderungen am Classloader So funktioniert der BootClassLoader nicht mehr. hier gibts ein paar Quellen zum nachlesen: http://java9.wtf/class-loading/ https://stackoverflow.com/questions/46494112/classloaders-hierarchy-in-java-9
* *
@ -54,7 +54,7 @@ public class CompilationEnvironment {
// librarys = Arrays.asList(loader.getURLs()); // librarys = Arrays.asList(loader.getURLs());
this.sourceFiles = sourceFiles; this.sourceFiles = sourceFiles;
this.packageCrawler = new PackageCrawler(librarys); this.packageCrawler = new PackageCrawler(classLoader);
} }
public void addClassesToRegistry(JavaClassRegistry registry, SourceFileContext tree, File sourceFile, JavaTXCompiler compiler) throws ClassNotFoundException, IOException { public void addClassesToRegistry(JavaClassRegistry registry, SourceFileContext tree, File sourceFile, JavaTXCompiler compiler) throws ClassNotFoundException, IOException {
@ -77,7 +77,7 @@ public class CompilationEnvironment {
// Set classLoader to include default package for this specific source file // Set classLoader to include default package for this specific source file
File dir = sourceFile.getAbsoluteFile().getParentFile(); File dir = sourceFile.getAbsoluteFile().getParentFile();
String dirPath = dir.toString() + "/"; String dirPath = dir.toString() + "/";
if (packageName.length() > 0) if (!packageName.isEmpty())
dirPath = dirPath.substring(0, dirPath.length() - packageName.length() - 1); dirPath = dirPath.substring(0, dirPath.length() - packageName.length() - 1);
String path = dirPath; String path = dirPath;
ArrayList<File> defaultPath = Lists.newArrayList(new File(path)); ArrayList<File> defaultPath = Lists.newArrayList(new File(path));
@ -89,7 +89,10 @@ public class CompilationEnvironment {
String className = classFile.getName().substring(0, classFile.getName().length() - 6); String className = classFile.getName().substring(0, classFile.getName().length() - 6);
if (className.matches("Fun\\d+\\$\\$.*")) if (className.matches("Fun\\d+\\$\\$.*"))
continue; continue;
ret.add(classLoader.loadClass(packageName + className)); var name = packageName;
if (!packageName.isEmpty()) name += ".";
name += className;
ret.add(classLoader.loadClass(name));
} }
return ret; return ret;
} }
@ -101,12 +104,4 @@ public class CompilationEnvironment {
return packageName; return packageName;
} }
public List<ClassOrInterface> getAllAvailableClasses() {
List<ClassOrInterface> ret = new ArrayList<>();
for (Class c : new PackageCrawler(librarys).getAllAvailableClasses()) {
ret.add(ASTFactory.createClass(c));
}
return ret;
}
} }

View File

@ -5,31 +5,61 @@ import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.nio.file.Files; import java.nio.file.*;
import java.nio.file.Path; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class DirectoryClassLoader extends URLClassLoader implements IByteArrayClassLoader { public class DirectoryClassLoader extends URLClassLoader implements IByteArrayClassLoader {
public DirectoryClassLoader(File directory, java.lang.ClassLoader parent) { // public DirectoryClassLoader(File directory, java.lang.ClassLoader parent) {
super(generateURLArray(dirToURL(directory)), parent); // super(generateURLArray(dirToURL(directory)), parent);
} // }
public DirectoryClassLoader(List<File> directory, java.lang.ClassLoader parent) { public DirectoryClassLoader(List<File> directory, java.lang.ClassLoader parent) {
super(directory.stream().map(DirectoryClassLoader::dirToURL).collect(Collectors.toList()).toArray(new URL[0]), parent); super(directory.stream().map(DirectoryClassLoader::dirToURL).flatMap(List::stream).collect(Collectors.toList()).toArray(new URL[0]), parent.getParent());
} }
private static URL[] generateURLArray(URL url) { private static URL[] generateURLArray(URL url) {
return new URL[]{url}; return new URL[]{url};
} }
private static URL dirToURL(File url){ private static List<URL> dirToURL(File file) {
if(!url.isDirectory())throw new RuntimeException(url.toString() + " is not a directory"); //if(!url.isDirectory())throw new RuntimeException(url.toString() + " is not a directory");
try {
return url.toURI().toURL(); Path dir;
} catch (MalformedURLException e) { if (file.isDirectory()) {
throw new RuntimeException(e); try {
return List.of(file.toURI().toURL()); // if file is a directory, use it as is
} catch (MalformedURLException e) {
e.printStackTrace();
return List.of();
}
} }
dir = file.toPath().getParent(); // if file is not a directory, get its parent directory
String pattern = file.toPath().getFileName().toString(); // use the file name as a glob pattern
List<URL> urls = new ArrayList<>();
try {
urls = Files.walk(dir)
.filter(Files::isRegularFile) // only consider files (not directories)
.filter(path -> {
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
return matcher.matches(path.getFileName()); // match the file name against the pattern
})
.map(path -> {
try {
return path.toUri().toURL();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}) // convert the path to a URL
.toList(); // print the path of each matching file
} catch (IOException | RuntimeException e) {
e.printStackTrace();
}
return urls;
} }
@Override @Override
@ -41,4 +71,8 @@ public class DirectoryClassLoader extends URLClassLoader implements IByteArrayCl
public Class<?> findClass(String name) throws ClassNotFoundException { public Class<?> findClass(String name) throws ClassNotFoundException {
return super.findClass(name); return super.findClass(name);
} }
public Class<?> _findLoadedClass(String name) throws ClassNotFoundException {
return super.findLoadedClass(name);
}
} }

View File

@ -1,17 +1,10 @@
package de.dhbwstuttgart.environment; package de.dhbwstuttgart.environment;
import java.net.URL; import io.github.classgraph.ClassGraph;
import io.github.classgraph.ScanResult;
import java.util.*; import java.util.*;
import org.reflections.Reflections;
import org.reflections.scanners.ResourcesScanner;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import org.reflections.vfs.SystemDir;
/** /**
* Hilft beim Durchsuchen von Packages * Hilft beim Durchsuchen von Packages
* Benutzt die Reflections-Library (https://github.com/ronmamo/reflections) * Benutzt die Reflections-Library (https://github.com/ronmamo/reflections)
@ -19,48 +12,30 @@ import org.reflections.vfs.SystemDir;
*/ */
public class PackageCrawler { public class PackageCrawler {
final URL[] urls; final DirectoryClassLoader classLoader;
public PackageCrawler(List<URL> urlList) { public PackageCrawler(DirectoryClassLoader classLoader) {
urls = urlList.toArray(new URL[0]); this.classLoader = classLoader;
} }
public Set<Class<?>> getClassesInPackage(String packageName){ public Set<Class<?>> getClassesInPackage(String packageName) {
/* var res = new HashSet<Class<?>>();
List<DirectoryClassLoader> classLoadersList = new LinkedList<DirectoryClassLoader>();
classLoadersList.add(Thread.currentThread().getContextClassLoader());
classLoadersList.add(ClasspathHelper.staticClassLoader());
classLoadersList.add(Thread.currentThread().getContextClassLoader().getParent());
classLoadersList.add(DirectoryClassLoader.getSystemClassLoader());
String bootClassPath = System.getProperty("sun.boot.class.path");
ArrayList<URL> urlList = new ArrayList<>();
for(String path : bootClassPath.split(";")) {
try {
urlList.add(new URL("file:"+path));
} catch (MalformedURLException e) {
new DebugException("Fehler im Classpath auf diesem System");
}
}
URL[] urls = urlList.toArray(new URL[0]);
classLoadersList.add(new URLClassLoader(urls, DirectoryClassLoader.getSystemClassLoader()));
*/
Reflections reflections = new Reflections(new ConfigurationBuilder()
.setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner())
.setUrls(urls)
.filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix(packageName))));
Set<Class<?>> classes = reflections.getSubTypesOf(Object.class); try (ScanResult result = new ClassGraph()
.enableClassInfo()
.enableSystemJarsAndModules()
.addClassLoader(classLoader)
.acceptPackages(packageName)
.scan()) {
return classes; for (var info : result.getAllClasses()) {
} try {
var clazz = Class.forName(info.getName());
res.add(clazz);
} catch (ClassNotFoundException ignored) {}
}
};
public Set<Class<?>> getAllAvailableClasses(){ return res;
Reflections reflections = new Reflections(new ConfigurationBuilder()
.setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner())
.setUrls(urls));
Set<Class<?>> classes = reflections.getSubTypesOf(Object.class);
return classes;
} }
public Map<String, Integer> getClassNames(String packageName){ public Map<String, Integer> getClassNames(String packageName){

View File

@ -1,5 +1,6 @@
package de.dhbwstuttgart.parser.SyntaxTreeGenerator; package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.exceptions.DebugException; import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassName;
@ -25,8 +26,8 @@ public class FCGenerator {
* *
* @param availableClasses - Alle geparsten Klassen * @param availableClasses - Alle geparsten Klassen
*/ */
public static Set<UnifyPair> toUnifyFC(Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException { public static Set<UnifyPair> toUnifyFC(JavaTXCompiler compiler, Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException {
return toFC(availableClasses, classLoader).stream().map(t -> UnifyTypeFactory.convert(t)).collect(Collectors.toSet()); return toFC(availableClasses, classLoader).stream().map(t -> UnifyTypeFactory.convert(compiler, t)).collect(Collectors.toSet());
} }
public static Set<Pair> toFC(Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException { public static Set<Pair> toFC(Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException {
@ -157,7 +158,8 @@ public class FCGenerator {
} }
/** /**
* Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus. * Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus auf der direkten Argumentebene.
* Hier sind keine Wildcards zulässig
*/ */
private static class TypeExchanger implements TypeVisitor<RefTypeOrTPHOrWildcardOrGeneric>{ private static class TypeExchanger implements TypeVisitor<RefTypeOrTPHOrWildcardOrGeneric>{
@ -171,7 +173,7 @@ public class FCGenerator {
public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) { public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>(); List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){ for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){
params.add(param.acceptTV(this)); params.add(param.acceptTV(new TypeExchangerInner(gtvs)));
} }
RefTypeOrTPHOrWildcardOrGeneric ret = new RefType(refType.getName(), params, new NullToken()); RefTypeOrTPHOrWildcardOrGeneric ret = new RefType(refType.getName(), params, new NullToken());
return ret; return ret;
@ -200,4 +202,51 @@ public class FCGenerator {
} }
} }
/**
* Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus auf den Argumenten der Argumente.
* Hier sind Wildcards zulässig
*/
private static class TypeExchangerInner implements TypeVisitor<RefTypeOrTPHOrWildcardOrGeneric>{
private final HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs;
TypeExchangerInner(HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs){
this.gtvs = gtvs;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){
params.add(param.acceptTV(this));
}
RefTypeOrTPHOrWildcardOrGeneric ret = new RefType(refType.getName(), params, new NullToken());
return ret;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(SuperWildcardType superWildcardType) {
return superWildcardType;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(TypePlaceholder typePlaceholder) {
throw new DebugException("Dieser Fall darf nicht auftreten");
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(ExtendsWildcardType extendsWildcardType) {
return extendsWildcardType;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(GenericRefType genericRefType) {
if(! gtvs.containsKey(genericRefType.getParsedName()))
throw new DebugException("Dieser Fall darf nicht auftreten");
return gtvs.get(genericRefType.getParsedName());
}
}
} }

View File

@ -279,7 +279,8 @@ public class StatementGenerator {
if (!Objects.isNull(creator.classCreatorRest())) { if (!Objects.isNull(creator.classCreatorRest())) {
ArgumentList args = convertArguments(creator.classCreatorRest().arguments().expressionList()); ArgumentList args = convertArguments(creator.classCreatorRest().arguments().expressionList());
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes = args.getArguments().stream().map(x -> TypePlaceholder.fresh(creator.getStart())).collect(Collectors.toCollection(ArrayList::new)); ArrayList<TypePlaceholder> argTypes = args.getArguments().stream().map(x -> TypePlaceholder.fresh(creator.getStart())).collect(Collectors.toCollection(ArrayList::new));
argTypes.add(TypePlaceholder.fresh(creator.getStart())); // return type
Statement ret = new NewClass(newclass, args, null, argTypes, creator.getStart()); Statement ret = new NewClass(newclass, args, null, argTypes, creator.getStart());
ret.setStatement(); ret.setStatement();
return ret; return ret;
@ -310,7 +311,7 @@ public class StatementGenerator {
IdentifierContext identifier = innercreator.identifier(); IdentifierContext identifier = innercreator.identifier();
RefType newclass = (RefType) TypeGenerator.convertTypeName(identifier.getText(), genericArgs, identifier.getStart(), reg, generics); RefType newclass = (RefType) TypeGenerator.convertTypeName(identifier.getText(), genericArgs, identifier.getStart(), reg, generics);
ArgumentList args = convertArguments(innercreator.classCreatorRest().arguments().expressionList()); ArgumentList args = convertArguments(innercreator.classCreatorRest().arguments().expressionList());
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes = args.getArguments().stream().map(x -> TypePlaceholder.fresh(innercreator.getStart())).collect(Collectors.toCollection(ArrayList::new)); ArrayList<TypePlaceholder> argTypes = args.getArguments().stream().map(x -> TypePlaceholder.fresh(innercreator.getStart())).collect(Collectors.toCollection(ArrayList::new));
Statement ret = new NewClass(newclass, args, null, argTypes, innercreator.getStart()); Statement ret = new NewClass(newclass, args, null, argTypes, innercreator.getStart());
ret.setStatement(); ret.setStatement();
return ret; return ret;
@ -596,8 +597,12 @@ public class StatementGenerator {
} }
private Statement convert(Java17Parser.ContinuestmtContext stmt) { private Statement convert(Java17Parser.ContinuestmtContext stmt) {
// TODO Token offset = stmt.getStart();
throw new NotImplementedException(); if (!Objects.isNull(stmt.identifier())) {
return new Continue(localVars.get(stmt.identifier().getText()), offset);
} else {
return new Continue(TypePlaceholder.fresh(offset), offset);
}
} }
private Statement convert(Java17Parser.SemistmtContext stmt) { private Statement convert(Java17Parser.SemistmtContext stmt) {
@ -692,6 +697,7 @@ public class StatementGenerator {
if (!Objects.isNull(expr.methodCall())) { if (!Objects.isNull(expr.methodCall())) {
return convert(expr.methodCall(), expr.expression(), offset); return convert(expr.methodCall(), expr.expression(), offset);
} else if (!Objects.isNull(expr.identifier())) { } else if (!Objects.isNull(expr.identifier())) {
// FIXME This is not the right way of handling any of this
return generateLocalOrFieldVarOrClassName(expr.getText(), offset); return generateLocalOrFieldVarOrClassName(expr.getText(), offset);
} else { } else {
// Für alle anderen Optionen, wie Feldzugriff, Aufrufe von super oder explizite // Für alle anderen Optionen, wie Feldzugriff, Aufrufe von super oder explizite
@ -711,7 +717,7 @@ public class StatementGenerator {
} }
ArgumentList argumentList = convertArguments(expr.expressionList()); ArgumentList argumentList = convertArguments(expr.expressionList());
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> signature = argumentList.getArguments().stream().map(x -> (RefTypeOrTPHOrWildcardOrGeneric) TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new)); ArrayList<TypePlaceholder> signature = argumentList.getArguments().stream().map(x -> TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new));
signature.add(TypePlaceholder.fresh(offset)); // return type signature.add(TypePlaceholder.fresh(offset)); // return type
MethodCall ret; MethodCall ret;
@ -736,7 +742,7 @@ public class StatementGenerator {
name = expr.SUPER().getText(); name = expr.SUPER().getText();
} }
ArgumentList argumentList = convertArguments(expr.expressionList()); ArgumentList argumentList = convertArguments(expr.expressionList());
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> signature = argumentList.getArguments().stream().map(x -> (RefTypeOrTPHOrWildcardOrGeneric) TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new)); ArrayList<TypePlaceholder> signature = argumentList.getArguments().stream().map(x -> TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new));
signature.add(TypePlaceholder.fresh(offset)); // return type signature.add(TypePlaceholder.fresh(offset)); // return type
MethodCall ret = new MethodCall(TypePlaceholder.fresh(offset), getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(offset), signature, offset); MethodCall ret = new MethodCall(TypePlaceholder.fresh(offset), getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(offset), signature, offset);
ret.setStatement(); ret.setStatement();
@ -774,6 +780,7 @@ public class StatementGenerator {
* @return * @return
*/ */
private Expression generateLocalOrFieldVarOrClassName(String expression, Token offset) { private Expression generateLocalOrFieldVarOrClassName(String expression, Token offset) {
// FIXME Why does this take a String argument???
String[] parts = expression.split("\\."); String[] parts = expression.split("\\.");
if (parts.length < 2) { if (parts.length < 2) {
// Check for localVar: // Check for localVar:
@ -803,6 +810,7 @@ public class StatementGenerator {
// Check for Classname: // Check for Classname:
if (reg.contains(whole)) { if (reg.contains(whole)) {
receiver = generateStaticClassName(whole, offset); receiver = generateStaticClassName(whole, offset);
break;
} }
whole += "."; whole += ".";
} }
@ -831,7 +839,13 @@ public class StatementGenerator {
} }
private Expression convert(Java17Parser.ConditionalassignexpressionContext expression) { private Expression convert(Java17Parser.ConditionalassignexpressionContext expression) {
throw new NotImplementedException(); return new Ternary(TypePlaceholder.fresh(
expression.getStart()),
convert(expression.expression(0)),
convert(expression.expression(1)),
convert(expression.expression(2)),
expression.getStart()
);
} }
private Expression convert(Java17Parser.OrexpressionContext expression) { private Expression convert(Java17Parser.OrexpressionContext expression) {
@ -884,15 +898,15 @@ public class StatementGenerator {
} }
private Expression convert(Java17Parser.BitwiseorexpressionContext expression) { private Expression convert(Java17Parser.BitwiseorexpressionContext expression) {
throw new NotImplementedException(); return new BinaryExpr(BinaryExpr.Operator.OR, TypePlaceholder.fresh(expression.getStart()), convert(expression.expression(0)), convert(expression.expression(1)), expression.getStart());
} }
private Expression convert(Java17Parser.BitwisexorexpressionContext expression) { private Expression convert(Java17Parser.BitwisexorexpressionContext expression) {
throw new NotImplementedException(); return new BinaryExpr(BinaryExpr.Operator.XOR, TypePlaceholder.fresh(expression.getStart()), convert(expression.expression(0)), convert(expression.expression(1)), expression.getStart());
} }
private Expression convert(Java17Parser.BitwiseandexpressionContext expression) { private Expression convert(Java17Parser.BitwiseandexpressionContext expression) {
throw new NotImplementedException(); return new BinaryExpr(BinaryExpr.Operator.AND, TypePlaceholder.fresh(expression.getStart()), convert(expression.expression(0)), convert(expression.expression(1)), expression.getStart());
} }
private Expression convert(Java17Parser.EqualityexpressionContext expression) { private Expression convert(Java17Parser.EqualityexpressionContext expression) {
@ -957,6 +971,8 @@ public class StatementGenerator {
return BinaryExpr.Operator.EQUAL; return BinaryExpr.Operator.EQUAL;
} else if (operator.equals("!=")) { } else if (operator.equals("!=")) {
return BinaryExpr.Operator.NOTEQUAL; return BinaryExpr.Operator.NOTEQUAL;
} else if (operator.equals("%")) {
return BinaryExpr.Operator.MOD;
} else { } else {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -995,6 +1011,9 @@ public class StatementGenerator {
ret = new UnaryExpr(UnaryExpr.Operation.PREDECREMENT, expr, TypePlaceholder.fresh(op), op); ret = new UnaryExpr(UnaryExpr.Operation.PREDECREMENT, expr, TypePlaceholder.fresh(op), op);
ret.setStatement(); ret.setStatement();
return ret; return ret;
} else if (op.getText().equals("!")) {
ret = new UnaryExpr(UnaryExpr.Operation.NOT, expr, TypePlaceholder.fresh(op), op);
return ret;
} else { } else {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -1028,7 +1047,7 @@ public class StatementGenerator {
case PrimaryThisContext primthis: case PrimaryThisContext primthis:
return new This(primthis.getStart()); return new This(primthis.getStart());
case PrimarySuperContext primsuper: case PrimarySuperContext primsuper:
throw new NotImplementedException(); return new Super(primsuper.getStart());
case PrimaryLiteralContext primliteral: case PrimaryLiteralContext primliteral:
return convert(primliteral.literal()); return convert(primliteral.literal());
case PrimaryIdentifierContext primidentifier: case PrimaryIdentifierContext primidentifier:
@ -1043,10 +1062,17 @@ public class StatementGenerator {
private Expression convert(Java17Parser.LiteralContext literal) { private Expression convert(Java17Parser.LiteralContext literal) {
switch (literal) { switch (literal) {
case IntLiteralContext intliteral: case IntLiteralContext intliteral:
Number value = Integer.parseInt(intliteral.getText()); Number value;
if (intliteral.getText().endsWith("l") || intliteral.getText().endsWith("L"))
value = Long.parseLong(intliteral.getText().substring(0, intliteral.getText().length() - 1));
else value = Integer.parseInt(intliteral.getText());
return new Literal(TypePlaceholder.fresh(literal.getStart()), value, intliteral.getStart()); return new Literal(TypePlaceholder.fresh(literal.getStart()), value, intliteral.getStart());
case FltLiteralContext floatliteral: case FltLiteralContext floatliteral:
value = Double.parseDouble(floatliteral.getText()); if (floatliteral.getText().endsWith("f") || floatliteral.getText().endsWith("F"))
value = Float.parseFloat(floatliteral.getText().substring(0, floatliteral.getText().length() - 1));
else if (floatliteral.getText().endsWith("d") || floatliteral.getText().endsWith("D"))
value = Double.parseDouble(floatliteral.getText().substring(0, floatliteral.getText().length() - 1));
else value = Double.parseDouble(floatliteral.getText());
return new Literal(TypePlaceholder.fresh(literal.getStart()), value, floatliteral.getStart()); return new Literal(TypePlaceholder.fresh(literal.getStart()), value, floatliteral.getStart());
case CharLiteralContext charliteral: case CharLiteralContext charliteral:
RefType type = new RefType(reg.getName("java.lang.Character"), charliteral.getStart()); RefType type = new RefType(reg.getName("java.lang.Character"), charliteral.getStart());

View File

@ -34,6 +34,11 @@ public class SyntacticSugar {
public void visit(ReturnVoid aReturn) { public void visit(ReturnVoid aReturn) {
hasReturn = true; hasReturn = true;
} }
@Override
public void visit(LambdaExpression le) {
//PL 2024-04-09 Do nothing, as in a LambdaExpression a return could be
}
} }
private static boolean hasReturn(Block block) { private static boolean hasReturn(Block block) {

View File

@ -71,10 +71,6 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.typeinference.constraints.GenericsResolver;
import javassist.compiler.SyntaxError;
import javax.swing.text.html.Option;
public class SyntaxTreeGenerator { public class SyntaxTreeGenerator {
private JavaClassRegistry reg; private JavaClassRegistry reg;
@ -258,7 +254,10 @@ public class SyntaxTreeGenerator {
List<RefType> implementedInterfaces = new ArrayList<>(); List<RefType> implementedInterfaces = new ArrayList<>();
List<Pattern> constructorParameters = new ArrayList<>(); List<Pattern> constructorParameters = new ArrayList<>();
List<Statement> constructorStatements = new ArrayList<>(); List<Statement> constructorStatements = new ArrayList<>();
for (RecordComponentContext component : recordDeclaration.recordHeader().recordComponentList().recordComponent()) {
List<Java17Parser.RecordComponentContext> components = recordDeclaration.recordHeader().recordComponentList() != null ?
recordDeclaration.recordHeader().recordComponentList().recordComponent(): List.of();
for (RecordComponentContext component : components) {
int fieldmodifiers = allmodifiers.get("private") + allmodifiers.get("final"); int fieldmodifiers = allmodifiers.get("private") + allmodifiers.get("final");
String fieldname = component.identifier().getText(); String fieldname = component.identifier().getText();
Token fieldoffset = component.getStart(); Token fieldoffset = component.getStart();
@ -333,7 +332,7 @@ public class SyntaxTreeGenerator {
private ClassOrInterface convertInterface(Java17Parser.InterfaceDeclarationContext ctx, int modifiers) { private ClassOrInterface convertInterface(Java17Parser.InterfaceDeclarationContext ctx, int modifiers) {
this.superClass = new RefType(new JavaClassName("java.lang.Object"), new NullToken()); this.superClass = new RefType(new JavaClassName("java.lang.Object"), new NullToken());
String className = this.pkgName.length() > 0 ? this.pkgName + "." : "" + ctx.identifier().getText(); String className = (this.pkgName.length() > 0 ? this.pkgName + "." : "") + ctx.identifier().getText();
JavaClassName name = reg.getName(className); // Holt den Package Namen mit dazu JavaClassName name = reg.getName(className); // Holt den Package Namen mit dazu
if (!name.toString().equals(className)) { // Kommt die Klasse schon in einem anderen Package vor? if (!name.toString().equals(className)) { // Kommt die Klasse schon in einem anderen Package vor?
throw new TypeinferenceException("Name " + className + " bereits vorhanden in " + reg.getName(className).toString(), ctx.getStart()); throw new TypeinferenceException("Name " + className + " bereits vorhanden in " + reg.getName(className).toString(), ctx.getStart());
@ -452,8 +451,8 @@ public class SyntaxTreeGenerator {
protected static Block prepareBlock(Block constructorBlock, RefType superClass) { protected static Block prepareBlock(Block constructorBlock, RefType superClass) {
List<Statement> statements = constructorBlock.getStatements(); List<Statement> statements = constructorBlock.getStatements();
if (statements.isEmpty() || !(statements.get(0) instanceof SuperCall || statements.get(0) instanceof ThisCall)) { if (statements.isEmpty() || !(statements.get(0) instanceof SuperCall || statements.get(0) instanceof ThisCall)) {
var signature = new ArrayList<RefTypeOrTPHOrWildcardOrGeneric>(); var signature = new ArrayList<TypePlaceholder>();
signature.add(new Void(new NullToken())); signature.add(TypePlaceholder.fresh(new NullToken()));
statements.add(0, new SuperCall(superClass, signature, constructorBlock.getOffset())); statements.add(0, new SuperCall(superClass, signature, constructorBlock.getOffset()));
} }
/* statements.addAll(fieldInitializations); geloescht PL 2018-11-24 */ /* statements.addAll(fieldInitializations); geloescht PL 2018-11-24 */

View File

@ -68,6 +68,8 @@ public class TypeGenerator {
return new RefType(ASTFactory.createClass(Integer.class).getClassName(), typeContext.getStart()); return new RefType(ASTFactory.createClass(Integer.class).getClassName(), typeContext.getStart());
case "double": case "double":
return new RefType(ASTFactory.createClass(Double.class).getClassName(), typeContext.getStart()); return new RefType(ASTFactory.createClass(Double.class).getClassName(), typeContext.getStart());
case "float":
return new RefType(ASTFactory.createClass(Float.class).getClassName(), typeContext.getStart());
default: default:
throw new NotImplementedException(); throw new NotImplementedException();
} }

View File

@ -140,7 +140,8 @@ public class GatherNames {
if (importDeclCtx.MUL() == null) { if (importDeclCtx.MUL() == null) {
var name = importDeclCtx.qualifiedName().getText(); var name = importDeclCtx.qualifiedName().getText();
var className = new JavaClassName(name); var className = new JavaClassName(name);
if (compiler.loadJavaTXClass(className)) { var clazz = compiler.loadJavaTXClass(className);
if (clazz != null) {
ret.put(name, compiler.classRegistry.getNumberOfGenerics(name)); ret.put(name, compiler.classRegistry.getNumberOfGenerics(name));
} else { } else {
Class<?> cl = compiler.getClassLoader().loadClass(name); Class<?> cl = compiler.getClassLoader().loadClass(name);

View File

@ -236,6 +236,11 @@ public abstract class AbstractASTWalker implements ASTVisitor {
aBreak.accept(this); aBreak.accept(this);
} }
@Override
public void visit(Continue aContinue) {
aContinue.accept(this);
}
@Override @Override
public void visit(StaticClassName staticClassName) { public void visit(StaticClassName staticClassName) {
@ -332,4 +337,11 @@ public abstract class AbstractASTWalker implements ASTVisitor {
public void visit(GuardedPattern aGuardedPattern) { public void visit(GuardedPattern aGuardedPattern) {
} }
@Override
public void visit(Ternary ternary) {
ternary.cond.accept(this);
ternary.iftrue.accept(this);
ternary.iffalse.accept(this);
}
} }

View File

@ -9,10 +9,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
/** /**
* Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces * Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces
@ -128,7 +125,6 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
public List<Method> getMethods() { public List<Method> getMethods() {
return this.methods; return this.methods;
} }
/* /*
* public RefType getType() { return generateTypeOfClass(this.getClassName(), this.getGenerics(), this.getOffset()); } * public RefType getType() { return generateTypeOfClass(this.getClassName(), this.getGenerics(), this.getOffset()); }
*/ */
@ -189,4 +185,15 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
return this.name.toString() + this.genericClassParameters.toString(); return this.name.toString() + this.genericClassParameters.toString();
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ClassOrInterface other)) return false;
return Objects.equals(name, other.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
} }

View File

@ -1,6 +1,7 @@
package de.dhbwstuttgart.syntaxtree; package de.dhbwstuttgart.syntaxtree;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects;
import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
@ -32,6 +33,7 @@ public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope
private GenericDeclarationList generics; private GenericDeclarationList generics;
private final RefTypeOrTPHOrWildcardOrGeneric returnType; private final RefTypeOrTPHOrWildcardOrGeneric returnType;
public final Boolean isInherited; public final Boolean isInherited;
public final Boolean isImplemented;
/* /*
* its Constraints * its Constraints
@ -49,10 +51,11 @@ public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope
this.block = block; this.block = block;
this.generics = gtvDeclarations; this.generics = gtvDeclarations;
this.isInherited = false; this.isInherited = false;
this.isImplemented = false;
} }
public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block block, public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block block,
GenericDeclarationList gtvDeclarations, Token offset, Boolean isInherited) { GenericDeclarationList gtvDeclarations, Token offset, Boolean isInherited, Boolean isOverridden) {
super(offset); super(offset);
this.name = name; this.name = name;
this.modifier = modifier; this.modifier = modifier;
@ -61,6 +64,7 @@ public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope
this.block = block; this.block = block;
this.generics = gtvDeclarations; this.generics = gtvDeclarations;
this.isInherited = isInherited; this.isInherited = isInherited;
this.isImplemented = isOverridden;
} }
public ParameterList getParameterList() { public ParameterList getParameterList() {
@ -93,4 +97,23 @@ public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope
public String getName() { public String getName() {
return name; return name;
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Method method = (Method) o;
return Objects.equals(name, method.name) && Objects.equals(parameterlist, method.parameterlist) && Objects.equals(returnType, method.returnType);
}
@Override
public int hashCode() {
return Objects.hash(name, parameterlist, returnType);
}
@Override
public String toString() {
return name;
}
} }

View File

@ -15,6 +15,8 @@ public class SourceFile extends SyntaxTreeNode {
public final List<ClassOrInterface> KlassenVektor; public final List<ClassOrInterface> KlassenVektor;
public final Set<JavaClassName> imports; public final Set<JavaClassName> imports;
private boolean isGenerated;
public List<ClassOrInterface> availableClasses = new ArrayList<>(); public List<ClassOrInterface> availableClasses = new ArrayList<>();
/** /**
@ -38,6 +40,18 @@ public class SourceFile extends SyntaxTreeNode {
this.imports = new HashSet<>(sf.imports); this.imports = new HashSet<>(sf.imports);
} }
public void setPackageName(String packageName) {
this.pkgName = packageName;
}
public void setGenerated() {
this.isGenerated = true;
}
public boolean isGenerated() {
return this.isGenerated;
}
public String getPkgName() { public String getPkgName() {
return this.pkgName; return this.pkgName;
} }

View File

@ -53,6 +53,8 @@ public interface StatementVisitor {
void visit(Break aBreak); void visit(Break aBreak);
void visit(Continue aContinue);
void visit(Yield aYield); void visit(Yield aYield);
void visit(StaticClassName staticClassName); void visit(StaticClassName staticClassName);
@ -80,4 +82,6 @@ public interface StatementVisitor {
void visit(Literal literal); void visit(Literal literal);
void visit(Throw aThrow); void visit(Throw aThrow);
void visit(Ternary ternary);
} }

View File

@ -34,6 +34,7 @@ public class ASTFactory {
private static final HashMap<java.lang.Class, ClassOrInterface> cache = new HashMap<>(); private static final HashMap<java.lang.Class, ClassOrInterface> cache = new HashMap<>();
public static ClassOrInterface createClass(java.lang.Class jreClass) { public static ClassOrInterface createClass(java.lang.Class jreClass) {
System.out.println(jreClass);
if (cache.containsKey(jreClass)) if (cache.containsKey(jreClass))
return cache.get(jreClass); return cache.get(jreClass);
@ -105,11 +106,46 @@ public class ASTFactory {
allInheritedMethods.removeAll(allDeclaredMethods); allInheritedMethods.removeAll(allDeclaredMethods);
for (java.lang.reflect.Method method : allDeclaredMethods) { for (java.lang.reflect.Method method : allDeclaredMethods) {
var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method))); var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
methoden.add(createMethod(method, signature, jreClass, false)); if (jreClass.getSuperclass()==null) {
} methoden.add(createMethod(method, signature, jreClass, false, false));
}
else {
Boolean isImplemented = false;
isImplemented = Arrays.stream(jreClass.getInterfaces()).
reduce(false,
(x,y) -> {
try {
y.getDeclaredMethod(method.getName(), method.getParameterTypes());
return true;
}
catch (java.lang.NoSuchMethodException e) {
return false;
}},
(x,y) -> (x || y)
);
if (isImplemented) {
methoden.add(createMethod(method, signature, jreClass, false, true));
}
else {
if (Modifier.isAbstract(jreClass.getSuperclass().getModifiers())) {
try {
jreClass.getSuperclass().getDeclaredMethod(method.getName(), method.getParameterTypes());
methoden.add(createMethod(method, signature, jreClass, false, true));
}
catch (java.lang.NoSuchMethodException e) {
methoden.add(createMethod(method, signature, jreClass, false, false));
}
}
else {
methoden.add(createMethod(method, signature, jreClass, false, false));
}
}
}}
for (java.lang.reflect.Method method : allInheritedMethods) { for (java.lang.reflect.Method method : allInheritedMethods) {
var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method))); var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
methoden.add(createMethod(method, signature, jreClass, true)); methoden.add(createMethod(method, signature, jreClass, true, false));
} }
List<Field> felder = new ArrayList<>(); List<Field> felder = new ArrayList<>();
for (java.lang.reflect.Field field : jreClass.getDeclaredFields()) { for (java.lang.reflect.Field field : jreClass.getDeclaredFields()) {
@ -138,6 +174,7 @@ public class ASTFactory {
superClass = (RefType) createType(java.lang.Object.class); superClass = (RefType) createType(java.lang.Object.class);
} }
List<RefType> implementedInterfaces = new ArrayList<>(); List<RefType> implementedInterfaces = new ArrayList<>();
System.out.println(jreClass);
for (Type jreInterface : jreClass.getGenericInterfaces()) { for (Type jreInterface : jreClass.getGenericInterfaces()) {
implementedInterfaces.add((RefType) createType(jreInterface)); implementedInterfaces.add((RefType) createType(jreInterface));
} }
@ -192,7 +229,7 @@ public class ASTFactory {
return Optional.of(new de.dhbwstuttgart.syntaxtree.Constructor(modifier, name, returnType, parameterList, block, gtvDeclarations, offset /* , new ArrayList<>() geloescht PL 2018-11-24 */)); return Optional.of(new de.dhbwstuttgart.syntaxtree.Constructor(modifier, name, returnType, parameterList, block, gtvDeclarations, offset /* , new ArrayList<>() geloescht PL 2018-11-24 */));
} }
public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, java.lang.Class inClass, Boolean isInherited) { public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, java.lang.Class inClass, Boolean isInherited, Boolean isImplemented) {
String name = jreMethod.getName(); String name = jreMethod.getName();
RefTypeOrTPHOrWildcardOrGeneric returnType; RefTypeOrTPHOrWildcardOrGeneric returnType;
Type jreRetType; Type jreRetType;
@ -218,7 +255,7 @@ public class ASTFactory {
GenericDeclarationList gtvDeclarations = createGenerics(jreMethod.getTypeParameters(), inClass, jreMethod.getName(), signature); GenericDeclarationList gtvDeclarations = createGenerics(jreMethod.getTypeParameters(), inClass, jreMethod.getName(), signature);
Token offset = new NullToken(); Token offset = new NullToken();
return new Method(jreMethod.getModifiers(), name, returnType, parameterList, block, gtvDeclarations, offset, isInherited); return new Method(jreMethod.getModifiers(), name, returnType, parameterList, block, gtvDeclarations, offset, isInherited, isImplemented);
} }
public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName, String signature) { public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName, String signature) {
@ -368,6 +405,8 @@ public class ASTFactory {
return new RefType(new JavaClassName("java.lang.Character"), new ArrayList<>(), new NullToken(), true); return new RefType(new JavaClassName("java.lang.Character"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("short")) { } else if (type.getTypeName().equals("short")) {
return new RefType(new JavaClassName("java.lang.Short"), new ArrayList<>(), new NullToken(), true); return new RefType(new JavaClassName("java.lang.Short"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("float")) {
return new RefType(new JavaClassName("java.lang.Float"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("double")) { } else if (type.getTypeName().equals("double")) {
return new RefType(new JavaClassName("java.lang.Double"), new ArrayList<>(), new NullToken(), true); return new RefType(new JavaClassName("java.lang.Double"), new ArrayList<>(), new NullToken(), true);
} else if (type.getTypeName().equals("long")) { } else if (type.getTypeName().equals("long")) {

View File

@ -1,17 +1,21 @@
package de.dhbwstuttgart.syntaxtree.factory; package de.dhbwstuttgart.syntaxtree.factory;
import java.io.Writer; import java.io.Writer;
import java.lang.reflect.Modifier;
import java.util.*; import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.SourceLoc; import de.dhbwstuttgart.parser.SourceLoc;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.FCGenerator; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.FCGenerator;
import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.syntaxtree.type.WildcardType; import de.dhbwstuttgart.syntaxtree.type.WildcardType;
@ -29,7 +33,7 @@ public class UnifyTypeFactory {
private static ArrayList<PlaceholderType> PLACEHOLDERS = new ArrayList<>(); private static ArrayList<PlaceholderType> PLACEHOLDERS = new ArrayList<>();
public static FiniteClosure generateFC(List<ClassOrInterface> fromClasses, Writer logFile, ClassLoader classLoader) throws ClassNotFoundException { public static FiniteClosure generateFC(List<ClassOrInterface> fromClasses, Writer logFile, ClassLoader classLoader, JavaTXCompiler compiler) throws ClassNotFoundException {
/* /*
Die transitive Hülle muss funktionieren. Die transitive Hülle muss funktionieren.
Man darf schreiben List<A> extends AL<A> Man darf schreiben List<A> extends AL<A>
@ -40,7 +44,7 @@ public class UnifyTypeFactory {
Generell dürfen sie immer die gleichen Namen haben. Generell dürfen sie immer die gleichen Namen haben.
TODO: die transitive Hülle bilden TODO: die transitive Hülle bilden
*/ */
return new FiniteClosure(FCGenerator.toUnifyFC(fromClasses, classLoader), logFile); return new FiniteClosure(FCGenerator.toUnifyFC(compiler, fromClasses, classLoader), logFile, compiler);
} }
public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr, SourceLoc location){ public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr, SourceLoc location){
@ -63,23 +67,23 @@ public class UnifyTypeFactory {
* Convert from * Convert from
* ASTType -> UnifyType * ASTType -> UnifyType
*/ */
public static UnifyType convert(RefTypeOrTPHOrWildcardOrGeneric t, Boolean innerType){ public static UnifyType convert(JavaTXCompiler compiler, RefTypeOrTPHOrWildcardOrGeneric t, Boolean innerType){
if(t instanceof GenericRefType){ if (t instanceof GenericRefType){
return UnifyTypeFactory.convert((GenericRefType)t, innerType); return UnifyTypeFactory.convert(compiler, (GenericRefType)t, innerType);
}else if(t instanceof TypePlaceholder){ } else if (t instanceof TypePlaceholder){
return UnifyTypeFactory.convert((TypePlaceholder)t, innerType); return UnifyTypeFactory.convert(compiler, (TypePlaceholder)t, innerType);
}else if(t instanceof ExtendsWildcardType){ } else if (t instanceof ExtendsWildcardType){
return UnifyTypeFactory.convert((ExtendsWildcardType)t, innerType); return UnifyTypeFactory.convert(compiler, (ExtendsWildcardType)t, innerType);
}else if(t instanceof SuperWildcardType){ } else if (t instanceof SuperWildcardType) {
return UnifyTypeFactory.convert((SuperWildcardType)t, innerType); return UnifyTypeFactory.convert(compiler, (SuperWildcardType) t, innerType);
}else if(t instanceof RefType){ } else if (t instanceof RefType){
return UnifyTypeFactory.convert((RefType)t, innerType); return UnifyTypeFactory.convert(compiler, (RefType)t, innerType);
} }
//Es wurde versucht ein Typ umzuwandeln, welcher noch nicht von der Factory abgedeckt ist //Es wurde versucht ein Typ umzuwandeln, welcher noch nicht von der Factory abgedeckt ist
throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden"); throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden");
} }
public static UnifyType convert(RefType t, Boolean innerType){ public static UnifyType convert(JavaTXCompiler compiler, RefType t, Boolean innerType){
//Check if it is a FunN Type: //Check if it is a FunN Type:
Pattern p = Pattern.compile("Fun(\\d+)[$][$]"); Pattern p = Pattern.compile("Fun(\\d+)[$][$]");
Matcher m = p.matcher(t.getName().toString()); Matcher m = p.matcher(t.getName().toString());
@ -87,35 +91,41 @@ public class UnifyTypeFactory {
if(b){ if(b){
Integer N = Integer.valueOf(m.group(1)); Integer N = Integer.valueOf(m.group(1));
if((N + 1) == t.getParaList().size()){ if((N + 1) == t.getParaList().size()){
return convertFunN(t.getParaList(), false); return convertFunN(compiler, t.getParaList(), false);
} }
} }
UnifyType ret; UnifyType ret;
if(t.getParaList() != null && t.getParaList().size() > 0){ List<UnifyType> params = new ArrayList<>();
List<UnifyType> params = new ArrayList<>(); if (t.getParaList() != null) {
for(RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()){ for (RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()) {
params.add(UnifyTypeFactory.convert(pT, true)); params.add(UnifyTypeFactory.convert(compiler, pT, true));
} }
ret = new ReferenceType(t.getName().toString(),new TypeParams(params));
}else{
ret = new ReferenceType(t.getName().toString(), false);
} }
return ret;
var clazz = compiler.getClass(t.getName());
if (clazz != null && clazz.isInterface() && clazz.isFunctionalInterface()) {
var method = clazz.getMethods().stream().filter(x -> Modifier.isAbstract(x.modifier)).findFirst().orElseThrow();
var methodParams = method.getParameterList().getFormalparalist().stream().map(x -> convert(compiler, x.getType(), true)).toList();
var generics = StreamSupport.stream(clazz.getGenerics().spliterator(), false).map(GenericTypeVar::getName).toList();
return new FunInterfaceType(t.getName().toString(), new TypeParams(params), methodParams, convert(compiler, method.getReturnType(), true), generics);
}
return new ReferenceType(t.getName().toString(),new TypeParams(params));
} }
public static UnifyType convertFunN(List<RefTypeOrTPHOrWildcardOrGeneric> paraList, Boolean innerType){ public static UnifyType convertFunN(JavaTXCompiler compiler, List<RefTypeOrTPHOrWildcardOrGeneric> paraList, Boolean innerType){
UnifyType ret; UnifyType ret;
List<UnifyType> params = new ArrayList<>(); List<UnifyType> params = new ArrayList<>();
if(paraList != null && paraList.size() > 0){ if(paraList != null && paraList.size() > 0){
for(RefTypeOrTPHOrWildcardOrGeneric pT : paraList){ for(RefTypeOrTPHOrWildcardOrGeneric pT : paraList){
params.add(UnifyTypeFactory.convert(pT, false)); params.add(UnifyTypeFactory.convert(compiler, pT, false));
} }
} }
ret = FunNType.getFunNType(new TypeParams(params)); ret = FunNType.getFunNType(new TypeParams(params));
return ret; return ret;
} }
public static UnifyType convert(TypePlaceholder tph, Boolean innerType){ public static UnifyType convert(JavaTXCompiler compiler, TypePlaceholder tph, Boolean innerType){
if (tph.getName().equals("AFR")) { if (tph.getName().equals("AFR")) {
System.out.println("XXX"+innerType); System.out.println("XXX"+innerType);
} }
@ -135,21 +145,21 @@ public class UnifyTypeFactory {
} }
} }
public static UnifyType convert(GenericRefType t, Boolean innerType){ public static UnifyType convert(JavaTXCompiler compiler, GenericRefType t, Boolean innerType){
return new ReferenceType(t.getParsedName(), true); return new ReferenceType(t.getParsedName(), true);
} }
public static UnifyType convert(WildcardType t, Boolean innerType){ public static UnifyType convert(JavaTXCompiler compiler, WildcardType t, Boolean innerType){
if(t.isExtends()) if(t.isExtends())
return new ExtendsType(UnifyTypeFactory.convert(t.getInnerType(), false)); return new ExtendsType(UnifyTypeFactory.convert(compiler, t.getInnerType(), false));
else if(t.isSuper()) else if(t.isSuper())
return new SuperType(UnifyTypeFactory.convert(t.getInnerType(), false)); return new SuperType(UnifyTypeFactory.convert(compiler, t.getInnerType(), false));
else throw new NotImplementedException(); else throw new NotImplementedException();
} }
public static ConstraintSet<UnifyPair> convert(ConstraintSet<Pair> constraints) { public static ConstraintSet<UnifyPair> convert(JavaTXCompiler compiler, ConstraintSet<Pair> constraints) {
return constraints.map(UnifyTypeFactory::convert); return constraints.map(c -> UnifyTypeFactory.convert(compiler, c));
} }
//NEVER USED //NEVER USED
@ -160,23 +170,23 @@ public class UnifyTypeFactory {
// return unifyPairConstraint; // return unifyPairConstraint;
//} //}
public static UnifyPair convert(Pair p) { public static UnifyPair convert(JavaTXCompiler compiler, Pair p) {
UnifyPair ret = null; UnifyPair ret = null;
if(p.GetOperator().equals(PairOperator.SMALLERDOT)) { if(p.GetOperator().equals(PairOperator.SMALLERDOT)) {
ret = generateSmallerDotPair(UnifyTypeFactory.convert(p.TA1, false) ret = generateSmallerDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false)
, UnifyTypeFactory.convert(p.TA2, false), p.getLocation()); , UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
//return ret; //return ret;
}else if(p.GetOperator().equals(PairOperator.SMALLERNEQDOT)) { }else if(p.GetOperator().equals(PairOperator.SMALLERNEQDOT)) {
ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(p.TA1, false) ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false)
, UnifyTypeFactory.convert(p.TA2, false), p.getLocation()); , UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
//return ret; //return ret;
}else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) { }else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) {
ret = generateEqualDotPair(UnifyTypeFactory.convert(p.TA1, false) ret = generateEqualDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false)
, UnifyTypeFactory.convert(p.TA2, false), p.getLocation()); , UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
//return ret; //return ret;
}else if(p.GetOperator().equals(PairOperator.SMALLER)){ }else if(p.GetOperator().equals(PairOperator.SMALLER)){
ret = generateSmallerPair(UnifyTypeFactory.convert(p.TA1, false), ret = generateSmallerPair(UnifyTypeFactory.convert(compiler, p.TA1, false),
UnifyTypeFactory.convert(p.TA2, false), p.getLocation()); UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
}else throw new NotImplementedException(); }else throw new NotImplementedException();
UnifyType lhs, rhs; UnifyType lhs, rhs;
if (((lhs = ret.getLhsType()) instanceof PlaceholderType) if (((lhs = ret.getLhsType()) instanceof PlaceholderType)

View File

@ -17,6 +17,7 @@ public class BinaryExpr extends Expression {
MOD, // Modulo Operator % MOD, // Modulo Operator %
AND, // & AND, // &
OR, // | OR, // |
XOR, // ^
DIV, // / DIV, // /
LESSTHAN, // < LESSTHAN, // <
BIGGERTHAN, // > BIGGERTHAN, // >

View File

@ -0,0 +1,18 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
public class Continue extends Statement {
public Continue(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
super(type, offset);
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@ -27,10 +27,10 @@ public class MethodCall extends Statement
public RefTypeOrTPHOrWildcardOrGeneric receiverType; public RefTypeOrTPHOrWildcardOrGeneric receiverType;
//sind Tphs, repraesentieren im Resultset die Signatur der aufgerufenen Methoden, letztes Element ist der Returntyp //sind Tphs, repraesentieren im Resultset die Signatur der aufgerufenen Methoden, letztes Element ist der Returntyp
public final ArrayList<RefTypeOrTPHOrWildcardOrGeneric> signature; public final ArrayList<TypePlaceholder> signature;
public MethodCall(RefTypeOrTPHOrWildcardOrGeneric retType, Receiver receiver, String methodName, ArgumentList argumentList, public MethodCall(RefTypeOrTPHOrWildcardOrGeneric retType, Receiver receiver, String methodName, ArgumentList argumentList,
RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList<RefTypeOrTPHOrWildcardOrGeneric> signature, Token offset){ RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList<TypePlaceholder> signature, Token offset){
super(retType,offset); super(retType,offset);
this.arglist = argumentList; this.arglist = argumentList;
this.name = methodName; this.name = methodName;
@ -40,7 +40,7 @@ public class MethodCall extends Statement
if (signature == null) throw new NullPointerException(); if (signature == null) throw new NullPointerException();
} }
public List<RefTypeOrTPHOrWildcardOrGeneric> signatureArguments() { public List<TypePlaceholder> signatureArguments() {
return signature.subList(0, signature.size() - 1); return signature.subList(0, signature.size() - 1);
} }

View File

@ -11,6 +11,7 @@ import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.constraints.Constraint;
@ -30,9 +31,9 @@ public class NewClass extends MethodCall
* @param start * @param start
*/ */
public NewClass(RefType newClass, ArgumentList args, RefTypeOrTPHOrWildcardOrGeneric receiverType, public NewClass(RefType newClass, ArgumentList args, RefTypeOrTPHOrWildcardOrGeneric receiverType,
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes, Token start) { ArrayList<TypePlaceholder> signature, Token start) {
super(newClass, new ExpressionReceiver(new EmptyStmt(start)), newClass.getName().toString(), super(newClass, new ExpressionReceiver(new EmptyStmt(start)), newClass.getName().toString(),
args, receiverType, argTypes, start); args, receiverType, signature, start);
} }
@Override @Override

View File

@ -3,6 +3,7 @@ package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
@ -10,8 +11,12 @@ import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.NotImplementedException;
public class Super extends Expression public class Super extends Expression {
{
public Super(Token offset) {
super(TypePlaceholder.fresh(offset), offset);
}
public Super(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) public Super(RefTypeOrTPHOrWildcardOrGeneric type, Token offset)
{ {
super(type, offset); super(type, offset);

View File

@ -4,6 +4,7 @@ import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.syntaxtree.type.Void;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
@ -16,12 +17,12 @@ import java.util.List;
public class SuperCall extends MethodCall public class SuperCall extends MethodCall
{ {
public SuperCall(RefTypeOrTPHOrWildcardOrGeneric receiverType, public SuperCall(RefTypeOrTPHOrWildcardOrGeneric receiverType,
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes, Token offset){ ArrayList<TypePlaceholder> argTypes, Token offset){
this(new ArgumentList(new ArrayList<Expression>(), offset), receiverType, argTypes, offset); this(new ArgumentList(new ArrayList<Expression>(), offset), receiverType, argTypes, offset);
} }
public SuperCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType, public SuperCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType,
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes, Token offset){ ArrayList<TypePlaceholder> argTypes, Token offset){
super(new Void(offset), new ExpressionReceiver(new Super(receiverType, offset)), "<init>", argumentList, receiverType, argTypes, offset); super(new Void(offset), new ExpressionReceiver(new Super(receiverType, offset)), "<init>", argumentList, receiverType, argTypes, offset);
} }

View File

@ -0,0 +1,24 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
public class Ternary extends Expression {
public final Expression cond;
public final Expression iftrue;
public final Expression iffalse;
public Ternary(RefTypeOrTPHOrWildcardOrGeneric type, Expression cond, Expression iftrue, Expression iffalse, Token offset) {
super(type, offset);
this.cond = cond;
this.iftrue = iftrue;
this.iffalse = iffalse;
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@ -8,9 +8,8 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
public class This extends Expression public class This extends Expression
{ {
public This(Token offset) public This(Token offset) {
{ super(TypePlaceholder.fresh(offset), offset);
super(TypePlaceholder.fresh(offset),offset);
} }
public ArgumentList arglist; public ArgumentList arglist;

View File

@ -3,6 +3,7 @@ package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.syntaxtree.Constructor; import de.dhbwstuttgart.syntaxtree.Constructor;
import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.syntaxtree.type.Void;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
@ -11,7 +12,7 @@ import java.util.ArrayList;
public class ThisCall extends MethodCall public class ThisCall extends MethodCall
{ {
public ThisCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes, Token offset) { public ThisCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList<TypePlaceholder> argTypes, Token offset) {
super(new Void(offset), new ExpressionReceiver(new This(offset)), "<init>", argumentList, receiverType, argTypes, offset); super(new Void(offset), new ExpressionReceiver(new This(offset)), "<init>", argumentList, receiverType, argTypes, offset);
} }

View File

@ -333,6 +333,11 @@ public class OutputGenerator implements ASTVisitor {
out.append("break"); out.append("break");
} }
@Override
public void visit(Continue aContinue) {
out.append("continue");
}
@Override @Override
public void visit(StaticClassName staticClassName) { public void visit(StaticClassName staticClassName) {
@ -380,6 +385,7 @@ public class OutputGenerator implements ASTVisitor {
out.append("super("); out.append("super(");
superCall.arglist.accept(this); superCall.arglist.accept(this);
out.append(")"); out.append(")");
out.append(" Signature: " + superCall.signature);
} }
@Override @Override
@ -387,6 +393,7 @@ public class OutputGenerator implements ASTVisitor {
out.append("this("); out.append("this(");
thisCall.arglist.accept(this); thisCall.arglist.accept(this);
out.append(")"); out.append(")");
out.append(" Signature: " + thisCall.signature);
} }
@Override @Override
@ -427,6 +434,18 @@ public class OutputGenerator implements ASTVisitor {
// TODO implement // TODO implement
} }
@Override
public void visit(Ternary ternary) {
out.append("(");
ternary.cond.accept(this);
out.append(" ? ");
ternary.iftrue.accept(this);
out.append(" : ");
ternary.iffalse.accept(this);
out.append(")::");
ternary.getType().accept(this);
}
@Override @Override
public void visit(Switch switchStmt) { public void visit(Switch switchStmt) {
out.append("switch("); out.append("switch(");

View File

@ -1,11 +1,12 @@
package de.dhbwstuttgart.target.generate; package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.bytecode.CodeGenException;
import de.dhbwstuttgart.bytecode.FunNGenerator; import de.dhbwstuttgart.bytecode.FunNGenerator;
import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.environment.ByteArrayClassLoader; import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import de.dhbwstuttgart.environment.IByteArrayClassLoader; import de.dhbwstuttgart.environment.IByteArrayClassLoader;
import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.Record; import de.dhbwstuttgart.syntaxtree.Record;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
@ -16,8 +17,6 @@ import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.*; import de.dhbwstuttgart.target.tree.type.*;
import de.dhbwstuttgart.typeinference.result.*; import de.dhbwstuttgart.typeinference.result.*;
import javax.sql.rowset.RowSetWarning;
import java.lang.annotation.Target;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -27,16 +26,19 @@ import java.util.stream.Stream;
*/ */
public class ASTToTargetAST { public class ASTToTargetAST {
record SignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {};
record SignaturePairTarget(TargetType signature, TargetType parameter) {}
public static RefType OBJECT = ASTFactory.createObjectType(); // TODO It would be better if I could call this directly but the hashcode seems to change public static RefType OBJECT = ASTFactory.createObjectType(); // TODO It would be better if I could call this directly but the hashcode seems to change
protected List<Generics> all; protected List<Generics> all;
protected Generics generics; public Generics generics;
final Map<ClassOrInterface, Set<GenericTypeVar>> userDefinedGenerics = new HashMap<>(); final Map<ClassOrInterface, Set<GenericTypeVar>> userDefinedGenerics = new HashMap<>();
final Map<Method, Set<SignaturePair>> tphsInMethods = new HashMap<>();
private Method currentMethod;
public final JavaTXCompiler compiler; public final JavaTXCompiler compiler;
protected ClassOrInterface currentClass; // TODO This is only needed because of SuperCall, maybe there's
public List<GenericsResult> txGenerics() { public List<GenericsResult> txGenerics() {
return all.stream().map(generics -> new GenericsResult(generics.txGenerics)).toList(); return all.stream().map(generics -> new GenericsResult(generics.txGenerics)).toList();
} }
@ -51,11 +53,11 @@ public class ASTToTargetAST {
return converter.result; return converter.result;
} }
record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) { public record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
} }
protected IByteArrayClassLoader classLoader; public IByteArrayClassLoader classLoader;
protected SourceFile sourceFile; protected SourceFile sourceFile;
public ASTToTargetAST(List<ResultSet> resultSets) { public ASTToTargetAST(List<ResultSet> resultSets) {
@ -77,15 +79,26 @@ public class ASTToTargetAST {
this.generics = all.get(0); this.generics = all.get(0);
} }
public void addSignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {
var set = tphsInMethods.getOrDefault(currentMethod, new HashSet<>());
set.add(new SignaturePair(signature, parameter));
tphsInMethods.put(currentMethod, set);
}
Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList) { Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList) {
Optional<Method> method = Optional.empty(); Optional<Method> method = Optional.empty();
while (method.isEmpty() && !owner.getClassName().toString().equals("java.lang.Object")) { while (method.isEmpty()) {
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList)).findFirst(); method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList)).findFirst();
if (owner.getClassName().toString().equals("java.lang.Object")) break;
owner = compiler.getClass(owner.getSuperClass().getName()); owner = compiler.getClass(owner.getSuperClass().getName());
} }
return method; return method;
} }
Optional<Constructor> findConstructor(ClassOrInterface owner, List<TargetType> argumentList) {
return owner.getConstructors().stream().filter(c -> parameterEquals(c.getParameterList(), argumentList)).findFirst();
}
boolean parameterEquals(ParameterList parameterList, List<TargetType> arguments) { boolean parameterEquals(ParameterList parameterList, List<TargetType> arguments) {
var pars = parameterList.getFormalparalist(); var pars = parameterList.getFormalparalist();
if (pars.size() != arguments.size()) if (pars.size() != arguments.size())
@ -125,8 +138,41 @@ public class ASTToTargetAST {
return ret; return ret;
} }
public List<List<TargetMethod>> groupOverloads(ClassOrInterface input, List<Method> methods) {
var res = new ArrayList<List<TargetMethod>>();
for (var method : methods) {
// Convert all methods
var methodsWithTphs = convert(input, method);
// Then check for methods with the same signature
var mapOfSignatures = new HashMap<TargetMethod.Signature, List<MethodWithTphs>>();
for (var m : methodsWithTphs) {
var methodsWithSameSignature = mapOfSignatures.getOrDefault(m.method.signature(), new ArrayList<>());
methodsWithSameSignature.add(m);
mapOfSignatures.put(m.method.signature(), methodsWithSameSignature);
}
var resMethods = new HashSet<TargetMethod>();
for (var methodsWithSignature : mapOfSignatures.values()) {
outer: for (var m1 : methodsWithSignature) {
for (var m2 : methodsWithSignature) {
for (var i = 0; i < m1.args.size(); i++) {
var arg1 = m1.args.get(i);
var arg2 = m2.args.get(i);
if (arg1.parameter.equals(arg2.parameter)) {
if (isSupertype(arg1.signature, arg2.signature) &&
!arg1.signature.equals(arg2.signature)) continue outer;
}
}
}
resMethods.add(m1.method);
}
}
res.add(resMethods.stream().toList());
}
return res;
}
public TargetStructure convert(ClassOrInterface input) { public TargetStructure convert(ClassOrInterface input) {
currentClass = input;
Set<TargetGeneric> javaGenerics = new HashSet<>(); Set<TargetGeneric> javaGenerics = new HashSet<>();
Set<TargetGeneric> txGenerics = new HashSet<>(); Set<TargetGeneric> txGenerics = new HashSet<>();
@ -154,13 +200,13 @@ public class ASTToTargetAST {
TargetBlock finalFieldInitializer = fieldInitializer; TargetBlock finalFieldInitializer = fieldInitializer;
var superInterfaces = input.getSuperInterfaces().stream().map(clazz -> convert(clazz, generics.javaGenerics)).toList(); var superInterfaces = input.getSuperInterfaces().stream().map(clazz -> convert(clazz, generics.javaGenerics)).toList();
var constructors = input.getConstructors().stream().map(constructor -> this.convert(constructor, finalFieldInitializer)).flatMap(List::stream).toList(); var constructors = input.getConstructors().stream().map(constructor -> this.convert(input, constructor, finalFieldInitializer)).flatMap(List::stream).toList();
var fields = input.getFieldDecl().stream().map(this::convert).toList(); var fields = input.getFieldDecl().stream().map(this::convert).toList();
var methods = groupOverloads(input.getMethods()).stream().map(this::convert).flatMap(List::stream).toList(); var methods = groupOverloads(input, input.getMethods()).stream().flatMap(List::stream).toList();
TargetMethod staticConstructor = null; TargetMethod staticConstructor = null;
if (input.getStaticInitializer().isPresent()) if (input.getStaticInitializer().isPresent())
staticConstructor = this.convert(input.getStaticInitializer().get()).get(0); staticConstructor = this.convert(input, input.getStaticInitializer().get()).stream().findFirst().orElseThrow().method;
if (input instanceof Record) if (input instanceof Record)
return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods); return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
@ -169,7 +215,7 @@ public class ASTToTargetAST {
else return new TargetClass(input.getModifiers(), input.getClassName(), convert(input.getSuperClass(), generics.javaGenerics), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods); else return new TargetClass(input.getModifiers(), input.getClassName(), convert(input.getSuperClass(), generics.javaGenerics), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
} }
private List<MethodParameter> convert(ParameterList input, GenerateGenerics generics) { public List<MethodParameter> convert(ParameterList input, GenerateGenerics generics) {
return input.getFormalparalist().stream().map(param -> return input.getFormalparalist().stream().map(param ->
new MethodParameter((TargetPattern) convert(param)) new MethodParameter((TargetPattern) convert(param))
).toList(); ).toList();
@ -179,10 +225,10 @@ public class ASTToTargetAST {
return generics.stream().anyMatch(g -> g.name().equals(type.getParsedName())); return generics.stream().anyMatch(g -> g.name().equals(type.getParsedName()));
} }
private Set<TargetGeneric> collectMethodGenerics(GenerateGenerics generateGenerics, Set<GenerateGenerics.Pair> generics, Method input) { private Set<TargetGeneric> collectMethodGenerics(ClassOrInterface clazz, GenerateGenerics generateGenerics, Set<GenerateGenerics.Pair> generics, Method input) {
var convertedGenerics = new HashSet<>(convert(generics, generateGenerics)); var convertedGenerics = new HashSet<>(convert(generics, generateGenerics));
outer: for (GenericTypeVar typeVar : input.getGenerics()) { outer: for (GenericTypeVar typeVar : input.getGenerics()) {
for (var classGeneric : currentClass.getGenerics()) { for (var classGeneric : clazz.getGenerics()) {
if (classGeneric.equals(typeVar)) { if (classGeneric.equals(typeVar)) {
continue outer; continue outer;
} }
@ -197,10 +243,11 @@ public class ASTToTargetAST {
return convertedGenerics; return convertedGenerics;
} }
private List<TargetConstructor> convert(Constructor input, TargetBlock fieldInitializer) { private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer) {
generics = all.get(0); generics = all.get(0);
List<TargetConstructor> result = new ArrayList<>(); List<TargetConstructor> result = new ArrayList<>();
Set<List<MethodParameter>> parameterSet = new HashSet<>(); Set<List<MethodParameter>> parameterSet = new HashSet<>();
this.currentMethod = input;
for (var s : all) { for (var s : all) {
generics = s; generics = s;
@ -209,8 +256,8 @@ public class ASTToTargetAST {
List<MethodParameter> params = convert(input.getParameterList(), this.generics.javaGenerics); List<MethodParameter> params = convert(input.getParameterList(), this.generics.javaGenerics);
if (parameterSet.stream().noneMatch(p -> p.equals(params))) { if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
List<MethodParameter> txParams = convert(input.getParameterList(), this.generics.txGenerics); List<MethodParameter> txParams = convert(input.getParameterList(), this.generics.txGenerics);
var javaMethodGenerics = collectMethodGenerics(generics.javaGenerics(), javaGenerics, input); var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, input);
var txMethodGenerics = collectMethodGenerics(generics.txGenerics(), txGenerics, input); var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, input);
result.add(new TargetConstructor(input.modifier, javaMethodGenerics, txMethodGenerics, params, txParams, convert(input.block), fieldInitializer)); result.add(new TargetConstructor(input.modifier, javaMethodGenerics, txMethodGenerics, params, txParams, convert(input.block), fieldInitializer));
parameterSet.add(params); parameterSet.add(params);
@ -220,56 +267,6 @@ public class ASTToTargetAST {
return result; return result;
} }
/**
* This only considers type patterns, all other methods aren't grouped together
* @param a
* @param b
* @return
*/
private boolean signatureEquals(Method a, Method b) {
if (!a.name.equals(b.name)) return false;
var para = a.getParameterList().getFormalparalist();
var parb = b.getParameterList().getFormalparalist();
if (para.size() != parb.size()) return false;
for (var i = 0; i < para.size(); i++) {
var pa = para.get(i);
var pb = parb.get(i);
if (pa instanceof RecordPattern rpa) {
if (pb instanceof RecordPattern rpb) {
if (rpa.getType().equals(rpb.getType())) continue;
}
return false;
} else if (pa.getType().equals(pb.getType())) {
continue;
}
return false;
}
return true;
}
// TODO Nested patterns
private List<List<Method>> groupOverloads(List<Method> input) {
var done = new HashSet<Method>();
var res = new ArrayList<List<Method>>();
for (var method : input) {
if (done.contains(method)) continue;
var overloads = new ArrayList<Method>();
overloads.add(method);
done.add(method);
for (var method2 : input) {
if (!done.contains(method2) && signatureEquals(method, method2)) {
done.add(method2);
overloads.add(method2);
}
}
res.add(overloads);
}
return res;
}
private String encodeName(String name, ParameterList params) { private String encodeName(String name, ParameterList params) {
var res = new StringBuilder(); var res = new StringBuilder();
res.append(name); res.append(name);
@ -285,11 +282,11 @@ public class ASTToTargetAST {
return res.toString(); return res.toString();
} }
private List<TargetMethod> convert(List<Method> overloadedMethods) { private List<TargetMethod> convert(ClassOrInterface clazz, List<Method> overloadedMethods) {
if (overloadedMethods.size() == 1) { if (overloadedMethods.size() == 1) {
return convert(overloadedMethods.get(0)); return convert(clazz, overloadedMethods.getFirst()).stream().map(m -> m.method()).toList();
} }
var res = new ArrayList<Method>(); var methods = new ArrayList<Method>();
for (var method : overloadedMethods) { for (var method : overloadedMethods) {
var newMethod = new Method( var newMethod = new Method(
method.modifier, method.modifier,
@ -301,7 +298,7 @@ public class ASTToTargetAST {
method.getGenerics(), method.getGenerics(),
method.getOffset() method.getOffset()
); );
res.add(newMethod); methods.add(newMethod);
} }
// TODO Record overloading // TODO Record overloading
@ -324,7 +321,16 @@ public class ASTToTargetAST {
var entryPoint = new Method(template.modifier, template.name, template.getReturnType(), params, block, template.getGenerics(), new NullToken()); var entryPoint = new Method(template.modifier, template.name, template.getReturnType(), params, block, template.getGenerics(), new NullToken());
res.add(entryPoint); // TODO*/ res.add(entryPoint); // TODO*/
return res.stream().map(this::convert).flatMap(List::stream).toList(); var res = new ArrayList<TargetMethod>();
for (var method : methods) {
var overloads = convert(clazz, method);
for (var m : overloads) {
var overload = m.method;
if (res.contains(overload)) throw new CodeGenException("Duplicate method found: " + overload.name() + " with signature " + overload.signature().getSignature());
res.add(overload);
}
}
return res;
} }
private Expression makeRecordSwitch(RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList params, List<Method> overloadedMethods) { private Expression makeRecordSwitch(RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList params, List<Method> overloadedMethods) {
@ -348,31 +354,75 @@ public class ASTToTargetAST {
return swtch; return swtch;
} }
private List<TargetMethod> convert(Method method) { private Optional<Method> findSuperMethodToOverride(ClassOrInterface currentClass, String name, List<MethodParameter> params) {
generics = all.get(0); var superClass = compiler.getClass(currentClass.getSuperClass().getName());
List<TargetMethod> result = new ArrayList<>(); var methodStream = superClass.getMethods().stream();
Set<List<MethodParameter>> parameterSet = new HashSet<>(); for (var superInterface : currentClass.getSuperInterfaces()) {
methodStream = Stream.concat(methodStream, compiler.getClass(superInterface.getName()).getMethods().stream());
}
return methodStream.filter(m -> {
if (!m.name.equals(name)) return false;
var sParams = m.getParameterList();
if (sParams.getFormalparalist().size() != params.size()) return false;
for (var i = 0; i < params.size(); i++) {
var a = TargetType.toPrimitive(params.get(i).pattern().type());
var b = convert(sParams.getFormalparalist().get(i).getType());
if (!Objects.equals(a, b)) return false;
}
return true;
}).findFirst();
}
record MethodWithTphs(TargetMethod method, List<SignaturePairTarget> args) {}
private List<MethodWithTphs> convert(ClassOrInterface currentClass, Method method) {
generics = all.getFirst();
List<MethodWithTphs> result = new ArrayList<>();
this.currentMethod = method;
for (var s : all) { for (var s : all) {
generics = s; generics = s;
var javaGenerics = this.generics.javaGenerics.generics(currentClass, method); var javaGenerics = this.generics.javaGenerics.generics(currentClass, method);
var txGenerics = this.generics.txGenerics.generics(currentClass, method); var txGenerics = this.generics.txGenerics.generics(currentClass, method);
List<MethodParameter> params = convert(method.getParameterList(), this.generics.javaGenerics); List<MethodParameter> params = convert(method.getParameterList(), this.generics.javaGenerics);
if (parameterSet.stream().noneMatch(p -> p.equals(params))) { var returnType = convert(method.getReturnType(), this.generics.javaGenerics);
List<MethodParameter> txParams = convert(method.getParameterList(), this.generics.txGenerics); var superMethod = findSuperMethodToOverride(currentClass, method.getName(), params);
if (superMethod.isPresent()) {
var javaMethodGenerics = collectMethodGenerics(generics.javaGenerics(), javaGenerics, method); // If we find a super method to override, use its parameters and return types
var txMethodGenerics = collectMethodGenerics(generics.txGenerics(), txGenerics, method); var newReturnType = convert(superMethod.get().getReturnType(), this.generics.javaGenerics);
if (newReturnType instanceof TargetPrimitiveType && TargetType.toPrimitive(returnType).equals(newReturnType)) {
var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, convert(method.getReturnType(), this.generics.javaGenerics)); returnType = newReturnType;
var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), this.generics.txGenerics)); params = convert(superMethod.get().getParameterList(), method.getParameterList(), this.generics.javaGenerics);
result.add(new TargetMethod(method.modifier, method.name, convert(method.block), javaSignature, txSignature)); }
parameterSet.add(params);
} }
List<MethodParameter> txParams = convert(method.getParameterList(), this.generics.txGenerics);
var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, method);
var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, method);
var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, returnType);
var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), this.generics.txGenerics));
var newMethod = new TargetMethod(method.modifier, method.name, convert(method.block), javaSignature, txSignature);
var concreteParams = tphsInMethods.getOrDefault(method, new HashSet<>()).stream().map(sig -> new SignaturePairTarget(convert(sig.signature), convert(sig.parameter))).toList();
result.add(new MethodWithTphs(newMethod, concreteParams));
} }
return result; return result;
} }
private List<MethodParameter> convert(ParameterList superList, ParameterList paraList, JavaGenerics generics) {
var list = new ArrayList<MethodParameter>();
for (var i = 0; i < paraList.getFormalparalist().size(); i++) {
var param = paraList.getParameterAt(i);
list.add(new MethodParameter((TargetPattern) convert(param)).withType(convert(superList.getParameterAt(i).getType(), generics)));
}
return list;
}
protected TargetSwitch.Case convert(SwitchBlock block) { protected TargetSwitch.Case convert(SwitchBlock block) {
return new TargetSwitch.Case(block.getLabels().stream().map(this::convert).toList(), convert((Block) block), block.isExpression); return new TargetSwitch.Case(block.getLabels().stream().map(this::convert).toList(), convert((Block) block), block.isExpression);
} }
@ -404,7 +454,7 @@ public class ASTToTargetAST {
public Map<String, byte[]> auxiliaries = new HashMap<>(); public Map<String, byte[]> auxiliaries = new HashMap<>();
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) { public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
return convert(input, generics.javaGenerics); return convert(input, generics.javaGenerics);
} }
@ -430,10 +480,59 @@ public class ASTToTargetAST {
} }
var filteredParams = new ArrayList<TargetType>(); var filteredParams = new ArrayList<TargetType>();
for (var i = 0; i < newParams.size(); i++) { for (var i = 0; i < newParams.size(); i++) {
if (gep.parameters.get(i) != null) if (i < gep.inParams.size() && gep.inParams.get(i) != null)
filteredParams.add(newParams.get(i)); filteredParams.add(newParams.get(i));
} }
return TargetFunNType.fromParams(params, filteredParams); return TargetFunNType.fromParams(params, filteredParams, gep.getReturnType() != null ? 1 : 0);
}
private boolean isSubtype(TargetType test, TargetType other) {
var testClass = compiler.getClass(new JavaClassName(test.name()));
var otherClass = compiler.getClass(new JavaClassName(other.name()));
if (testClass == null) return false;
while (testClass != null) {
if (testClass.equals(otherClass)) return true;
if (testClass.getClassName().equals(new JavaClassName("java.lang.Object"))) break;
testClass = compiler.getClass(testClass.getSuperClass().getName());
}
return false;
}
private boolean isSupertype(TargetType test, TargetType other) {
return isSubtype(other, test);
}
private boolean isSubtype(FunNGenerator.GenericParameters test, FunNGenerator.GenericParameters other) {
if (test.getArguments().size() != other.getArguments().size()) return false;
if (!isSubtype(test.getReturnType(), other.getReturnType())) return false;
for (int i = 0; i < test.getArguments().size(); i++) {
var arg1 = test.getArguments().get(i);
var arg2 = other.getArguments().get(i);
if (!isSupertype(arg1, arg2)) return false;
}
return true;
}
public void generateFunNTypes() {
for (var entry : usedFunN.entrySet()) {
var gep = entry.getValue();
var superInterfaces = usedFunN.values().stream()
.filter(g -> !g.equals(gep))
.filter(genericParameters -> isSubtype(gep, genericParameters))
.map(FunNGenerator::getSpecializedClassName)
.toList();
var code = FunNGenerator.generateSpecializedBytecode(gep, superInterfaces);
try {
classLoader.findClass(entry.getKey());
} catch (ClassNotFoundException e) {
try {
classLoader.loadClass(code);
} catch (LinkageError ignored) {}
}
auxiliaries.put(entry.getKey(), code);
}
} }
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) { protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
@ -448,17 +547,16 @@ public class ASTToTargetAST {
} }
var params = refType.getParaList().stream().map(type -> { var params = refType.getParaList().stream().map(type -> {
var res = convert(type, generics); return convert(type, generics);
if (res == null) res = new TargetRefType("java.lang.Void");
return res;
}).toList(); }).toList();
if (name.matches("Fun\\d+\\$\\$")) { // TODO This seems like a bad idea if (name.matches("Fun\\d+\\$\\$")) { // TODO This seems like a bad idea
var className = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params)); var returnType = FunNGenerator.getReturnType(params);
var className = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), returnType);
if (!usedFunNSuperTypes.contains(params.size())) { if (!usedFunNSuperTypes.contains(params.size())) {
usedFunNSuperTypes.add(params.size()); usedFunNSuperTypes.add(params.size());
var code = FunNGenerator.generateSuperBytecode(params.size() - 1); var code = FunNGenerator.generateSuperBytecode(params.size() - 1, returnType != null ? 1 : 0);
var superClassName = FunNGenerator.getSuperClassName(params.size() - 1); var superClassName = FunNGenerator.getSuperClassName(params.size() - 1, returnType != null ? 1 : 0);
try { try {
classLoader.findClass(superClassName); classLoader.findClass(superClassName);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
@ -470,17 +568,8 @@ public class ASTToTargetAST {
} }
FunNGenerator.GenericParameters gep = null; FunNGenerator.GenericParameters gep = null;
if (!usedFunN.containsKey(className)) { if (!usedFunN.containsKey(className)) {
gep = new FunNGenerator.GenericParameters(); gep = new FunNGenerator.GenericParameters(params, returnType != null ? 1 : 0);
var code = FunNGenerator.generateSpecializedBytecode(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params), gep);
try {
classLoader.findClass(className);
} catch (ClassNotFoundException e) {
try {
classLoader.loadClass(code);
} catch (LinkageError ignored) {}
}
usedFunN.put(className, gep); usedFunN.put(className, gep);
auxiliaries.put(className, code);
} else { } else {
gep = usedFunN.get(className); gep = usedFunN.get(className);
} }

View File

@ -652,14 +652,12 @@ public abstract class GenerateGenerics {
} }
void normalize(Set<Pair> result, Set<Pair> classGenerics, Set<TPH> usedTphs) { void normalize(Set<Pair> result, Set<Pair> classGenerics, Set<TPH> usedTphs) {
outer: for (var p1 : new HashSet<>(result)) {
for (var tph : usedTphs) { if (p1 instanceof PairLT ptph && ptph.left.resolve().equals(ptph.right.resolve()))
for (var p1 : new HashSet<>(result)) { result.remove(p1); // TODO This is a bit strange
if (p1 instanceof PairLT ptph && ptph.left.equals(ptph.right)) }
result.remove(p1); // TODO This is a bit strange
if (p1.left.equals(tph)) continue outer;
}
for (var tph : usedTphs) {
if (classGenerics == null || classGenerics.stream().noneMatch((pair) -> pair.left.equals(tph))) if (classGenerics == null || classGenerics.stream().noneMatch((pair) -> pair.left.equals(tph)))
addToPairs(result, new PairEQ(tph, ASTToTargetAST.OBJECT)); addToPairs(result, new PairEQ(tph, ASTToTargetAST.OBJECT));
} }

View File

@ -1,5 +1,6 @@
package de.dhbwstuttgart.target.generate; package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
@ -9,6 +10,8 @@ import de.dhbwstuttgart.syntaxtree.factory.PrimitiveMethodsGenerator;
import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.target.tree.MethodParameter; import de.dhbwstuttgart.target.tree.MethodParameter;
import de.dhbwstuttgart.target.tree.TargetGeneric;
import de.dhbwstuttgart.target.tree.TargetMethod;
import de.dhbwstuttgart.target.tree.expression.*; import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.*; import de.dhbwstuttgart.target.tree.type.*;
@ -81,7 +84,9 @@ public class StatementToTargetExpression implements ASTVisitor {
} // Don't look at lambda expressions } // Don't look at lambda expressions
}); });
result = new TargetLambdaExpression(converter.convert(lambdaExpression.getType()), captures, parameters, converter.convert(lambdaExpression.getReturnType()), converter.convert(lambdaExpression.methodBody)); TargetMethod.Signature signature = new TargetMethod.Signature(Set.of(), parameters, converter.convert(lambdaExpression.getReturnType()));;
var tpe = converter.convert(lambdaExpression.getType());
result = new TargetLambdaExpression(tpe, captures, signature, converter.convert(lambdaExpression.methodBody));
} }
@Override @Override
@ -103,8 +108,9 @@ public class StatementToTargetExpression implements ASTVisitor {
case SUB -> new TargetBinaryOp.Sub(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); case SUB -> new TargetBinaryOp.Sub(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case MUL -> new TargetBinaryOp.Mul(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); case MUL -> new TargetBinaryOp.Mul(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case MOD -> new TargetBinaryOp.Rem(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); case MOD -> new TargetBinaryOp.Rem(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case AND -> new TargetBinaryOp.And(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); case AND -> new TargetBinaryOp.BAnd(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case OR -> new TargetBinaryOp.Or(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); case OR -> new TargetBinaryOp.BOr(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case XOR -> new TargetBinaryOp.XOr(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case DIV -> new TargetBinaryOp.Div(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); case DIV -> new TargetBinaryOp.Div(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case LESSTHAN -> new TargetBinaryOp.Less(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); case LESSTHAN -> new TargetBinaryOp.Less(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case BIGGERTHAN -> new TargetBinaryOp.Greater(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); case BIGGERTHAN -> new TargetBinaryOp.Greater(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
@ -199,14 +205,23 @@ public class StatementToTargetExpression implements ASTVisitor {
Method foundMethod = null; Method foundMethod = null;
var isStatic = false; var isStatic = false;
var isInterface = true; var isInterface = true;
var isPrivate = false;
var signature = methodCall.signatureArguments().stream().map(converter::convert).toList(); var signature = methodCall.signatureArguments().stream().map(converter::convert).toList();
var receiverClass = converter.currentClass; // Add used TPHs to containing method
for (var i = 0; i < methodCall.signatureArguments().size(); i++) {
converter.addSignaturePair(methodCall.signatureArguments().get(i), methodCall.arglist.getArguments().get(i).getType());
}
var receiverClass = converter.compiler.getClass(receiverName);
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver && expressionReceiver.expr instanceof This) { if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver && expressionReceiver.expr instanceof This) {
var thisMethod = converter.findMethod(converter.currentClass, methodCall.name, signature); if (receiverClass == null) throw new DebugException("Class " + receiverName + " does not exist!");
foundMethod = thisMethod.orElseGet(() -> findMethod(converter.currentClass.getSuperClass().getName(), methodCall.name, signature).orElseThrow()); var thisMethod = converter.findMethod(receiverClass, methodCall.name, signature);
ClassOrInterface finalReceiverClass = receiverClass;
foundMethod = thisMethod.orElseGet(() -> findMethod(finalReceiverClass.getSuperClass().getName(), methodCall.name, signature).orElseThrow());
} else if (!isFunNType) { } else if (!isFunNType) {
receiverClass = converter.compiler.getClass(receiverName); receiverClass = converter.compiler.getClass(receiverName);
if (receiverClass == null) throw new DebugException("Class " + receiverName + " does not exist!");
foundMethod = findMethod(receiverName, methodCall.name, signature).orElseThrow(); foundMethod = findMethod(receiverName, methodCall.name, signature).orElseThrow();
} }
@ -214,15 +229,20 @@ public class StatementToTargetExpression implements ASTVisitor {
returnType = converter.convert(foundMethod.getReturnType()); returnType = converter.convert(foundMethod.getReturnType());
argList = foundMethod.getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList(); argList = foundMethod.getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
isStatic = Modifier.isStatic(foundMethod.modifier); isStatic = Modifier.isStatic(foundMethod.modifier);
isPrivate = Modifier.isPrivate(foundMethod.modifier);
isInterface = receiverClass.isInterface(); isInterface = receiverClass.isInterface();
} }
result = new TargetMethodCall(converter.convert(methodCall.getType()), returnType, argList, converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), receiverType, methodCall.name, isStatic, isInterface); System.out.println(argList);
result = new TargetMethodCall(converter.convert(methodCall.getType()), returnType, argList, converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), receiverType, methodCall.name, isStatic, isInterface, isPrivate);
} }
@Override @Override
public void visit(NewClass newClass) { public void visit(NewClass newClass) {
result = new TargetNew(new TargetRefType(newClass.name), newClass.getArgumentList().getArguments().stream().map(converter::convert).toList()); var receiverName = new JavaClassName(newClass.name);
var ctor = converter.findConstructor(converter.compiler.getClass(receiverName), newClass.signatureArguments().stream().map(converter::convert).toList());
var signature = ctor.orElseThrow().getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
result = new TargetNew(new TargetRefType(newClass.name), signature, newClass.getArgumentList().getArguments().stream().map(converter::convert).toList());
} }
@Override @Override
@ -246,6 +266,11 @@ public class StatementToTargetExpression implements ASTVisitor {
result = new TargetBreak(); result = new TargetBreak();
} }
@Override
public void visit(Continue aContinue) {
result = new TargetContinue();
}
@Override @Override
public void visit(StaticClassName staticClassName) { public void visit(StaticClassName staticClassName) {
result = new TargetClassName(converter.convert(staticClassName.getType())); result = new TargetClassName(converter.convert(staticClassName.getType()));
@ -268,7 +293,7 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override @Override
public void visit(DoStmt whileStmt) { public void visit(DoStmt whileStmt) {
throw new NotImplementedException(); result = new TargetDo(converter.convert(whileStmt.expr), converter.convert(whileStmt.loopBlock));
} }
// TODO These two might not be necessary // TODO These two might not be necessary
@ -284,20 +309,31 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override @Override
public void visit(SuperCall superCall) { public void visit(SuperCall superCall) {
var aSuper = converter.convert(converter.currentClass.getSuperClass()); var aSuper = converter.convert(superCall.receiver.getType());
var type = converter.convert(superCall.getType()); var type = converter.convert(superCall.getType());
var parameters = superCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList(); var receiverName = new JavaClassName(converter.convert(superCall.receiver.getType()).name());
var clazz = converter.compiler.getClass(receiverName);
var signature = superCall.signatureArguments().stream().map(converter::convert).toList();
var method = converter.findConstructor(clazz, signature);
var params = superCall.getArgumentList().getArguments().stream().map(converter::convert).toList();
result = new TargetMethodCall(type, type, parameters, new TargetSuper(aSuper), superCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aSuper, superCall.name, false, false); List<TargetType> argList;
if (method.isPresent()) {
argList = method.get().getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
} else {
argList = params.stream().map(TargetExpression::type).toList();
}
result = new TargetMethodCall(type, null, argList, new TargetSuper(aSuper), params, aSuper, superCall.name, false, false, false);
} }
@Override @Override
public void visit(ThisCall thisCall) { public void visit(ThisCall thisCall) {
var aThis = converter.convert(new RefType(converter.currentClass.getClassName(), new NullToken())); var aThis = converter.convert(thisCall.receiver.getType());
var type = converter.convert(thisCall.getType()); var type = converter.convert(thisCall.getType());
var parameters = thisCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList(); var parameters = thisCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList();
result = new TargetMethodCall(type, type, parameters, new TargetThis(aThis), thisCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aThis, thisCall.name, false, false); result = new TargetMethodCall(type, type, parameters, new TargetThis(aThis), thisCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aThis, thisCall.name, false, false, false);
} }
@Override @Override
@ -345,6 +381,11 @@ public class StatementToTargetExpression implements ASTVisitor {
result = new TargetThrow(converter.convert(aThrow.expr)); result = new TargetThrow(converter.convert(aThrow.expr));
} }
@Override
public void visit(Ternary ternary) {
result = new TargetTernary(converter.convert(ternary.getType()), converter.convert(ternary.cond), converter.convert(ternary.iftrue), converter.convert(ternary.iffalse));
}
@Override @Override
public void visit(Switch switchStmt) { public void visit(Switch switchStmt) {
var cases = switchStmt.getBlocks().stream().filter(s -> !s.isDefault()).map(converter::convert).toList(); var cases = switchStmt.getBlocks().stream().filter(s -> !s.isDefault()).map(converter::convert).toList();

View File

@ -124,6 +124,11 @@ public abstract class TracingStatementVisitor implements StatementVisitor {
} }
@Override
public void visit(Continue aContinue) {
}
@Override @Override
public void visit(StaticClassName staticClassName) { public void visit(StaticClassName staticClassName) {
@ -203,4 +208,11 @@ public abstract class TracingStatementVisitor implements StatementVisitor {
public void visit(Yield aYield) { public void visit(Yield aYield) {
} }
@Override
public void visit(Ternary ternary) {
ternary.cond.accept(this);
ternary.iftrue.accept(this);
ternary.iffalse.accept(this);
}
} }

View File

@ -1,14 +1,24 @@
package de.dhbwstuttgart.target.tree; package de.dhbwstuttgart.target.tree;
import de.dhbwstuttgart.target.tree.expression.TargetBlock; import de.dhbwstuttgart.target.tree.expression.TargetBlock;
import de.dhbwstuttgart.target.tree.expression.TargetPattern;
import de.dhbwstuttgart.target.tree.type.TargetType; import de.dhbwstuttgart.target.tree.type.TargetType;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Set; import java.util.Set;
public record TargetMethod(int access, String name, TargetBlock block, Signature signature, Signature txSignature) { public record TargetMethod(int access, String name, TargetBlock block, Signature signature, Signature txSignature) {
public record Signature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) { } public record Signature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) {
public String getSignature() {
return TargetMethod.getSignature(generics, parameters, returnType);
}
public String getDescriptor() {
return TargetMethod.getDescriptor(returnType, parameters.stream().map(MethodParameter::pattern).map(TargetPattern::type).toArray(TargetType[]::new));
}
}
public static String getDescriptor(TargetType returnType, TargetType... parameters) { public static String getDescriptor(TargetType returnType, TargetType... parameters) {
String ret = "("; String ret = "(";
@ -55,5 +65,16 @@ public record TargetMethod(int access, String name, TargetBlock block, Signature
public boolean isStatic() { public boolean isStatic() {
return (access & Opcodes.ACC_STATIC) != 0; return (access & Opcodes.ACC_STATIC) != 0;
} }
@Override
public boolean equals(Object other) {
if (!(other instanceof TargetMethod otherMethod)) return false;
return otherMethod.signature.equals(this.signature) && otherMethod.name.equals(this.name);
}
@Override
public int hashCode() {
return Objects.hash(name, signature);
}
} }

View File

@ -0,0 +1,4 @@
package de.dhbwstuttgart.target.tree.expression;
public record TargetDo(TargetExpression cond, TargetExpression body) implements TargetExpression {
}

View File

@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.*; import de.dhbwstuttgart.target.tree.type.*;
public sealed interface TargetExpression public sealed interface TargetExpression
permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetPattern, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetThrow, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield { permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetDo, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetPattern, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetThrow, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield {
default TargetType type() { default TargetType type() {
return null; return null;

View File

@ -7,4 +7,9 @@ public record TargetGuard(TargetPattern inner, TargetExpression expression) impl
public TargetGuard withType(TargetType type) { public TargetGuard withType(TargetType type) {
return new TargetGuard(inner.withType(type), expression); return new TargetGuard(inner.withType(type), expression);
} }
@Override
public TargetType type() {
return inner.type();
}
} }

View File

@ -2,9 +2,10 @@ package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.MethodParameter; import de.dhbwstuttgart.target.tree.MethodParameter;
import de.dhbwstuttgart.target.tree.TargetField; import de.dhbwstuttgart.target.tree.TargetField;
import de.dhbwstuttgart.target.tree.TargetMethod;
import de.dhbwstuttgart.target.tree.type.TargetType; import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List; import java.util.List;
public record TargetLambdaExpression(TargetType type, List<MethodParameter> captures, List<MethodParameter> params, TargetType returnType, TargetBlock block) implements TargetExpression { public record TargetLambdaExpression(TargetType type, List<MethodParameter> captures, TargetMethod.Signature signature, TargetBlock block) implements TargetExpression {
} }

View File

@ -1,15 +1,13 @@
package de.dhbwstuttgart.target.tree.expression; package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.MethodParameter;
import de.dhbwstuttgart.target.tree.TargetMethod; import de.dhbwstuttgart.target.tree.TargetMethod;
import de.dhbwstuttgart.target.tree.type.TargetRefType;
import de.dhbwstuttgart.target.tree.type.TargetType; import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List; import java.util.List;
public record TargetMethodCall(TargetType type, TargetType returnType, List<TargetType> parameterTypes, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface) implements TargetStatementExpression { public record TargetMethodCall(TargetType type, TargetType returnType, List<TargetType> parameterTypes, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface, boolean isPrivate) implements TargetStatementExpression {
public TargetMethodCall(TargetType type, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface) { public TargetMethodCall(TargetType type, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface, boolean isPrivate) {
this(type, type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface); this(type, type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface, isPrivate);
} }

View File

@ -5,8 +5,8 @@ import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List; import java.util.List;
public record TargetNew(TargetType type, List<TargetExpression> params) implements TargetStatementExpression { public record TargetNew(TargetType type, List<TargetType> signature, List<TargetExpression> params) implements TargetStatementExpression {
public String getDescriptor() { public String getDescriptor() {
return TargetMethod.getDescriptor(null, params.stream().map(TargetExpression::type).toArray(TargetType[]::new)); return TargetMethod.getDescriptor(null, signature.toArray(TargetType[]::new));
} }
} }

View File

@ -8,4 +8,6 @@ public sealed interface TargetPattern extends TargetExpression permits TargetCom
} }
TargetPattern withType(TargetType type); TargetPattern withType(TargetType type);
TargetType type();
} }

View File

@ -2,5 +2,5 @@ package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType; import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetTernary(TargetType type, TargetExpression cond, TargetExpression ifTrue, TargetExpression ifFalse) implements TargetExpression { public record TargetTernary(TargetType type, TargetExpression cond, TargetExpression iftrue, TargetExpression iffalse) implements TargetExpression {
} }

View File

@ -1,6 +1,4 @@
package de.dhbwstuttgart.target.tree.expression; package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetWhile(TargetExpression cond, TargetExpression body) implements TargetExpression { public record TargetWhile(TargetExpression cond, TargetExpression body) implements TargetExpression {
} }

View File

@ -4,15 +4,29 @@ import de.dhbwstuttgart.bytecode.FunNGenerator;
import java.util.List; import java.util.List;
public record TargetFunNType(String name, List<TargetType> params) implements TargetSpecializedType { public record TargetFunNType(String name, List<TargetType> funNParams, List<TargetType> params, int returnArguments) implements TargetSpecializedType {
public static TargetFunNType fromParams(List<TargetType> params) { public static TargetFunNType fromParams(List<TargetType> params, int returnArguments) {
return fromParams(params, params); return fromParams(params, params, returnArguments);
} }
public static TargetFunNType fromParams(List<TargetType> params, List<TargetType> realParams) { public static TargetFunNType fromParams(List<TargetType> params, List<TargetType> realParams, int returnArguments) {
var name = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params)); var name = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params));
return new TargetFunNType(name, realParams); return new TargetFunNType(name, params, realParams, returnArguments);
}
public String toMethodDescriptor() {
var res = "(";
for (var i = 0; i < funNParams.size() - 1; i++) {
res += "Ljava/lang/Object;";
}
res += ")";
if (returnArguments > 0) {
res += "Ljava/lang/Object;";
} else {
res += "V";
}
return res;
} }
@Override @Override

View File

@ -53,19 +53,17 @@ public sealed interface TargetType
}; };
} }
static TargetType toTargetType(Class<?> clazz) { static TargetType toWrapper(TargetType f) {
if (clazz.isPrimitive()) { if (f.equals(boolean_)) return Boolean;
if (clazz.equals(boolean.class)) return boolean_; if (f.equals(char_)) return Char;
if (clazz.equals(char.class)) return char_; if (f.equals(byte_)) return Byte;
if (clazz.equals(byte.class)) return byte_; if (f.equals(short_)) return Short;
if (clazz.equals(short.class)) return short_; if (f.equals(int_)) return Integer;
if (clazz.equals(int.class)) return int_; if (f.equals(long_)) return Long;
if (clazz.equals(long.class)) return long_; if (f.equals(float_)) return Float;
if (clazz.equals(float.class)) return float_; if (f.equals(double_)) return Double;
if (clazz.equals(double.class)) return double_;
} return f;
if (clazz.equals(void.class)) return null;
return new TargetRefType(clazz.getName());
} }
String toSignature(); String toSignature();

View File

@ -10,6 +10,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.typeinference.constraints.GenericsResolver; import de.dhbwstuttgart.typeinference.constraints.GenericsResolver;
import de.dhbwstuttgart.typeinference.typeAlgo.TYPEStmt;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -19,14 +20,16 @@ public class MethodAssumption extends Assumption{
private RefTypeOrTPHOrWildcardOrGeneric retType; private RefTypeOrTPHOrWildcardOrGeneric retType;
List<? extends RefTypeOrTPHOrWildcardOrGeneric> params; List<? extends RefTypeOrTPHOrWildcardOrGeneric> params;
private final Boolean isInherited; private final Boolean isInherited;
private final Boolean isOverridden;
public MethodAssumption(ClassOrInterface receiver, RefTypeOrTPHOrWildcardOrGeneric retType, public MethodAssumption(ClassOrInterface receiver, RefTypeOrTPHOrWildcardOrGeneric retType,
List<? extends RefTypeOrTPHOrWildcardOrGeneric> params, TypeScope scope, Boolean isInherited){ List<? extends RefTypeOrTPHOrWildcardOrGeneric> params, TypeScope scope, Boolean isInherited, Boolean isOverridden){
super(scope); super(scope);
this.receiver = receiver; this.receiver = receiver;
this.retType = retType; this.retType = retType;
this.params = params; this.params = params;
this.isInherited = isInherited; this.isInherited = isInherited;
this.isOverridden = isOverridden;
} }
/* /*
@ -67,23 +70,14 @@ public class MethodAssumption extends Assumption{
* @return * @return
*/ */
public RefTypeOrTPHOrWildcardOrGeneric getReceiverType(GenericsResolver resolver) { public RefTypeOrTPHOrWildcardOrGeneric getReceiverType(GenericsResolver resolver) {
if (receiver == null) return null; return TYPEStmt.getReceiverType(receiver, resolver);
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for(GenericTypeVar gtv : receiver.getGenerics()){
//Die Generics werden alle zu TPHs umgewandelt.
params.add(resolver.resolve(new GenericRefType(gtv.getName(), new NullToken())));
}
RefTypeOrTPHOrWildcardOrGeneric receiverType;
if(receiver instanceof FunNClass){
receiverType = new RefType(new JavaClassName(receiver.getClassName().toString()+"$$"), params, new NullToken()); // new FunN(params);
}else{
receiverType = new RefType(receiver.getClassName(), params, new NullToken());
}
return receiverType;
} }
public Boolean isInherited() { public Boolean isInherited() {
return isInherited; return isInherited;
} }
public Boolean isOverridden() {
return isOverridden;
}
} }

View File

@ -2,6 +2,8 @@ package de.dhbwstuttgart.typeinference.assumptions;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators; import com.google.common.collect.Iterators;
import de.dhbwstuttgart.bytecode.CodeGenException;
import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.Method;
@ -30,6 +32,14 @@ public class TypeInferenceBlockInformation extends TypeInferenceInformation {
public ClassOrInterface getCurrentClass() { public ClassOrInterface getCurrentClass() {
return currentClass; return currentClass;
} }
public ClassOrInterface getSuperClass() {
for (var clazz : getAvailableClasses()) {
if (clazz.getClassName().equals(currentClass.getSuperClass().getName()))
return clazz;
}
throw new DebugException("Class has no superclass!");
}
public TypeScope getCurrentTypeScope() { public TypeScope getCurrentTypeScope() {
return methodContext; return methodContext;
} }

View File

@ -8,7 +8,8 @@ import java.util.Set;
public class Constraint<A> extends HashSet<A> { public class Constraint<A> extends HashSet<A> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private Boolean isInherited = false;//wird nur für die Method-Constraints benoetigt private Boolean isInherited = false;//wird beides nur für die Method-Constraints benoetigt
private Boolean isImplemented = false;
/* /*
* wird verwendet um bei der Codegenerierung die richtige Methoden - Signatur * wird verwendet um bei der Codegenerierung die richtige Methoden - Signatur
@ -22,12 +23,14 @@ public class Constraint<A> extends HashSet<A> {
super(); super();
} }
public Constraint(Boolean isInherited) { public Constraint(Boolean isInherited, Boolean isImplemented) {
this.isInherited = isInherited; this.isInherited = isInherited;
this.isImplemented = isImplemented;
} }
public Constraint(Boolean isInherited, Constraint<A> extendConstraint, Set<A> methodSignatureConstraint) { public Constraint(Boolean isInherited, Boolean isImplemented, Constraint<A> extendConstraint, Set<A> methodSignatureConstraint) {
this.isInherited = isInherited; this.isInherited = isInherited;
this.isImplemented = isImplemented;
this.extendConstraint = extendConstraint; this.extendConstraint = extendConstraint;
this.methodSignatureConstraint = methodSignatureConstraint; this.methodSignatureConstraint = methodSignatureConstraint;
} }
@ -40,6 +43,10 @@ public class Constraint<A> extends HashSet<A> {
return isInherited; return isInherited;
} }
public Boolean isImplemented() {
return isImplemented;
}
public Constraint<A> getExtendConstraint() { public Constraint<A> getExtendConstraint() {
return extendConstraint; return extendConstraint;
} }
@ -57,7 +64,8 @@ public class Constraint<A> extends HashSet<A> {
} }
public String toString() { public String toString() {
return super.toString() + "\nisInherited = " + isInherited return super.toString() + "\nisInherited = " + isInherited + " isOveridden = " + isImplemented
+ methodSignatureConstraint
//" + extendsContraint: " + (extendConstraint != null ? extendConstraint.toStringBase() : "null" ) //" + extendsContraint: " + (extendConstraint != null ? extendConstraint.toStringBase() : "null" )
+ "\n" ; + "\n" ;
} }

View File

@ -71,12 +71,13 @@ public class ConstraintSet<A> {
for(Set<Constraint<A>> oderConstraint : oderConstraints){ for(Set<Constraint<A>> oderConstraint : oderConstraints){
newOder.add( newOder.add(
oderConstraint.parallelStream().map((Constraint<A> as) -> { oderConstraint.stream().map((Constraint<A> as) -> {
Constraint<B> newConst = as.stream() Constraint<B> newConst = as.stream()
.map(o) .map(o)
.collect(Collectors.toCollection(( .collect(Collectors.toCollection((
() -> new Constraint<B> (as.isInherited(), () -> new Constraint<B> (as.isInherited(),
as.isImplemented(),
(as.getExtendConstraint() != null) (as.getExtendConstraint() != null)
? as.getExtendConstraint().stream().map(o).collect(Collectors.toCollection(Constraint::new)) ? as.getExtendConstraint().stream().map(o).collect(Collectors.toCollection(Constraint::new))
: null, : null,

View File

@ -15,24 +15,22 @@ import java.util.*;
public class TYPE { public class TYPE {
private final Collection<SourceFile> sfs; private final SourceFile sf;
private final Set<ClassOrInterface> allAvailableClasses; private final Set<ClassOrInterface> allAvailableClasses;
public TYPE(Collection<SourceFile> sourceFiles, Set<ClassOrInterface> allAvailableClasses){ public TYPE(SourceFile sf, Set<ClassOrInterface> allAvailableClasses){
sfs = sourceFiles; this.sf = sf;
this.allAvailableClasses = allAvailableClasses; this.allAvailableClasses = allAvailableClasses;
} }
public ConstraintSet getConstraints() { public ConstraintSet getConstraints() {
ConstraintSet ret = new ConstraintSet(); ConstraintSet ret = new ConstraintSet();
for(SourceFile sf : sfs) for (ClassOrInterface cl : sf.KlassenVektor) {
for (ClassOrInterface cl : sf.KlassenVektor) { var allClasses = new HashSet<ClassOrInterface>();
System.out.println(sf.availableClasses); allClasses.addAll(allAvailableClasses);
var allClasses = new HashSet<ClassOrInterface>(); allClasses.addAll(sf.availableClasses);
allClasses.addAll(allAvailableClasses); ret.addAll(getConstraintsClass(cl, new TypeInferenceInformation(allClasses)));
allClasses.addAll(sf.availableClasses); }
ret.addAll(getConstraintsClass(cl, new TypeInferenceInformation(allClasses)));
}
return ret; return ret;
} }

View File

@ -1,6 +1,7 @@
//PL 2018-12-19: Merge chekcen //PL 2018-12-19: Merge chekcen
package de.dhbwstuttgart.typeinference.typeAlgo; package de.dhbwstuttgart.typeinference.typeAlgo;
import java.sql.Ref;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -245,6 +246,9 @@ public class TYPEStmt implements StatementVisitor {
constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), number, PairOperator.SMALLERNEQDOT, loc(unaryExpr.getOffset()))); constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), number, PairOperator.SMALLERNEQDOT, loc(unaryExpr.getOffset())));
// The type of the postfix increment expression is the type of the variable // The type of the postfix increment expression is the type of the variable
constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), unaryExpr.getType(), PairOperator.EQUALSDOT, loc(unaryExpr.getOffset()))); constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), unaryExpr.getType(), PairOperator.EQUALSDOT, loc(unaryExpr.getOffset())));
} else if (unaryExpr.operation == UnaryExpr.Operation.NOT) {
constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), unaryExpr.getType(), PairOperator.EQUALSDOT, loc(unaryExpr.getOffset())));
constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), new RefType(ASTFactory.createClass(java.lang.Boolean.class).getClassName(), new NullToken()), PairOperator.EQUALSDOT, loc(unaryExpr.getOffset())));
} else { } else {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -256,7 +260,15 @@ public class TYPEStmt implements StatementVisitor {
public void visit(BinaryExpr binary) { public void visit(BinaryExpr binary) {
binary.lexpr.accept(this); binary.lexpr.accept(this);
binary.rexpr.accept(this); binary.rexpr.accept(this);
if (binary.operation.equals(BinaryExpr.Operator.DIV) || binary.operation.equals(BinaryExpr.Operator.MUL) || binary.operation.equals(BinaryExpr.Operator.MOD) || binary.operation.equals(BinaryExpr.Operator.ADD) || binary.operation.equals(BinaryExpr.Operator.SUB)) { if (binary.operation.equals(BinaryExpr.Operator.DIV)
|| binary.operation.equals(BinaryExpr.Operator.MUL)
|| binary.operation.equals(BinaryExpr.Operator.MOD)
|| binary.operation.equals(BinaryExpr.Operator.ADD)
|| binary.operation.equals(BinaryExpr.Operator.SUB)
|| binary.operation.equals(BinaryExpr.Operator.OR)
|| binary.operation.equals(BinaryExpr.Operator.AND)
|| binary.operation.equals(BinaryExpr.Operator.XOR)) {
Set<Constraint<Pair>> numericAdditionOrStringConcatenation = new HashSet<>(); Set<Constraint<Pair>> numericAdditionOrStringConcatenation = new HashSet<>();
// TODO PL 2018-11-06 // TODO PL 2018-11-06
@ -476,6 +488,16 @@ public class TYPEStmt implements StatementVisitor {
aThrow.expr.accept(this); aThrow.expr.accept(this);
} }
@Override
public void visit(Ternary ternary) {
ternary.cond.accept(this);
ternary.iftrue.accept(this);
ternary.iffalse.accept(this);
constraintsSet.addUndConstraint(new Pair(ternary.cond.getType(), bool, PairOperator.EQUALSDOT));
constraintsSet.addUndConstraint(new Pair(ternary.iftrue.getType(), ternary.getType(), PairOperator.SMALLERDOT));
constraintsSet.addUndConstraint(new Pair(ternary.iffalse.getType(), ternary.getType(), PairOperator.SMALLERDOT));
}
@Override @Override
public void visit(Return returnExpr) { public void visit(Return returnExpr) {
returnExpr.retexpr.accept(this); returnExpr.retexpr.accept(this);
@ -492,6 +514,11 @@ public class TYPEStmt implements StatementVisitor {
} }
@Override
public void visit(Continue aContinue) {
}
@Override @Override
public void visit(StaticClassName staticClassName) { public void visit(StaticClassName staticClassName) {
// Hier entstehen keine Constraints // Hier entstehen keine Constraints
@ -499,7 +526,13 @@ public class TYPEStmt implements StatementVisitor {
@Override @Override
public void visit(Super aSuper) { public void visit(Super aSuper) {
throw new NotImplementedException(); var superClass = info.getSuperClass();
var params = new ArrayList<RefTypeOrTPHOrWildcardOrGeneric>();
for (var gtv : superClass.getGenerics()) {
params.add(new GenericRefType(gtv.getName(), aSuper.getOffset()));
}
var superType = new RefType(superClass.getClassName(), params, aSuper.getOffset());
constraintsSet.addUndConstraint(new Pair(aSuper.getType(), superType, PairOperator.EQUALSDOT, loc(aSuper.getOffset())));
} }
@Override @Override
@ -541,7 +574,10 @@ public class TYPEStmt implements StatementVisitor {
@Override @Override
public void visit(DoStmt whileStmt) { public void visit(DoStmt whileStmt) {
throw new NotImplementedException(); RefType booleanType = new RefType(ASTFactory.createClass(java.lang.Boolean.class).getClassName(), new NullToken());
whileStmt.expr.accept(this);
constraintsSet.addUndConstraint(new Pair(whileStmt.expr.getType(), booleanType, PairOperator.EQUALSDOT, loc(whileStmt.expr.getOffset())));
whileStmt.loopBlock.accept(this);
} }
@Override @Override
@ -559,20 +595,17 @@ public class TYPEStmt implements StatementVisitor {
@Override @Override
public void visit(SuperCall superCall) { public void visit(SuperCall superCall) {
Set<Constraint<Pair>> methodConstraints = new HashSet<>(); Set<Constraint<Pair>> methodConstraints = new HashSet<>();
for (var clazz : info.getAvailableClasses()) { var clazz = info.getSuperClass();
if (clazz.getClassName().equals(info.getCurrentClass().getSuperClass().getName())) { for (var ctor : clazz.getConstructors()) {
for (var ctor : clazz.getConstructors()) { var params = convertParams(ctor.getParameterList(), info);
var params = convertParams(ctor.getParameterList(), info); if (params.size() != superCall.arglist.getArguments().size()) continue;
if (params.size() != superCall.arglist.getArguments().size()) continue; var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(clazz, ctor), ctor.isInherited, false);
var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(clazz, ctor), ctor.isInherited);
GenericsResolver resolver = getResolverInstance(); GenericsResolver resolver = getResolverInstance();
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver); Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver);
methodConstraints.addAll(oneMethodConstraints); methodConstraints.addAll(oneMethodConstraints);
}
break;
}
} }
constraintsSet.addUndConstraint(new Pair(superCall.receiver.getType(), getReceiverType(info.getSuperClass(), getResolverInstance()), PairOperator.EQUALSDOT));
constraintsSet.addOderConstraint(methodConstraints); constraintsSet.addOderConstraint(methodConstraints);
} }
@ -582,23 +615,41 @@ public class TYPEStmt implements StatementVisitor {
for (var ctor : info.getCurrentClass().getConstructors()) { for (var ctor : info.getCurrentClass().getConstructors()) {
var params = convertParams(ctor.getParameterList(), info); var params = convertParams(ctor.getParameterList(), info);
if (params.size() != thisCall.arglist.getArguments().size()) continue; if (params.size() != thisCall.arglist.getArguments().size()) continue;
var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(info.getCurrentClass(), ctor), ctor.isInherited); var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(info.getCurrentClass(), ctor), ctor.isInherited, false);
GenericsResolver resolver = getResolverInstance(); GenericsResolver resolver = getResolverInstance();
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(thisCall, assumption, info, resolver); Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(thisCall, assumption, info, resolver);
methodConstraints.addAll(oneMethodConstraints); methodConstraints.addAll(oneMethodConstraints);
} }
constraintsSet.addUndConstraint(new Pair(thisCall.receiver.getType(), getReceiverType(info.getCurrentClass(), getResolverInstance()), PairOperator.EQUALSDOT));
constraintsSet.addOderConstraint(methodConstraints); constraintsSet.addOderConstraint(methodConstraints);
} }
public static RefTypeOrTPHOrWildcardOrGeneric getReceiverType(ClassOrInterface receiver, GenericsResolver resolver) {
if (receiver == null) return null;
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for(GenericTypeVar gtv : receiver.getGenerics()){
//Die Generics werden alle zu TPHs umgewandelt.
params.add(resolver.resolve(new GenericRefType(gtv.getName(), new NullToken())));
}
RefTypeOrTPHOrWildcardOrGeneric receiverType;
if(receiver instanceof FunNClass){
receiverType = new RefType(new JavaClassName(receiver.getClassName().toString()+"$$"), params, new NullToken()); // new FunN(params);
}else{
receiverType = new RefType(receiver.getClassName(), params, new NullToken());
}
return receiverType;
}
/* /*
* METHOD CALL Section: * METHOD CALL Section:
*/ */
protected Set<Constraint<Pair>> generateConstraint(MethodCall forMethod, MethodAssumption assumption, TypeInferenceBlockInformation info, GenericsResolver resolver) { protected Set<Constraint<Pair>> generateConstraint(MethodCall forMethod, MethodAssumption assumption, TypeInferenceBlockInformation info, GenericsResolver resolver) {
Constraint<Pair> methodConstraint, extendsMethodConstraint; Constraint<Pair> methodConstraint, extendsMethodConstraint;
methodConstraint = new Constraint<>(assumption.isInherited()); methodConstraint = new Constraint<>(assumption.isInherited(), assumption.isOverridden());
extendsMethodConstraint = new Constraint<>(assumption.isInherited());// PL 2023-01-24: Ersetzt die Dopplung in visit(MethodCall) extendsMethodConstraint = new Constraint<>(assumption.isInherited(), assumption.isOverridden());// PL 2023-01-24: Ersetzt die Dopplung in visit(MethodCall)
ClassOrInterface receiverCl = assumption.getReceiver(); ClassOrInterface receiverCl = assumption.getReceiver();
/* /*
@ -640,7 +691,8 @@ public class TYPEStmt implements StatementVisitor {
Set<Pair> methodSignatureConstraint = generatemethodSignatureConstraint(forMethod, assumption, info, resolver); Set<Pair> methodSignatureConstraint = generatemethodSignatureConstraint(forMethod, assumption, info, resolver);
System.out.println("methodSignatureConstraint; " + methodSignatureConstraint); //System.out.println("methodSignatureConstraint: " + methodSignatureConstraint);
//System.out.println("methodConstraint: " + methodConstraint);
methodConstraint.setmethodSignatureConstraint(methodSignatureConstraint); methodConstraint.setmethodSignatureConstraint(methodSignatureConstraint);
extendsMethodConstraint.setmethodSignatureConstraint(methodSignatureConstraint); extendsMethodConstraint.setmethodSignatureConstraint(methodSignatureConstraint);
@ -648,6 +700,7 @@ public class TYPEStmt implements StatementVisitor {
Set<Constraint<Pair>> ret = new HashSet<>(); Set<Constraint<Pair>> ret = new HashSet<>();
ret.add(methodConstraint); ret.add(methodConstraint);
ret.add(extendsMethodConstraint); ret.add(extendsMethodConstraint);
return ret; return ret;
} }
@ -671,7 +724,6 @@ public class TYPEStmt implements StatementVisitor {
Set<Pair> ret = new HashSet<>(); Set<Pair> ret = new HashSet<>();
for (int i = 0; i < foMethod.arglist.getArguments().size(); i++) { for (int i = 0; i < foMethod.arglist.getArguments().size(); i++) {
// Zuordnung von MethoCall.signature (Argumenttypen) zu der Argumenttypen der ausgewaehlten Methode (assumption.params) // Zuordnung von MethoCall.signature (Argumenttypen) zu der Argumenttypen der ausgewaehlten Methode (assumption.params)
ret.add(new Pair(foMethod.signature.get(i), assumption.getArgTypes().get(i), PairOperator.EQUALSDOT)); ret.add(new Pair(foMethod.signature.get(i), assumption.getArgTypes().get(i), PairOperator.EQUALSDOT));
@ -702,14 +754,14 @@ public class TYPEStmt implements StatementVisitor {
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
throw new NotImplementedException(); throw new NotImplementedException();
} }
}, false)); }, false, false));
} }
for (ClassOrInterface cl : info.getAvailableClasses()) { for (ClassOrInterface cl : info.getAvailableClasses()) {
for (Method m : cl.getMethods()) { for (Method m : cl.getMethods()) {
if (m.getName().equals(name) && m.getParameterList().getFormalparalist().size() == numArgs) { if (m.getName().equals(name) && m.getParameterList().getFormalparalist().size() == numArgs) {
RefTypeOrTPHOrWildcardOrGeneric retType = m.getReturnType();// info.checkGTV(m.getReturnType()); RefTypeOrTPHOrWildcardOrGeneric retType = m.getReturnType();// info.checkGTV(m.getReturnType());
ret.add(new MethodAssumption(cl, retType, convertParams(m.getParameterList(), info), createTypeScope(cl, m), m.isInherited)); ret.add(new MethodAssumption(cl, retType, convertParams(m.getParameterList(), info), createTypeScope(cl, m), m.isInherited, m.isImplemented));
} }
} }
} }
@ -740,7 +792,8 @@ public class TYPEStmt implements StatementVisitor {
if (cl.getClassName().equals(ofType.getName())) { if (cl.getClassName().equals(ofType.getName())) {
for (Method m : cl.getConstructors()) { for (Method m : cl.getConstructors()) {
if (m.getParameterList().getFormalparalist().size() == argList.getArguments().size()) { if (m.getParameterList().getFormalparalist().size() == argList.getArguments().size()) {
ret.add(new MethodAssumption(cl, cl.generateTypeOfThisClass(), convertParams(m.getParameterList(), info), createTypeScope(cl, m), m.isInherited)); var params = convertParams(m.getParameterList(), info);
ret.add(new MethodAssumption(cl, cl.generateTypeOfThisClass(), params, createTypeScope(cl, m), m.isInherited, m.isImplemented));
} }
} }
} }
@ -755,6 +808,12 @@ public class TYPEStmt implements StatementVisitor {
methodConstraint.add(new Pair(assumption.getReturnType(resolver), forConstructor.getType(), PairOperator.SMALLERDOT, loc(forConstructor.getOffset()))); methodConstraint.add(new Pair(assumption.getReturnType(resolver), forConstructor.getType(), PairOperator.SMALLERDOT, loc(forConstructor.getOffset())));
// WELCHEN SINN MACHT DIESER CONSTRAINT??? // WELCHEN SINN MACHT DIESER CONSTRAINT???
methodConstraint.addAll(generateParameterConstraints(forConstructor, assumption, info, resolver)); methodConstraint.addAll(generateParameterConstraints(forConstructor, assumption, info, resolver));
Set<Pair> methodSignatureConstraint = generatemethodSignatureConstraint(forConstructor, assumption, info, resolver);
methodConstraint.setmethodSignatureConstraint(methodSignatureConstraint);
methodConstraint.addAll(methodSignatureConstraint);
return methodConstraint; return methodConstraint;
} }

View File

@ -79,9 +79,10 @@ public class Match implements IMatch {
// SUBST - Rule // SUBST - Rule
if(lhsType instanceof PlaceholderType) { if(lhsType instanceof PlaceholderType) {
mgu.add((PlaceholderType) lhsType, rhsType); mgu.add((PlaceholderType) lhsType, rhsType);
termsList = termsList.stream().map(mgu::applyleft).collect(Collectors.toCollection(ArrayList::new));
idx = idx+1 == termsList.size() ? 0 : idx+1; idx = idx+1 == termsList.size() ? 0 : idx+1;
continue; //PL 2024-04-08 falsch da es sich nicht um Unifikation handelt
//termsList = termsList.stream().map(mgu::applyleft).collect(Collectors.toCollection(ArrayList::new));
//continue;
} }
idx++; idx++;

View File

@ -12,21 +12,14 @@ import java.util.Stack;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.exceptions.DebugException; import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet; import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet;
import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; import de.dhbwstuttgart.typeinference.unify.model.*;
import de.dhbwstuttgart.typeinference.unify.model.FunNType;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.ReferenceType;
import de.dhbwstuttgart.typeinference.unify.model.SuperType;
import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
import de.dhbwstuttgart.typeinference.unify.model.Unifier;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
import de.dhbwstuttgart.typeinference.unify.model.WildcardType;
import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.unify.distributeVariance; import de.dhbwstuttgart.typeinference.unify.distributeVariance;
@ -709,9 +702,10 @@ public class RuleSet implements IRuleSet{
x -> uni.apply(pair,x)).collect(Collectors.toCollection((b.getExtendConstraint() != null) x -> uni.apply(pair,x)).collect(Collectors.toCollection((b.getExtendConstraint() != null)
? () -> new Constraint<UnifyPair>( ? () -> new Constraint<UnifyPair>(
b.isInherited(), b.isInherited(),
b.isImplemented(),
b.getExtendConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(Constraint::new)), b.getExtendConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(Constraint::new)),
b.getmethodSignatureConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(HashSet::new))) b.getmethodSignatureConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(HashSet::new)))
: () -> new Constraint<UnifyPair>(b.isInherited()) : () -> new Constraint<UnifyPair>(b.isInherited(), b.isImplemented())
)); ));
oderConstraints.replaceAll(oc -> oc.stream().map(applyUni).collect(Collectors.toCollection(HashSet::new))); oderConstraints.replaceAll(oc -> oc.stream().map(applyUni).collect(Collectors.toCollection(HashSet::new)));
/* /*
@ -892,38 +886,42 @@ public class RuleSet implements IRuleSet{
//FunN$$<...> <. FunctinalInterface<...> wird umgewandelt in FunN$$<...> <. FunN$$<... args aus FuntionalInterface ...> //FunN$$<...> <. FunctinalInterface<...> wird umgewandelt in FunN$$<...> <. FunN$$<... args aus FuntionalInterface ...>
if (rhsType instanceof ReferenceType) { if (rhsType instanceof ReferenceType) {
UnifyType typeFI = pair.getRhsType(); UnifyType typeFI = pair.getRhsType();
Optional<UnifyType> opt = fc.getRightHandedFunctionalInterfaceType(typeFI.getName()); Optional<UnifyType> opt = fc.getRightHandedFunctionalInterfaceType(typeFI.getName());
if(!opt.isPresent()) if(!opt.isPresent())
return Optional.empty(); return Optional.empty();
// The generic Version of typeFI (FI<a1, a2, a3, ... >) if (!(typeFI instanceof ReferenceType refType) || !(refType instanceof FunInterfaceType intf))
UnifyType typeDgen = opt.get();
// Actually greater+ because the types are ensured to have different names
Set<UnifyType> smaller = fc.getChildren(typeDgen);
opt = smaller.stream().filter(x -> x.getName().equals(pair.getLhsType().getName())).findAny();
if(!opt.isPresent())
return Optional.empty(); return Optional.empty();
TypeParams typeDParams = typeFI.getTypeParams(); var fiArgs = intf.getFunctionalInterfaceTypeArguments(refType);
TypeParams typeDgenParams = typeDgen.getTypeParams(); var retType = fiArgs.getFirst();
var lhsArgs = intf.getFunctionalInterfaceTypeArguments(lhsType);
Unifier unif = Unifier.identity(); var lhsRet = lhsArgs.getFirst();
for(int i = 0; i < typeDParams.size(); i++) {
if (typeDgenParams.get(i) instanceof PlaceholderType)
unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i));
else System.out.println("ERROR");
}
UnifyType newRhsType = opt.get();
Set<UnifyPair> result = new HashSet<>(); Set<UnifyPair> result = new HashSet<>();
result.add(new UnifyPair(lhsType, unif.apply(newRhsType), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); if (retType instanceof ExtendsType) {
result.add(new UnifyPair(lhsRet, retType, PairOperator.SMALLERDOTWC));
} else if (retType instanceof SuperType) {
return Optional.empty();
} else {
result.add(new UnifyPair(lhsRet, retType, PairOperator.EQUALSDOT));
}
for (var i = 1; i < fiArgs.size(); i++) {
var lh = lhsArgs.get(i);
var rh = fiArgs.get(i);
if (rh instanceof SuperType) {
result.add(new UnifyPair(lh, rh, PairOperator.SMALLERDOTWC));
} else if (rh instanceof ExtendsType) {
return Optional.empty();
} else {
result.add(new UnifyPair(lh, rh, PairOperator.EQUALSDOT));
}
}
return Optional.of(result); return Optional.of(result);
} }

View File

@ -253,13 +253,14 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
one = true; one = true;
Set<UnifyPair> neweq = new HashSet<>(eq); Set<UnifyPair> neweq = new HashSet<>(eq);
/* 1-elementige Oder-Constraints werden in und-Constraints umgewandelt */ /* 1-elementige Oder-Constraints werden in und-Constraints umgewandelt */
Set<UnifyPair> methodSignatureConstraint = new HashSet<>();
oderConstraintsField.stream() oderConstraintsField.stream()
.filter(x -> x.size()==1) .filter(x -> x.size()==1)
.map(y -> y.stream().findFirst().get()).forEach(x -> neweq.addAll(x)); .map(y -> y.stream().findFirst().get()).forEach(x -> { neweq.addAll(x); methodSignatureConstraint.addAll(x.getmethodSignatureConstraint());} );
ArrayList<Set<Constraint<UnifyPair>>> remainingOderconstraints = oderConstraintsField.stream() ArrayList<Set<Constraint<UnifyPair>>> remainingOderconstraints = oderConstraintsField.stream()
.filter(x -> x.size()>1) .filter(x -> x.size()>1)
.collect(Collectors.toCollection(ArrayList::new)); .collect(Collectors.toCollection(ArrayList::new));
Set<Set<UnifyPair>> res = unify(neweq, remainingOderconstraints, fc, parallel, rekTiefeField, new HashSet<>()); Set<Set<UnifyPair>> res = unify(neweq, remainingOderconstraints, fc, parallel, rekTiefeField, methodSignatureConstraint);
noOfThread--; noOfThread--;
try { try {
logFile.close(); logFile.close();
@ -594,15 +595,17 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
/* methodconstraintsets werden zum Ergebnis hinzugefuegt /* methodconstraintsets werden zum Ergebnis hinzugefuegt
* Anfang * Anfang
*/ */
//System.out.println("methodSignatureConstraint Return: " + methodSignatureConstraint); //System.out.println("methodSignatureConstraint Return: " + methodSignatureConstraint + "\n");
eqPrimePrimeSet.forEach(x -> x.addAll(methodSignatureConstraint)); eqPrimePrimeSet.forEach(x -> x.addAll(methodSignatureConstraint));
//Substitutionen in methodcontraintsets werdne ausgeführt //Substitutionen in methodcontraintsets werdne ausgeführt
/* PL auskommentiert 2024-05-02
eqPrimePrimeSet = eqPrimePrimeSet.stream().map( eqPrimePrimeSet = eqPrimePrimeSet.stream().map(
x -> { Optional<Set<UnifyPair>> help = rules.subst(x); x -> { Optional<Set<UnifyPair>> help = rules.subst(x);
return help.isPresent() ? return help.isPresent() ?
help.get(): help.get():
x; }).collect(Collectors.toSet()); x; }).collect(Collectors.toSet());
*/
/* /*
* Ende * Ende
*/ */
@ -813,6 +816,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
writeLog("nextSetasList: " + nextSetasList.toString()); writeLog("nextSetasList: " + nextSetasList.toString());
if (variance == 1) { if (variance == 1) {
a = oup.max(nextSetasList.iterator()); a = oup.max(nextSetasList.iterator());
writeLog("Max: a in " + variance + " "+ a);
nextSetasList.remove(a); nextSetasList.remove(a);
if (oderConstraint) { if (oderConstraint) {
nextSetasListOderConstraints.add(((Constraint<UnifyPair>)a).getExtendConstraint()); nextSetasListOderConstraints.add(((Constraint<UnifyPair>)a).getExtendConstraint());
@ -885,7 +889,11 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
if (oderConstraint) {//Methodconstraints werden abgespeichert für die Bytecodegenerierung von Methodenaufrufen if (oderConstraint) {//Methodconstraints werden abgespeichert für die Bytecodegenerierung von Methodenaufrufen
methodSignatureConstraint.addAll(((Constraint<UnifyPair>)a).getmethodSignatureConstraint()); methodSignatureConstraint.addAll(((Constraint<UnifyPair>)a).getmethodSignatureConstraint());
//System.out.println("ERSTELLUNG: " +methodSignatureConstraint); writeLog("ERSTELLUNG methodSignatureConstraint: " + methodSignatureConstraint);
//System.out.println("ERSTELLUNG methodSignatureConstraint: " +noOfThread+" "+methodSignatureConstraint);
//System.out.println("a: " +a);
//System.out.println("eq: " +eq);
//System.out.println();
} }
i++; i++;
@ -1134,14 +1142,22 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
writeLog("a in " + variance + " "+ a); writeLog("a in " + variance + " "+ a);
writeLog("nextSetasListRest: " + nextSetasListRest.toString()); writeLog("nextSetasListRest: " + nextSetasListRest.toString());
} }
//Fuer parallele Berechnung der Oder-Contraints wird methodSignature kopiert
//und jeweils die methodSignature von a bzw. nSaL wieder gelöscht, wenn es keine Lösung ist.
Set<UnifyPair> methodSignatureConstraintForParallel = new HashSet<>(methodSignatureConstraint);
Set<UnifyPair> nSaL = a;
while (!nextSetasListRest.isEmpty()) { while (!nextSetasListRest.isEmpty()) {
Set<UnifyPair> nSaL = nextSetasListRest.remove(0); methodSignatureConstraintForParallel.removeAll(((Constraint<UnifyPair>)nSaL).getmethodSignatureConstraint());
nSaL = nextSetasListRest.remove(0);
nextSetasList.remove(nSaL); //PL einkommentiert 20-02-03 nextSetasList.remove(nSaL); //PL einkommentiert 20-02-03
methodSignatureConstraintForParallel.addAll(((Constraint<UnifyPair>)nSaL).getmethodSignatureConstraint());
Set<UnifyPair> newEq = new HashSet<>(eq); Set<UnifyPair> newEq = new HashSet<>(eq);
Set<Set<UnifyPair>> newElems = new HashSet<>(elems); Set<Set<UnifyPair>> newElems = new HashSet<>(elems);
List<Set<Constraint<UnifyPair>>> newOderConstraints = new ArrayList<>(oderConstraints); List<Set<Constraint<UnifyPair>>> newOderConstraints = new ArrayList<>(oderConstraints);
newElems.add(nSaL); newElems.add(nSaL);
TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, parallel, logFile, log, rekTiefe, urm, usedTasks, methodSignatureConstraint); TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, parallel, logFile, log, rekTiefe, urm, usedTasks, new HashSet<>(methodSignatureConstraintForParallel));
forks.add(fork); forks.add(fork);
synchronized(usedTasks) { synchronized(usedTasks) {
if (this.myIsCancelled()) { if (this.myIsCancelled()) {
@ -1338,12 +1354,15 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
while(aParDefIt.hasNext()) { while(aParDefIt.hasNext()) {
Set<UnifyPair> a_new = aParDefIt.next(); Set<UnifyPair> a_new = aParDefIt.next();
List<Set<UnifyPair>> smallerSetasList = oup.smallerThan(a_new, nextSetasList); List<Set<UnifyPair>> smallerSetasList = oup.smallerThan(a_new, nextSetasList);
writeLog("smallerSetasList: " + smallerSetasList);
List<Set<UnifyPair>> notInherited = smallerSetasList.stream() List<Set<UnifyPair>> notInherited = smallerSetasList.stream()
.filter(x -> !((Constraint<UnifyPair>)x).isInherited()) .filter(x -> !((Constraint<UnifyPair>)x).isInherited() && !((Constraint<UnifyPair>)x).isImplemented())
.collect(Collectors.toCollection(ArrayList::new)); .collect(Collectors.toCollection(ArrayList::new));
writeLog("notInherited: " + notInherited+"\n");
List<Set<UnifyPair>> notErased = new ArrayList<>(); List<Set<UnifyPair>> notErased = new ArrayList<>();
notInherited.stream().forEach(x -> { notErased.addAll(oup.smallerEqThan(x, smallerSetasList)); }); notInherited.stream().forEach(x -> { notErased.addAll(oup.smallerEqThan(x, smallerSetasList)); });
List<Set<UnifyPair>> erased = new ArrayList<>(smallerSetasList); List<Set<UnifyPair>> erased = new ArrayList<>(smallerSetasList);
writeLog("notErased: " + notErased+"\n");
erased.removeAll(notErased); erased.removeAll(notErased);
nextSetasList.removeAll(erased); nextSetasList.removeAll(erased);

View File

@ -1,5 +1,6 @@
package de.dhbwstuttgart.typeinference.unify.interfaces; package de.dhbwstuttgart.typeinference.unify.interfaces;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;

View File

@ -3,6 +3,8 @@ package de.dhbwstuttgart.typeinference.unify.model;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import java.lang.reflect.Modifier;
import java.sql.Array;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -20,7 +22,12 @@ import com.google.common.collect.Ordering;
//PL 18-02-05/18-04-05 Unifier durch Matcher ersetzt //PL 18-02-05/18-04-05 Unifier durch Matcher ersetzt
//muss greater noch ersetzt werden ja erledigt 18--04-05 //muss greater noch ersetzt werden ja erledigt 18--04-05
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.parser.SourceLoc; import de.dhbwstuttgart.parser.SourceLoc;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.unify.MartelliMontanariUnify; import de.dhbwstuttgart.typeinference.unify.MartelliMontanariUnify;
import de.dhbwstuttgart.typeinference.unify.Match; import de.dhbwstuttgart.typeinference.unify.Match;
@ -29,6 +36,7 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify;
import de.dhbwstuttgart.util.Pair; import de.dhbwstuttgart.util.Pair;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
import org.apache.commons.io.output.NullWriter;
/** /**
* The finite closure for the type unification * The finite closure for the type unification
@ -37,6 +45,8 @@ import org.antlr.v4.runtime.Token;
public class FiniteClosure //extends Ordering<UnifyType> //entfernt PL 2018-12-11 public class FiniteClosure //extends Ordering<UnifyType> //entfernt PL 2018-12-11
implements IFiniteClosure { implements IFiniteClosure {
final JavaTXCompiler compiler;
Writer logFile; Writer logFile;
static Boolean log = false; static Boolean log = false;
public void setLogTrue() { public void setLogTrue() {
@ -71,7 +81,8 @@ implements IFiniteClosure {
/** /**
* Creates a new instance using the inheritance tree defined in the pairs. * Creates a new instance using the inheritance tree defined in the pairs.
*/ */
public FiniteClosure(Set<UnifyPair> pairs, Writer logFile) { public FiniteClosure(Set<UnifyPair> pairs, Writer logFile, JavaTXCompiler compiler) {
this.compiler = compiler;
this.logFile = logFile; this.logFile = logFile;
this.pairs = new HashSet<>(pairs); this.pairs = new HashSet<>(pairs);
inheritanceGraph = new HashMap<UnifyType, Node<UnifyType>>(); inheritanceGraph = new HashMap<UnifyType, Node<UnifyType>>();
@ -130,6 +141,10 @@ implements IFiniteClosure {
} }
} }
public FiniteClosure(Set<UnifyPair> constraints, Writer writer) {
this(constraints, writer, null);
}
void testSmaller() { void testSmaller() {
UnifyType tq1, tq2, tq3; UnifyType tq1, tq2, tq3;
tq1 = new ExtendsType(PlaceholderType.freshPlaceholder()); tq1 = new ExtendsType(PlaceholderType.freshPlaceholder());
@ -596,7 +611,7 @@ implements IFiniteClosure {
return new HashSet<>(); return new HashSet<>();
return strInheritanceGraph.get(typeName).stream().map(x -> x.getContent()).collect(Collectors.toCollection(HashSet::new)); return strInheritanceGraph.get(typeName).stream().map(x -> x.getContent()).collect(Collectors.toCollection(HashSet::new));
} }
@Override @Override
public Optional<UnifyType> getLeftHandedType(String typeName) { public Optional<UnifyType> getLeftHandedType(String typeName) {
if(!strInheritanceGraph.containsKey(typeName)) if(!strInheritanceGraph.containsKey(typeName))
@ -684,7 +699,7 @@ implements IFiniteClosure {
*/ */
public int compare (UnifyType left, UnifyType right, PairOperator pairop) { public int compare (UnifyType left, UnifyType right, PairOperator pairop) {
//try {logFile.write("left: "+ left + " right: " + right + " pairop: " + pairop);} catch (IOException ie) {} try {logFile.write("left: "+ left + " right: " + right + " pairop: " + pairop +"\n");} catch (IOException ie) {}
if (left.getName().equals("Matrix") || right.getName().equals("Matrix")) if (left.getName().equals("Matrix") || right.getName().equals("Matrix"))
System.out.println(""); System.out.println("");
/* /*
@ -741,15 +756,15 @@ implements IFiniteClosure {
HashSet<UnifyPair> hs = new HashSet<>(); HashSet<UnifyPair> hs = new HashSet<>();
hs.add(up); hs.add(up);
Set<UnifyPair> smallerRes = unifyTask.applyTypeUnificationRules(hs, this); Set<UnifyPair> smallerRes = unifyTask.applyTypeUnificationRules(hs, this);
/*
//if (left.getName().equals("Matrix") || right.getName().equals("Matrix")) //if (left.getName().equals("Vector") || right.getName().equals("AbstractList"))
{try { {try {
logFile.write("\nsmallerRes: " + smallerRes);//"smallerHash: " + greaterHash.toString()); logFile.write("\nsmallerRes: " + smallerRes);//"smallerHash: " + greaterHash.toString());
logFile.flush(); logFile.flush();
} }
catch (IOException e) { catch (IOException e) {
System.err.println("no LogFile");}} System.err.println("no LogFile");}}
*/
//Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok. //Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok.
Predicate<UnifyPair> delFun = x -> !((x.getLhsType() instanceof PlaceholderType || Predicate<UnifyPair> delFun = x -> !((x.getLhsType() instanceof PlaceholderType ||
x.getRhsType() instanceof PlaceholderType) x.getRhsType() instanceof PlaceholderType)
@ -757,6 +772,12 @@ implements IFiniteClosure {
((WildcardType)x.getLhsType()).getWildcardedType().equals(x.getRhsType())) ((WildcardType)x.getLhsType()).getWildcardedType().equals(x.getRhsType()))
); );
long smallerLen = smallerRes.stream().filter(delFun).count(); long smallerLen = smallerRes.stream().filter(delFun).count();
try {
logFile.write("\nsmallerLen: " + smallerLen +"\n");
logFile.flush();
}
catch (IOException e) {
System.err.println("no LogFile");}
if (smallerLen == 0) return -1; if (smallerLen == 0) return -1;
else { else {
up = new UnifyPair(right, left, pairop); up = new UnifyPair(right, left, pairop);
@ -764,15 +785,15 @@ implements IFiniteClosure {
hs = new HashSet<>(); hs = new HashSet<>();
hs.add(up); hs.add(up);
Set<UnifyPair> greaterRes = unifyTask.applyTypeUnificationRules(hs, this); Set<UnifyPair> greaterRes = unifyTask.applyTypeUnificationRules(hs, this);
/*
//if (left.getName().equals("Matrix") || right.getName().equals("Matrix")) //if (left.getName().equals("Vector") || right.getName().equals("AbstractList"))
{try { {try {
logFile.write("\ngreaterRes: " + greaterRes);//"smallerHash: " + greaterHash.toString()); logFile.write("\ngreaterRes: " + greaterRes);//"smallerHash: " + greaterHash.toString());
logFile.flush(); logFile.flush();
} }
catch (IOException e) { catch (IOException e) {
System.err.println("no LogFile");}} System.err.println("no LogFile");}}
*/
//Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok. //Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok.
long greaterLen = greaterRes.stream().filter(delFun).count(); long greaterLen = greaterRes.stream().filter(delFun).count();
if (greaterLen == 0) return 1; if (greaterLen == 0) return 1;

View File

@ -0,0 +1,49 @@
package de.dhbwstuttgart.typeinference.unify.model;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FunInterfaceType extends ReferenceType {
final List<UnifyType> intfArgTypes;
final UnifyType intfReturnType;
final List<String> generics;
public FunInterfaceType(String name, TypeParams params, List<UnifyType> intfArgTypes, UnifyType intfReturnType, List<String> generics) {
super(name, params);
this.intfArgTypes = intfArgTypes;
this.intfReturnType = intfReturnType;
this.generics = generics;
}
public List<UnifyType> getFunctionalInterfaceTypeArguments(UnifyType t) {
if (t instanceof FunNType) {
var ret = new ArrayList<UnifyType>();
if (t.getTypeParams().size() > 0) {
ret.add(t.getTypeParams().get(t.getTypeParams().size() - 1));
ret.addAll(Arrays.asList(t.getTypeParams().get()).subList(0, t.getTypeParams().size() - 1));
}
return ret;
}
var args = new ArrayList<UnifyType>();
args.add(intfReturnType);
args.addAll(intfArgTypes);
// TODO There might be a better way of dealing with this
var i = 0;
for (var generic : generics) {
for (var j = 0; j < args.size(); j++) {
if (args.get(j).getName().equals(generic))
args.set(j, t.getTypeParams().get(i));
}
i += 1;
}
return args;
}
}

Some files were not shown because too many files have changed in this diff Show More