forked from JavaTX/JavaCompilerCore
Compare commits
3 Commits
24bcdf9dd8
...
5bee05ac43
Author | SHA1 | Date | |
---|---|---|---|
5bee05ac43 | |||
518a09b00f | |||
c8a043219e |
BIN
JavaTXcompiler-1.1-jar-with-dependencies.jar
Normal file
BIN
JavaTXcompiler-1.1-jar-with-dependencies.jar
Normal file
Binary file not shown.
BIN
JavaTXcompiler-1.2-jar-with-dependencies.jar
Normal file
BIN
JavaTXcompiler-1.2-jar-with-dependencies.jar
Normal file
Binary file not shown.
10
compile.sh
10
compile.sh
@ -3,10 +3,10 @@
|
|||||||
SRCDIR="javatx-src/main/java"
|
SRCDIR="javatx-src/main/java"
|
||||||
DESTDIR="out"
|
DESTDIR="out"
|
||||||
JAVAC_FLAGS="-g:none -nowarn"
|
JAVAC_FLAGS="-g:none -nowarn"
|
||||||
JAVATX_COMPILER_PATH="JavaTXcompiler-1.1-jar-with-dependencies.jar"
|
JAVATX_COMPILER_PATH="JavaTXcompiler-1.2-jar-with-dependencies.jar"
|
||||||
|
|
||||||
#remove all files, if the script is called with parameter "clear"
|
#remove all files, if the script is called with parameter "clear"
|
||||||
if [ "$1" = "clear" ]; then
|
if [ "$1" = "clean" ]; then
|
||||||
rm -r "$DESTDIR"
|
rm -r "$DESTDIR"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
@ -54,11 +54,15 @@ done
|
|||||||
if [ "${#JAV_CHANGED[@]}" -ne 0 ]; then
|
if [ "${#JAV_CHANGED[@]}" -ne 0 ]; then
|
||||||
for ((i = 0; i < "${#JAV_CHANGED[@]}"; i++)); do
|
for ((i = 0; i < "${#JAV_CHANGED[@]}"; i++)); do
|
||||||
java -jar $JAVATX_COMPILER_PATH -d "${JAV_CLASSES[i]%/*}" -cp "$SRCDIR:$DESTDIR:target/dependencies/" "${JAV_CHANGED[i]}"
|
java -jar $JAVATX_COMPILER_PATH -d "${JAV_CLASSES[i]%/*}" -cp "$SRCDIR:$DESTDIR:target/dependencies/" "${JAV_CHANGED[i]}"
|
||||||
|
if [ $? -eq 1 ]; then
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${#JAVA_CHANGED[@]}" -ne 0 ]; then
|
if [ "${#JAVA_CHANGED[@]}" -ne 0 ]; then
|
||||||
javac -d $DESTDIR -cp "$SRCDIR:$DESTDIR:target/dependencies/*" $JFLAGS "${JAVA_CHANGED[@]}"
|
echo "javac -d $DESTDIR -cp "$SRCDIR:$DESTDIR:target/dependencies/*" $JAVAC_FLAGS ${JAVA_CHANGED[@]}"
|
||||||
|
javac -d $DESTDIR -cp "$SRCDIR:$DESTDIR:target/dependencies/*" $JAVAC_FLAGS "${JAVA_CHANGED[@]}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,241 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2013 Terence Parr, Sam Harwell
|
||||||
|
Copyright (c) 2017 Ivan Kochurkin (upgrade to Java 8)
|
||||||
|
Copyright (c) 2021 Michał Lorek (upgrade to Java 11)
|
||||||
|
Copyright (c) 2022 Michał Lorek (upgrade to Java 17)
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
lexer grammar Java17Lexer;
|
||||||
|
|
||||||
|
// Keywords
|
||||||
|
|
||||||
|
ABSTRACT: 'abstract';
|
||||||
|
ASSERT: 'assert';
|
||||||
|
BOOLEAN: 'boolean';
|
||||||
|
BREAK: 'break';
|
||||||
|
BYTE: 'byte';
|
||||||
|
CASE: 'case';
|
||||||
|
CATCH: 'catch';
|
||||||
|
CHAR: 'char';
|
||||||
|
CLASS: 'class';
|
||||||
|
CONST: 'const';
|
||||||
|
CONTINUE: 'continue';
|
||||||
|
DEFAULT: 'default';
|
||||||
|
DO: 'do';
|
||||||
|
DOUBLE: 'double';
|
||||||
|
ELSE: 'else';
|
||||||
|
ENUM: 'enum';
|
||||||
|
EXTENDS: 'extends';
|
||||||
|
FINAL: 'final';
|
||||||
|
FINALLY: 'finally';
|
||||||
|
FLOAT: 'float';
|
||||||
|
FOR: 'for';
|
||||||
|
IF: 'if';
|
||||||
|
GOTO: 'goto';
|
||||||
|
IMPLEMENTS: 'implements';
|
||||||
|
IMPORT: 'import';
|
||||||
|
INSTANCEOF: 'instanceof';
|
||||||
|
INT: 'int';
|
||||||
|
INTERFACE: 'interface';
|
||||||
|
LONG: 'long';
|
||||||
|
NATIVE: 'native';
|
||||||
|
NEW: 'new';
|
||||||
|
PACKAGE: 'package';
|
||||||
|
PRIVATE: 'private';
|
||||||
|
PROTECTED: 'protected';
|
||||||
|
PUBLIC: 'public';
|
||||||
|
RETURN: 'return';
|
||||||
|
SHORT: 'short';
|
||||||
|
STATIC: 'static';
|
||||||
|
STRICTFP: 'strictfp';
|
||||||
|
SUPER: 'super';
|
||||||
|
SWITCH: 'switch';
|
||||||
|
SYNCHRONIZED: 'synchronized';
|
||||||
|
THIS: 'this';
|
||||||
|
THROW: 'throw';
|
||||||
|
THROWS: 'throws';
|
||||||
|
TRANSIENT: 'transient';
|
||||||
|
TRY: 'try';
|
||||||
|
VOID: 'void';
|
||||||
|
VOLATILE: 'volatile';
|
||||||
|
WHILE: 'while';
|
||||||
|
|
||||||
|
// Module related keywords
|
||||||
|
MODULE: 'module';
|
||||||
|
OPEN: 'open';
|
||||||
|
REQUIRES: 'requires';
|
||||||
|
EXPORTS: 'exports';
|
||||||
|
OPENS: 'opens';
|
||||||
|
TO: 'to';
|
||||||
|
USES: 'uses';
|
||||||
|
PROVIDES: 'provides';
|
||||||
|
WITH: 'with';
|
||||||
|
TRANSITIVE: 'transitive';
|
||||||
|
|
||||||
|
// Local Variable Type Inference
|
||||||
|
VAR: 'var'; // reserved type name
|
||||||
|
|
||||||
|
// Switch Expressions
|
||||||
|
YIELD: 'yield'; // reserved type name from Java 14
|
||||||
|
|
||||||
|
// Records
|
||||||
|
RECORD: 'record';
|
||||||
|
|
||||||
|
// Sealed Classes
|
||||||
|
SEALED: 'sealed';
|
||||||
|
PERMITS: 'permits';
|
||||||
|
NON_SEALED: 'non-sealed';
|
||||||
|
|
||||||
|
// Literals
|
||||||
|
|
||||||
|
DECIMAL_LITERAL: ('0' | [1-9] (Digits? | '_'+ Digits)) [lL]?;
|
||||||
|
HEX_LITERAL: '0' [xX] [0-9a-fA-F] ([0-9a-fA-F_]* [0-9a-fA-F])? [lL]?;
|
||||||
|
OCT_LITERAL: '0' '_'* [0-7] ([0-7_]* [0-7])? [lL]?;
|
||||||
|
BINARY_LITERAL: '0' [bB] [01] ([01_]* [01])? [lL]?;
|
||||||
|
|
||||||
|
FLOAT_LITERAL: (Digits '.' Digits? | '.' Digits) ExponentPart? [fFdD]?
|
||||||
|
| Digits (ExponentPart [fFdD]? | [fFdD])
|
||||||
|
;
|
||||||
|
|
||||||
|
HEX_FLOAT_LITERAL: '0' [xX] (HexDigits '.'? | HexDigits? '.' HexDigits) [pP] [+-]? Digits [fFdD]?;
|
||||||
|
|
||||||
|
BOOL_LITERAL: 'true'
|
||||||
|
| 'false'
|
||||||
|
;
|
||||||
|
|
||||||
|
CHAR_LITERAL: '\'' (~['\\\r\n] | EscapeSequence) '\'';
|
||||||
|
|
||||||
|
STRING_LITERAL: '"' (~["\\\r\n] | EscapeSequence)* '"';
|
||||||
|
|
||||||
|
TEXT_BLOCK: '"""' [ \t]* [\r\n] (. | EscapeSequence)*? '"""';
|
||||||
|
|
||||||
|
NULL_LITERAL: 'null';
|
||||||
|
|
||||||
|
// Separators
|
||||||
|
|
||||||
|
LPAREN: '(';
|
||||||
|
RPAREN: ')';
|
||||||
|
LBRACE: '{';
|
||||||
|
RBRACE: '}';
|
||||||
|
LBRACK: '[';
|
||||||
|
RBRACK: ']';
|
||||||
|
SEMI: ';';
|
||||||
|
COMMA: ',';
|
||||||
|
DOT: '.';
|
||||||
|
|
||||||
|
// Operators
|
||||||
|
|
||||||
|
ASSIGN: '=';
|
||||||
|
GT: '>';
|
||||||
|
LT: '<';
|
||||||
|
BANG: '!';
|
||||||
|
TILDE: '~';
|
||||||
|
QUESTION: '?';
|
||||||
|
COLON: ':';
|
||||||
|
EQUAL: '==';
|
||||||
|
LE: '<=';
|
||||||
|
GE: '>=';
|
||||||
|
NOTEQUAL: '!=';
|
||||||
|
AND: '&&';
|
||||||
|
OR: '||';
|
||||||
|
INC: '++';
|
||||||
|
DEC: '--';
|
||||||
|
ADD: '+';
|
||||||
|
SUB: '-';
|
||||||
|
MUL: '*';
|
||||||
|
DIV: '/';
|
||||||
|
BITAND: '&';
|
||||||
|
BITOR: '|';
|
||||||
|
CARET: '^';
|
||||||
|
MOD: '%';
|
||||||
|
|
||||||
|
ADD_ASSIGN: '+=';
|
||||||
|
SUB_ASSIGN: '-=';
|
||||||
|
MUL_ASSIGN: '*=';
|
||||||
|
DIV_ASSIGN: '/=';
|
||||||
|
AND_ASSIGN: '&=';
|
||||||
|
OR_ASSIGN: '|=';
|
||||||
|
XOR_ASSIGN: '^=';
|
||||||
|
MOD_ASSIGN: '%=';
|
||||||
|
LSHIFT_ASSIGN: '<<=';
|
||||||
|
RSHIFT_ASSIGN: '>>=';
|
||||||
|
URSHIFT_ASSIGN: '>>>=';
|
||||||
|
|
||||||
|
// Java 8 tokens
|
||||||
|
|
||||||
|
ARROW: '->';
|
||||||
|
COLONCOLON: '::';
|
||||||
|
|
||||||
|
// Additional symbols not defined in the lexical specification
|
||||||
|
|
||||||
|
AT: '@';
|
||||||
|
ELLIPSIS: '...';
|
||||||
|
|
||||||
|
// Whitespace and comments
|
||||||
|
|
||||||
|
WS: [ \t\r\n\u000C]+ -> channel(HIDDEN);
|
||||||
|
COMMENT: '/*' .*? '*/' -> channel(HIDDEN);
|
||||||
|
LINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN);
|
||||||
|
|
||||||
|
// Identifiers
|
||||||
|
|
||||||
|
IDENTIFIER: Letter LetterOrDigit*;
|
||||||
|
|
||||||
|
// Fragment rules
|
||||||
|
|
||||||
|
fragment ExponentPart
|
||||||
|
: [eE] [+-]? Digits
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment EscapeSequence
|
||||||
|
: '\\' [btnfr"'\\]
|
||||||
|
| '\\' ([0-3]? [0-7])? [0-7]
|
||||||
|
| '\\' 'u'+ HexDigit HexDigit HexDigit HexDigit
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment HexDigits
|
||||||
|
: HexDigit ((HexDigit | '_')* HexDigit)?
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment HexDigit
|
||||||
|
: [0-9a-fA-F]
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment Digits
|
||||||
|
: [0-9] ([0-9_]* [0-9])?
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment LetterOrDigit
|
||||||
|
: Letter
|
||||||
|
| [0-9]
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment Letter
|
||||||
|
: [a-zA-Z$_] // these are the "java letters" below 0x7F
|
||||||
|
| ~[\u0000-\u007F\uD800-\uDBFF] // covers all characters above 0x7F which are not a surrogate
|
||||||
|
| [\uD800-\uDBFF] [\uDC00-\uDFFF] // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
|
||||||
|
;
|
@ -0,0 +1,816 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2013 Terence Parr, Sam Harwell
|
||||||
|
Copyright (c) 2017 Ivan Kochurkin (upgrade to Java 8)
|
||||||
|
Copyright (c) 2021 Michał Lorek (upgrade to Java 11)
|
||||||
|
Copyright (c) 2022 Michał Lorek (upgrade to Java 17)
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
parser grammar Java17Parser;
|
||||||
|
|
||||||
|
options { tokenVocab=Java17Lexer; }
|
||||||
|
|
||||||
|
sourceFile
|
||||||
|
: packageDeclaration? importDeclaration* classOrInterface* # srcfile
|
||||||
|
| moduleDeclaration EOF # moduledecl
|
||||||
|
;
|
||||||
|
|
||||||
|
packageDeclaration
|
||||||
|
: annotation* PACKAGE qualifiedName ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
importDeclaration
|
||||||
|
: IMPORT STATIC? qualifiedName ('.' '*')? ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
classOrInterface
|
||||||
|
: classOrInterfaceModifier*
|
||||||
|
(classDeclaration | enumDeclaration | interfaceDeclaration | annotationTypeDeclaration | recordDeclaration) # classorinterfacedecl
|
||||||
|
| ';' # noclassorinterface
|
||||||
|
;
|
||||||
|
|
||||||
|
modifier
|
||||||
|
: classOrInterfaceModifier
|
||||||
|
| NATIVE
|
||||||
|
| SYNCHRONIZED
|
||||||
|
| TRANSIENT
|
||||||
|
| VOLATILE
|
||||||
|
;
|
||||||
|
|
||||||
|
classOrInterfaceModifier
|
||||||
|
: annotation
|
||||||
|
| PUBLIC
|
||||||
|
| PROTECTED
|
||||||
|
| PRIVATE
|
||||||
|
| STATIC
|
||||||
|
| ABSTRACT
|
||||||
|
| FINAL // FINAL for class only -- does not apply to interfaces
|
||||||
|
| STRICTFP
|
||||||
|
| SEALED // Java17
|
||||||
|
| NON_SEALED // Java17
|
||||||
|
;
|
||||||
|
|
||||||
|
variableModifier
|
||||||
|
: FINAL # finalvarmod
|
||||||
|
| annotation # annotationvarmod
|
||||||
|
;
|
||||||
|
|
||||||
|
classDeclaration
|
||||||
|
: CLASS identifier genericDeclarationList?
|
||||||
|
(EXTENDS typeType)?
|
||||||
|
(IMPLEMENTS typeList)?
|
||||||
|
(PERMITS typeList)? // Java17
|
||||||
|
classBody
|
||||||
|
;
|
||||||
|
|
||||||
|
genericDeclarationList
|
||||||
|
: '<' genericTypeVar (',' genericTypeVar)* '>'
|
||||||
|
;
|
||||||
|
|
||||||
|
genericTypeVar
|
||||||
|
: annotation* identifier ((EXTENDS | IMPLEMENTS) annotation* typeBound)?
|
||||||
|
;
|
||||||
|
|
||||||
|
typeBound
|
||||||
|
: typeType ('&' typeType)*
|
||||||
|
;
|
||||||
|
|
||||||
|
enumDeclaration
|
||||||
|
: ENUM identifier (IMPLEMENTS typeList)? '{' enumConstants? ','? enumBodyDeclarations? '}'
|
||||||
|
;
|
||||||
|
|
||||||
|
enumConstants
|
||||||
|
: enumConstant (',' enumConstant)*
|
||||||
|
;
|
||||||
|
|
||||||
|
enumConstant
|
||||||
|
: annotation* identifier arguments? classBody?
|
||||||
|
;
|
||||||
|
|
||||||
|
enumBodyDeclarations
|
||||||
|
: ';' classBodyDeclaration*
|
||||||
|
;
|
||||||
|
|
||||||
|
interfaceDeclaration
|
||||||
|
: INTERFACE identifier genericDeclarationList? (EXTENDS typeList)? (PERMITS typeList)? interfaceBody
|
||||||
|
;
|
||||||
|
|
||||||
|
classBody
|
||||||
|
: '{' classBodyDeclaration* '}'
|
||||||
|
;
|
||||||
|
|
||||||
|
interfaceBody
|
||||||
|
: '{' interfaceBodyDeclaration* '}'
|
||||||
|
;
|
||||||
|
|
||||||
|
classBodyDeclaration
|
||||||
|
: ';' # emptyclassbody
|
||||||
|
| STATIC? block # classblock
|
||||||
|
| modifier* memberDeclaration # memberdecl
|
||||||
|
;
|
||||||
|
|
||||||
|
memberDeclaration
|
||||||
|
: classOrInterface # memberclassorinterface
|
||||||
|
| fieldDeclaration # memberfield
|
||||||
|
| method # membermethod
|
||||||
|
| constructor # memberconstructor
|
||||||
|
;
|
||||||
|
|
||||||
|
method
|
||||||
|
: methodDeclaration # methoddecl
|
||||||
|
| genericMethodDeclaration # genericmethod
|
||||||
|
;
|
||||||
|
|
||||||
|
/* We use rule this even for void methods which cannot have [] after parameters.
|
||||||
|
This simplifies grammar and we can consider void to be a type, which
|
||||||
|
renders the [] matching as a context-sensitive issue or a semantic check
|
||||||
|
for invalid return type after parsing.
|
||||||
|
*/
|
||||||
|
methodDeclaration
|
||||||
|
: methodHeader
|
||||||
|
(THROWS exceptionList)?
|
||||||
|
methodBody
|
||||||
|
;
|
||||||
|
|
||||||
|
methodHeader
|
||||||
|
: refType? identifier formalParameters ('[' ']')*
|
||||||
|
;
|
||||||
|
|
||||||
|
methodBody
|
||||||
|
: block # methodblock
|
||||||
|
| ';' # emptymethod
|
||||||
|
;
|
||||||
|
|
||||||
|
refType
|
||||||
|
: typeType # refType2
|
||||||
|
| VOID # refvoid
|
||||||
|
;
|
||||||
|
|
||||||
|
genericMethodDeclaration
|
||||||
|
: genericDeclarationList methodDeclaration
|
||||||
|
;
|
||||||
|
|
||||||
|
constructor
|
||||||
|
: genericConstructorDeclaration # genericconstructor
|
||||||
|
| constructorDeclaration # constructordecl
|
||||||
|
;
|
||||||
|
|
||||||
|
genericConstructorDeclaration
|
||||||
|
: genericDeclarationList constructorDeclaration
|
||||||
|
;
|
||||||
|
|
||||||
|
constructorDeclaration
|
||||||
|
: identifier formalParameters (THROWS exceptionList)? constructorBody=block
|
||||||
|
;
|
||||||
|
|
||||||
|
fieldDeclaration
|
||||||
|
: typeType? variableDeclarators ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
interfaceBodyDeclaration
|
||||||
|
: modifier* interfaceMemberDeclaration # interfacemember
|
||||||
|
| ';' # emptyinterface
|
||||||
|
;
|
||||||
|
|
||||||
|
interfaceMemberDeclaration
|
||||||
|
: constDeclaration # interfaceconst
|
||||||
|
| interfaceMethodDeclaration # interfacemethod
|
||||||
|
| genericInterfaceMethodDeclaration # genericinterfacemethod
|
||||||
|
| classOrInterface # subclassorinterface
|
||||||
|
;
|
||||||
|
|
||||||
|
constDeclaration
|
||||||
|
: typeType? constantDeclarator (',' constantDeclarator)* ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
constantDeclarator
|
||||||
|
: identifier ('[' ']')* '=' variableInitializer
|
||||||
|
;
|
||||||
|
|
||||||
|
// Early versions of Java allows brackets after the method name, eg.
|
||||||
|
// public int[] return2DArray() [] { ... }
|
||||||
|
// is the same as
|
||||||
|
// public int[][] return2DArray() { ... }
|
||||||
|
interfaceMethodDeclaration
|
||||||
|
: interfaceMethodModifier* interfaceCommonBodyDeclaration
|
||||||
|
;
|
||||||
|
|
||||||
|
// Java8
|
||||||
|
interfaceMethodModifier
|
||||||
|
: annotation
|
||||||
|
| PUBLIC
|
||||||
|
| ABSTRACT
|
||||||
|
| DEFAULT
|
||||||
|
| STATIC
|
||||||
|
| STRICTFP
|
||||||
|
;
|
||||||
|
|
||||||
|
genericInterfaceMethodDeclaration
|
||||||
|
: interfaceMethodModifier* genericDeclarationList interfaceCommonBodyDeclaration
|
||||||
|
;
|
||||||
|
|
||||||
|
interfaceCommonBodyDeclaration
|
||||||
|
: annotation* refType? identifier formalParameters ('[' ']')* (THROWS exceptionList)? methodBody
|
||||||
|
;
|
||||||
|
|
||||||
|
variableDeclarators
|
||||||
|
: variableDeclarator (',' variableDeclarator)*
|
||||||
|
;
|
||||||
|
|
||||||
|
variableDeclarator
|
||||||
|
: variableDeclaratorId ('=' variableInitializer)?
|
||||||
|
;
|
||||||
|
|
||||||
|
variableDeclaratorId
|
||||||
|
: identifier ('[' ']')*
|
||||||
|
;
|
||||||
|
|
||||||
|
variableInitializer
|
||||||
|
: arrayInitializer
|
||||||
|
| expression
|
||||||
|
;
|
||||||
|
|
||||||
|
arrayInitializer
|
||||||
|
: '{' (variableInitializer (',' variableInitializer)* (',')? )? '}'
|
||||||
|
;
|
||||||
|
|
||||||
|
classOrInterfaceType
|
||||||
|
: (identifier typeArguments? '.')* typeIdentifier typeArguments?
|
||||||
|
;
|
||||||
|
|
||||||
|
typeArgument
|
||||||
|
: typeType
|
||||||
|
| wildcardType
|
||||||
|
;
|
||||||
|
|
||||||
|
wildcardType
|
||||||
|
: annotation* '?' (extendsWildcardType | superWildcardType)?
|
||||||
|
;
|
||||||
|
|
||||||
|
extendsWildcardType
|
||||||
|
: EXTENDS typeType
|
||||||
|
;
|
||||||
|
|
||||||
|
superWildcardType
|
||||||
|
: SUPER typeType
|
||||||
|
;
|
||||||
|
|
||||||
|
qualifiedNameList
|
||||||
|
: qualifiedName (',' qualifiedName)*
|
||||||
|
;
|
||||||
|
|
||||||
|
exceptionList
|
||||||
|
: qualifiedNameList
|
||||||
|
;
|
||||||
|
|
||||||
|
formalParameters
|
||||||
|
: '(' ( receiverParameter?
|
||||||
|
| receiverParameter (',' formalParameterList)?
|
||||||
|
| formalParameterList?
|
||||||
|
) ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
receiverParameter
|
||||||
|
: typeType? (identifier '.')* THIS
|
||||||
|
;
|
||||||
|
|
||||||
|
formalParameterList
|
||||||
|
: formalParameter (',' formalParameter)* (',' lastFormalParameter)?
|
||||||
|
| lastFormalParameter
|
||||||
|
;
|
||||||
|
|
||||||
|
formalParameter
|
||||||
|
: variableModifier* typeType? variableDeclaratorId
|
||||||
|
| pattern // Pattern matching for Methods
|
||||||
|
;
|
||||||
|
|
||||||
|
lastFormalParameter
|
||||||
|
: variableModifier* typeType? annotation* '...' variableDeclaratorId
|
||||||
|
;
|
||||||
|
|
||||||
|
// local variable type inference
|
||||||
|
lambdaLVTIList
|
||||||
|
: lambdaLVTIParameter (',' lambdaLVTIParameter)*
|
||||||
|
;
|
||||||
|
|
||||||
|
lambdaLVTIParameter
|
||||||
|
: variableModifier* VAR identifier
|
||||||
|
;
|
||||||
|
|
||||||
|
qualifiedName
|
||||||
|
: identifier ('.' identifier)*
|
||||||
|
;
|
||||||
|
|
||||||
|
literal
|
||||||
|
: integerLiteral # intLiteral
|
||||||
|
| floatLiteral # fltLiteral
|
||||||
|
| CHAR_LITERAL # charLiteral
|
||||||
|
| STRING_LITERAL # stringLiteral
|
||||||
|
| BOOL_LITERAL # boolLiteral
|
||||||
|
| NULL_LITERAL # nullLiteral
|
||||||
|
| TEXT_BLOCK # textBlock // Java17
|
||||||
|
;
|
||||||
|
|
||||||
|
integerLiteral
|
||||||
|
: DECIMAL_LITERAL
|
||||||
|
| HEX_LITERAL
|
||||||
|
| OCT_LITERAL
|
||||||
|
| BINARY_LITERAL
|
||||||
|
;
|
||||||
|
|
||||||
|
floatLiteral
|
||||||
|
: FLOAT_LITERAL
|
||||||
|
| HEX_FLOAT_LITERAL
|
||||||
|
;
|
||||||
|
|
||||||
|
// ANNOTATIONS
|
||||||
|
altAnnotationQualifiedName
|
||||||
|
: (identifier DOT)* '@' identifier
|
||||||
|
;
|
||||||
|
|
||||||
|
annotation
|
||||||
|
: ('@' qualifiedName | altAnnotationQualifiedName) ('(' ( elementValuePairs | elementValue )? ')')?
|
||||||
|
;
|
||||||
|
|
||||||
|
elementValuePairs
|
||||||
|
: elementValuePair (',' elementValuePair)*
|
||||||
|
;
|
||||||
|
|
||||||
|
elementValuePair
|
||||||
|
: identifier '=' elementValue
|
||||||
|
;
|
||||||
|
|
||||||
|
elementValue
|
||||||
|
: expression
|
||||||
|
| annotation
|
||||||
|
| elementValueArrayInitializer
|
||||||
|
;
|
||||||
|
|
||||||
|
elementValueArrayInitializer
|
||||||
|
: '{' (elementValue (',' elementValue)*)? (',')? '}'
|
||||||
|
;
|
||||||
|
|
||||||
|
annotationTypeDeclaration
|
||||||
|
: '@' INTERFACE identifier annotationTypeBody
|
||||||
|
;
|
||||||
|
|
||||||
|
annotationTypeBody
|
||||||
|
: '{' (annotationTypeElementDeclaration)* '}'
|
||||||
|
;
|
||||||
|
|
||||||
|
annotationTypeElementDeclaration
|
||||||
|
: modifier* annotationTypeElementRest
|
||||||
|
| ';' // this is not allowed by the grammar, but apparently allowed by the actual compiler
|
||||||
|
;
|
||||||
|
|
||||||
|
annotationTypeElementRest
|
||||||
|
: typeType annotationMethodOrConstantRest ';'
|
||||||
|
| classOrInterface ';'?
|
||||||
|
;
|
||||||
|
|
||||||
|
annotationMethodOrConstantRest
|
||||||
|
: annotationMethodRest
|
||||||
|
| annotationConstantRest
|
||||||
|
;
|
||||||
|
|
||||||
|
annotationMethodRest
|
||||||
|
: identifier '(' ')' defaultValue?
|
||||||
|
;
|
||||||
|
|
||||||
|
annotationConstantRest
|
||||||
|
: variableDeclarators
|
||||||
|
;
|
||||||
|
|
||||||
|
defaultValue
|
||||||
|
: DEFAULT elementValue
|
||||||
|
;
|
||||||
|
|
||||||
|
// MODULES - Java9
|
||||||
|
|
||||||
|
moduleDeclaration
|
||||||
|
: OPEN? MODULE qualifiedName moduleBody
|
||||||
|
;
|
||||||
|
|
||||||
|
moduleBody
|
||||||
|
: '{' moduleDirective* '}'
|
||||||
|
;
|
||||||
|
|
||||||
|
moduleDirective
|
||||||
|
: REQUIRES requiresModifier* qualifiedName ';'
|
||||||
|
| EXPORTS qualifiedName (TO qualifiedName)? ';'
|
||||||
|
| OPENS qualifiedName (TO qualifiedName)? ';'
|
||||||
|
| USES qualifiedName ';'
|
||||||
|
| PROVIDES qualifiedName WITH qualifiedName ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
requiresModifier
|
||||||
|
: TRANSITIVE
|
||||||
|
| STATIC
|
||||||
|
;
|
||||||
|
|
||||||
|
// RECORDS - Java 17
|
||||||
|
|
||||||
|
recordDeclaration
|
||||||
|
: RECORD identifier genericDeclarationList? recordHeader
|
||||||
|
(IMPLEMENTS typeList)?
|
||||||
|
recordBody
|
||||||
|
;
|
||||||
|
|
||||||
|
recordHeader
|
||||||
|
: '(' recordComponentList? ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
recordComponentList
|
||||||
|
: recordComponent (',' recordComponent)*
|
||||||
|
;
|
||||||
|
|
||||||
|
recordComponent
|
||||||
|
: typeType? identifier
|
||||||
|
;
|
||||||
|
|
||||||
|
recordBody
|
||||||
|
: '{' classBodyDeclaration* '}'
|
||||||
|
;
|
||||||
|
|
||||||
|
// STATEMENTS / BLOCKS
|
||||||
|
|
||||||
|
block
|
||||||
|
: '{' blockStatement* '}'
|
||||||
|
;
|
||||||
|
|
||||||
|
blockStatement
|
||||||
|
: localVariableDeclaration ';'
|
||||||
|
| localTypeDeclaration
|
||||||
|
| statement
|
||||||
|
;
|
||||||
|
|
||||||
|
localVariableDeclaration
|
||||||
|
: variableModifier* (VAR | typeType) variableDeclarators
|
||||||
|
;
|
||||||
|
|
||||||
|
identifier
|
||||||
|
: IDENTIFIER
|
||||||
|
| MODULE
|
||||||
|
| OPEN
|
||||||
|
| REQUIRES
|
||||||
|
| EXPORTS
|
||||||
|
| OPENS
|
||||||
|
| TO
|
||||||
|
| USES
|
||||||
|
| PROVIDES
|
||||||
|
| WITH
|
||||||
|
| TRANSITIVE
|
||||||
|
| YIELD
|
||||||
|
| SEALED
|
||||||
|
| PERMITS
|
||||||
|
| RECORD
|
||||||
|
| VAR
|
||||||
|
;
|
||||||
|
|
||||||
|
typeIdentifier // Identifiers that are not restricted for type declarations
|
||||||
|
: IDENTIFIER
|
||||||
|
| MODULE
|
||||||
|
| OPEN
|
||||||
|
| REQUIRES
|
||||||
|
| EXPORTS
|
||||||
|
| OPENS
|
||||||
|
| TO
|
||||||
|
| USES
|
||||||
|
| PROVIDES
|
||||||
|
| WITH
|
||||||
|
| TRANSITIVE
|
||||||
|
| SEALED
|
||||||
|
| PERMITS
|
||||||
|
| RECORD
|
||||||
|
;
|
||||||
|
|
||||||
|
localTypeDeclaration
|
||||||
|
: classOrInterfaceModifier*
|
||||||
|
(classDeclaration | interfaceDeclaration | recordDeclaration)
|
||||||
|
| ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
statement
|
||||||
|
: blockLabel=block #blockstmt
|
||||||
|
| ASSERT expression (':' expression)? ';' #assertstmt
|
||||||
|
| IF parExpression statement (ELSE statement)? #conditionalstmt
|
||||||
|
| FOR '(' forControl ')' statement #forloop
|
||||||
|
| WHILE parExpression statement #whileloop
|
||||||
|
| DO statement WHILE parExpression ';' #dowhileloop
|
||||||
|
| TRY block (catchClause+ finallyBlock? | finallyBlock) #trycatchblock
|
||||||
|
| TRY resourceSpecification block catchClause* finallyBlock? #trycatchresource
|
||||||
|
| SWITCH parExpression '{' switchBlockStatementGroup* switchLabel* '}' #switchstmt
|
||||||
|
| SYNCHRONIZED parExpression block #synchronizedstmt
|
||||||
|
| RETURN expression? ';' #returnstmt
|
||||||
|
| THROW expression ';' #throwstmt
|
||||||
|
| BREAK identifier? ';' #breakstmt
|
||||||
|
| CONTINUE identifier? ';' #continuestmt
|
||||||
|
| YIELD expression ';' #yieldstmt // Java17
|
||||||
|
| SEMI #semistmt
|
||||||
|
| statementExpression=expression ';' #stmtexpression
|
||||||
|
| identifierLabel=identifier ':' statement #labeledstmt
|
||||||
|
;
|
||||||
|
|
||||||
|
catchClause
|
||||||
|
: CATCH '(' variableModifier* catchType? identifier ')' block
|
||||||
|
;
|
||||||
|
|
||||||
|
catchType
|
||||||
|
: qualifiedName ('|' qualifiedName)*
|
||||||
|
;
|
||||||
|
|
||||||
|
finallyBlock
|
||||||
|
: FINALLY block
|
||||||
|
;
|
||||||
|
|
||||||
|
resourceSpecification
|
||||||
|
: '(' resources ';'? ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
resources
|
||||||
|
: resource (';' resource)*
|
||||||
|
;
|
||||||
|
|
||||||
|
resource
|
||||||
|
: variableModifier* ( classOrInterfaceType? variableDeclaratorId | VAR identifier ) '=' expression
|
||||||
|
| identifier
|
||||||
|
;
|
||||||
|
|
||||||
|
/** Matches cases then statements, both of which are mandatory.
|
||||||
|
* To handle empty cases at the end, we add switchLabel* to statement.
|
||||||
|
*/
|
||||||
|
switchBlockStatementGroup
|
||||||
|
: switchLabel+ blockStatement+
|
||||||
|
;
|
||||||
|
|
||||||
|
switchLabel
|
||||||
|
: CASE constantExpression=expression ':' #switchLabelConst
|
||||||
|
| CASE enumConstantName=IDENTIFIER ':' #switchLabelEnum
|
||||||
|
| CASE pattern ':' #switchLabelPattern
|
||||||
|
| DEFAULT ':' #switchLabelDefault
|
||||||
|
;
|
||||||
|
|
||||||
|
forControl
|
||||||
|
: enhancedForControl
|
||||||
|
| forInit? ';' expression? ';' forUpdate=expressionList?
|
||||||
|
;
|
||||||
|
|
||||||
|
forInit
|
||||||
|
: localVariableDeclaration
|
||||||
|
| expressionList
|
||||||
|
;
|
||||||
|
|
||||||
|
enhancedForControl
|
||||||
|
: variableModifier* (typeType? | VAR) variableDeclaratorId ':' expression
|
||||||
|
;
|
||||||
|
|
||||||
|
// EXPRESSIONS
|
||||||
|
|
||||||
|
parExpression
|
||||||
|
: '(' expression ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
expressionList
|
||||||
|
: expression (',' expression)*
|
||||||
|
;
|
||||||
|
|
||||||
|
methodCall
|
||||||
|
: identifier '(' expressionList? ')'
|
||||||
|
| THIS '(' expressionList? ')'
|
||||||
|
| SUPER '(' expressionList? ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
expression
|
||||||
|
: primary #primaryExpression2
|
||||||
|
| expression bop='.'
|
||||||
|
(
|
||||||
|
identifier
|
||||||
|
| methodCall
|
||||||
|
| THIS
|
||||||
|
| NEW nonWildcardTypeArguments? innerCreator
|
||||||
|
| SUPER superSuffix
|
||||||
|
| explicitGenericInvocation
|
||||||
|
) # dottedexpression
|
||||||
|
| expression '[' expression ']' #arrayaccessexpression
|
||||||
|
| methodCall #methodcallexpression
|
||||||
|
| NEW creator #newinstanceexpression
|
||||||
|
| '(' annotation* typeType ('&' typeType)* ')' expression #castexpression
|
||||||
|
| expression postfix=('++' | '--') #postfixexpression
|
||||||
|
| prefix=('+'|'-'|'++'|'--'|'~'|'!') expression #prefixexpression
|
||||||
|
| expression bop=('*'|'/'|'%') expression #mathmuldivmodexpression
|
||||||
|
| expression bop=('+'|'-') expression #mathaddsubexpression
|
||||||
|
| expression ('<' '<' | '>' '>' '>' | '>' '>') expression #shiftexpression
|
||||||
|
| expression bop=('<=' | '>=' | '>' | '<') expression #relationalexpression
|
||||||
|
| expression bop=INSTANCEOF (typeType | pattern) #instanceofexpression
|
||||||
|
| expression bop=('==' | '!=') expression #equalityexpression
|
||||||
|
| expression bop='&' expression #bitwiseandexpression
|
||||||
|
| expression bop='^' expression #bitwisexorexpression
|
||||||
|
| expression bop='|' expression #bitwiseorexpression
|
||||||
|
| expression bop='&&' expression #andexpression
|
||||||
|
| expression bop='||' expression #orexpression
|
||||||
|
| <assoc=right> expression bop='?' expression ':' expression #conditionalassignexpression
|
||||||
|
| <assoc=right> expression
|
||||||
|
bop=('=' | '+=' | '-=' | '*=' | '/=' | '&=' | '|=' | '^=' | '>>=' | '>>>=' | '<<=' | '%=')
|
||||||
|
expression #assignexpression
|
||||||
|
| lambdaExpression #lambdaExpression2 // Java8
|
||||||
|
| switchExpression #switchExpression2 // Java17
|
||||||
|
|
||||||
|
// Java 8 methodReference
|
||||||
|
| expression '::' typeArguments? identifier #methodreferenceexpression
|
||||||
|
| typeType '::' (typeArguments? identifier | NEW) #methodorcreatorreferenceexpression
|
||||||
|
| classType '::' typeArguments? NEW #creatorreferenceexpression
|
||||||
|
;
|
||||||
|
|
||||||
|
// Java17
|
||||||
|
pattern
|
||||||
|
: primaryPattern #pPattern
|
||||||
|
| guardedPattern #gPattern
|
||||||
|
;
|
||||||
|
|
||||||
|
primaryPattern
|
||||||
|
: typePattern #tPattern
|
||||||
|
| recordPattern #rPattern
|
||||||
|
| '(' pattern ')' #enclosedPattern
|
||||||
|
;
|
||||||
|
|
||||||
|
recordPattern
|
||||||
|
: typeType recordStructurePattern identifier?
|
||||||
|
;
|
||||||
|
|
||||||
|
typePattern
|
||||||
|
: variableModifier* typeType identifier
|
||||||
|
;
|
||||||
|
|
||||||
|
recordStructurePattern
|
||||||
|
: '(' recordComponentPatternList? ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
recordComponentPatternElement
|
||||||
|
: pattern
|
||||||
|
| identifier
|
||||||
|
;
|
||||||
|
|
||||||
|
recordComponentPatternList
|
||||||
|
: pattern (',' pattern)*
|
||||||
|
;
|
||||||
|
|
||||||
|
// Java8
|
||||||
|
lambdaExpression
|
||||||
|
: lambdaParameters '->' lambdaBody
|
||||||
|
;
|
||||||
|
|
||||||
|
// Java8
|
||||||
|
lambdaParameters
|
||||||
|
: identifier
|
||||||
|
| '(' formalParameterList? ')'
|
||||||
|
| '(' identifier (',' identifier)* ')'
|
||||||
|
| '(' lambdaLVTIList? ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
// Java8
|
||||||
|
lambdaBody
|
||||||
|
: expression
|
||||||
|
| block
|
||||||
|
;
|
||||||
|
|
||||||
|
primary
|
||||||
|
: '(' expression ')' # primaryExpression
|
||||||
|
| THIS # primaryThis
|
||||||
|
| SUPER # primarySuper
|
||||||
|
| literal # primaryLiteral
|
||||||
|
| identifier # primaryIdentifier
|
||||||
|
| refType '.' CLASS # primaryClassref
|
||||||
|
| nonWildcardTypeArguments (explicitGenericInvocationSuffix | THIS arguments) # primaryInvocation
|
||||||
|
;
|
||||||
|
|
||||||
|
// Java17
|
||||||
|
switchExpression
|
||||||
|
: SWITCH parExpression '{' switchLabeledRule* '}'
|
||||||
|
;
|
||||||
|
|
||||||
|
// Java17
|
||||||
|
switchLabeledRule
|
||||||
|
: switchLabelCase switchRuleOutcome
|
||||||
|
;
|
||||||
|
|
||||||
|
switchLabelCase
|
||||||
|
: CASE expressionList (ARROW | COLON) #labeledRuleExprList
|
||||||
|
| CASE NULL_LITERAL (ARROW | COLON) #labeledRuleNull
|
||||||
|
| CASE pattern (ARROW | COLON) #labeledRulePattern
|
||||||
|
| DEFAULT (ARROW | COLON) #labeledRuleDefault
|
||||||
|
;
|
||||||
|
|
||||||
|
// Java20
|
||||||
|
guardedPattern
|
||||||
|
: primaryPattern WITH expression
|
||||||
|
;
|
||||||
|
|
||||||
|
// Java17
|
||||||
|
switchRuleOutcome
|
||||||
|
: block
|
||||||
|
| expression ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
classType
|
||||||
|
: (classOrInterfaceType '.')? annotation* identifier typeArguments?
|
||||||
|
;
|
||||||
|
|
||||||
|
creator
|
||||||
|
: nonWildcardTypeArguments createdName classCreatorRest
|
||||||
|
| createdName (arrayCreatorRest | classCreatorRest)
|
||||||
|
;
|
||||||
|
|
||||||
|
createdName
|
||||||
|
: identifier typeArgumentsOrDiamond?
|
||||||
|
| primitiveType
|
||||||
|
;
|
||||||
|
|
||||||
|
innerCreator
|
||||||
|
: identifier nonWildcardTypeArgumentsOrDiamond? classCreatorRest
|
||||||
|
;
|
||||||
|
|
||||||
|
arrayCreatorRest
|
||||||
|
: '[' (']' ('[' ']')* arrayInitializer | expression ']' ('[' expression ']')* ('[' ']')*)
|
||||||
|
;
|
||||||
|
|
||||||
|
classCreatorRest
|
||||||
|
: arguments classBody?
|
||||||
|
;
|
||||||
|
|
||||||
|
explicitGenericInvocation
|
||||||
|
: nonWildcardTypeArguments explicitGenericInvocationSuffix
|
||||||
|
;
|
||||||
|
|
||||||
|
typeArgumentsOrDiamond
|
||||||
|
: '<' '>'
|
||||||
|
| typeArguments
|
||||||
|
;
|
||||||
|
|
||||||
|
nonWildcardTypeArgumentsOrDiamond
|
||||||
|
: '<' '>'
|
||||||
|
| nonWildcardTypeArguments
|
||||||
|
;
|
||||||
|
|
||||||
|
nonWildcardTypeArguments
|
||||||
|
: '<' typeList '>'
|
||||||
|
;
|
||||||
|
|
||||||
|
typeList
|
||||||
|
: typeType (',' typeType)*
|
||||||
|
;
|
||||||
|
|
||||||
|
typeType
|
||||||
|
: annotation* (classOrInterfaceType | primitiveType) (annotation* '[' ']')*
|
||||||
|
;
|
||||||
|
|
||||||
|
primitiveType
|
||||||
|
: BOOLEAN
|
||||||
|
| CHAR
|
||||||
|
| BYTE
|
||||||
|
| SHORT
|
||||||
|
| INT
|
||||||
|
| LONG
|
||||||
|
| FLOAT
|
||||||
|
| DOUBLE
|
||||||
|
;
|
||||||
|
|
||||||
|
typeArguments
|
||||||
|
: '<' typeArgument (',' typeArgument)* '>'
|
||||||
|
;
|
||||||
|
|
||||||
|
superSuffix
|
||||||
|
: arguments
|
||||||
|
| '.' typeArguments? identifier arguments?
|
||||||
|
;
|
||||||
|
|
||||||
|
explicitGenericInvocationSuffix
|
||||||
|
: SUPER superSuffix
|
||||||
|
| identifier arguments
|
||||||
|
;
|
||||||
|
|
||||||
|
arguments
|
||||||
|
: '(' expressionList? ')'
|
||||||
|
;
|
10
javatx-src-backup/main/java/Main.java
Normal file
10
javatx-src-backup/main/java/Main.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import de.dhbwstuttgart.core.ConsoleInterface;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException, ClassNotFoundException {
|
||||||
|
ConsoleInterface.main(args);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package de.dhbwstuttgart.bytecode;
|
||||||
|
|
||||||
|
public class CodeGenException extends RuntimeException {
|
||||||
|
public CodeGenException(String cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
1521
javatx-src-backup/main/java/de/dhbwstuttgart/bytecode/Codegen.java
Normal file
1521
javatx-src-backup/main/java/de/dhbwstuttgart/bytecode/Codegen.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,160 @@
|
|||||||
|
package de.dhbwstuttgart.bytecode;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.TargetGeneric;
|
||||||
|
import de.dhbwstuttgart.target.tree.type.*;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
|
import java.lang.String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* //ToDo beschreiben
|
||||||
|
*
|
||||||
|
* @since Studienarbeit Type Erasure
|
||||||
|
* @author etiennezink
|
||||||
|
*/
|
||||||
|
public class FunNGenerator {
|
||||||
|
|
||||||
|
private static final String argumentGenericBase = "T";
|
||||||
|
private static final String returnGeneric = "R";
|
||||||
|
private static final String methodName = "apply";
|
||||||
|
private static final int bytecodeVersion = V1_8;
|
||||||
|
|
||||||
|
private static final String objectSuperType = Type.getInternalName(Object.class).replace('.','/');
|
||||||
|
private static final String objectSignature = applySignature(TargetType.Object);
|
||||||
|
|
||||||
|
private static final String VOID = "Ljava/lang/Void;";
|
||||||
|
|
||||||
|
public static class GenericParameters {
|
||||||
|
int start;
|
||||||
|
public List<TargetType> parameters = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String applyDescriptor(TargetType type, GenericParameters gep) {
|
||||||
|
if (type == null) return VOID;
|
||||||
|
var res = "L" + type.getInternalName();
|
||||||
|
if (type instanceof TargetSpecializedType a) {
|
||||||
|
if (a.params().size() > 0) {
|
||||||
|
res += "<";
|
||||||
|
for (var param : a.params()) {
|
||||||
|
if (param instanceof TargetGenericType gp) {
|
||||||
|
gep.parameters.add(param);
|
||||||
|
res += "TT" + gep.start + ";";
|
||||||
|
gep.start += 1;
|
||||||
|
} else {
|
||||||
|
res += applyDescriptor(param, gep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res += ">";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gep.parameters.add(null);
|
||||||
|
return type.toDescriptor();
|
||||||
|
}
|
||||||
|
res += ";";
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String applySignature(TargetType a) { return a.toSignature(); }
|
||||||
|
private static String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("%s", applySignature(a)); }
|
||||||
|
|
||||||
|
public static String encodeType(TargetType type) {
|
||||||
|
if (type == null) return VOID;
|
||||||
|
return applyNameDescriptor(type).replace("/", "$").replace(";", "$_$");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] generateSuperBytecode(int numberArguments) {
|
||||||
|
StringBuilder superFunNClassSignature = new StringBuilder("<");
|
||||||
|
StringBuilder superFunNMethodSignature = new StringBuilder("(");
|
||||||
|
StringBuilder superFunNMethodDescriptor = new StringBuilder("(");
|
||||||
|
|
||||||
|
for (int currentParameter = 1; currentParameter <= numberArguments; currentParameter++){
|
||||||
|
superFunNClassSignature.append(String.format("%s%d:%s", argumentGenericBase, currentParameter, objectSignature));
|
||||||
|
superFunNMethodSignature.append(String.format("T%s;", argumentGenericBase + currentParameter));
|
||||||
|
superFunNMethodDescriptor.append(objectSignature);
|
||||||
|
}
|
||||||
|
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
|
||||||
|
superFunNMethodSignature.append(String.format(")T%s;", returnGeneric));
|
||||||
|
superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
|
||||||
|
|
||||||
|
System.out.println(superFunNMethodSignature);
|
||||||
|
|
||||||
|
ClassWriter classWriter = new ClassWriter(0);
|
||||||
|
MethodVisitor methodVisitor;
|
||||||
|
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSuperClassName(numberArguments), superFunNClassSignature.toString(), objectSuperType, null);
|
||||||
|
methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor.toString(), superFunNMethodSignature.toString(), null);
|
||||||
|
methodVisitor.visitEnd();
|
||||||
|
classWriter.visitEnd();
|
||||||
|
return classWriter.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSuperClassName(int numberArguments) {
|
||||||
|
return String.format("Fun%d$$", numberArguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] generateSpecializedBytecode(List<TargetType> argumentTypes, TargetType returnType, GenericParameters gep) {
|
||||||
|
List<TargetType> parameters = Stream
|
||||||
|
.concat(argumentTypes.stream(), Stream.of(returnType))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
StringBuilder funNClassSignature = new StringBuilder(objectSignature + applyDescriptor(new TargetRefType(getSuperClassName(argumentTypes.size()), parameters), gep));
|
||||||
|
boolean containsGeneric = false;
|
||||||
|
|
||||||
|
String genericSignature = "<";
|
||||||
|
for (var i = 0; i < gep.start; i++) {
|
||||||
|
genericSignature += String.format("T%d:%s", i, objectSignature);
|
||||||
|
containsGeneric = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
genericSignature += ">";
|
||||||
|
if (containsGeneric) funNClassSignature.insert(0, genericSignature);
|
||||||
|
System.out.println(funNClassSignature.toString());
|
||||||
|
|
||||||
|
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.visitEnd();
|
||||||
|
return classWriter.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void collectGenericTypeArguments(Map<TargetGenericType, Integer> generics, TargetType typeArgument) {
|
||||||
|
if (typeArgument instanceof TargetSpecializedType specializedType) {
|
||||||
|
for (var arg : specializedType.params())
|
||||||
|
collectGenericTypeArguments(generics, arg);
|
||||||
|
} else if (typeArgument instanceof TargetGenericType genericType) {
|
||||||
|
if (generics.containsKey(genericType))
|
||||||
|
generics.put(genericType, generics.get(genericType) + 1);
|
||||||
|
else generics.put(genericType, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSpecializedClassName(List<TargetType> argumentTypes, TargetType returnType) {
|
||||||
|
return String.format("Fun%d$$%s%s",
|
||||||
|
argumentTypes.size(),
|
||||||
|
argumentTypes
|
||||||
|
.stream()
|
||||||
|
.map(FunNGenerator::encodeType)
|
||||||
|
.collect(Collectors.joining()),
|
||||||
|
encodeType(returnType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<TargetType> getArguments(List<TargetType> list) {
|
||||||
|
return list
|
||||||
|
.stream()
|
||||||
|
.limit(Math.max(0, list.size() - 1))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TargetType getReturnType(List<TargetType> list) {
|
||||||
|
if(list.size() == 0)
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
return list.get(list.size() - 1);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package de.dhbwstuttgart.bytecode;
|
||||||
|
|
||||||
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
|
import java.lang.String;
|
||||||
|
|
||||||
|
public class JavaTXSignatureAttribute extends Attribute {
|
||||||
|
public String signature;
|
||||||
|
|
||||||
|
public JavaTXSignatureAttribute() {
|
||||||
|
super("JavaTXSignature");
|
||||||
|
}
|
||||||
|
protected JavaTXSignatureAttribute(String signature) {
|
||||||
|
this();
|
||||||
|
this.signature = signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Attribute read(ClassReader classReader, int offset, int length, char[] charBuffer, int codeAttributeOffset, Label[] labels) {
|
||||||
|
var data = new byte[length];
|
||||||
|
System.arraycopy(classReader.b, offset, data, 0, length);
|
||||||
|
var constantPoolOffset = data[0] << 8 | data[1];
|
||||||
|
return new JavaTXSignatureAttribute((String) classReader.readConst(constantPoolOffset, charBuffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ByteVector write(ClassWriter classWriter, byte[] code, int codeLength, int maxStack, int maxLocals) {
|
||||||
|
var data = new ByteVector();
|
||||||
|
data.putShort(classWriter.newConst(this.signature));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package de.dhbwstuttgart.core;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
public class ConsoleInterface {
|
||||||
|
private static final String directory = System.getProperty("user.dir");
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException, ClassNotFoundException {
|
||||||
|
List<File> input = new ArrayList<>();
|
||||||
|
List<File> classpath = new ArrayList<>();
|
||||||
|
String outputPath = null;
|
||||||
|
Iterator<String> it = Arrays.asList(args).iterator();
|
||||||
|
if(args.length == 0){
|
||||||
|
System.out.println("No input files given. Get help with --help");
|
||||||
|
System.exit(1);
|
||||||
|
}else if(args.length == 1 && args[0].equals("--help")){
|
||||||
|
System.out.println("Usage: javatx [OPTION]... [FILE]...\n" +
|
||||||
|
"\t-cp\tSet Classpath\n" +
|
||||||
|
"\t-d\tSet destination directory");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
while(it.hasNext()){
|
||||||
|
String arg = it.next();
|
||||||
|
if(arg.equals("-d")){
|
||||||
|
outputPath = it.next();
|
||||||
|
}else if(arg.startsWith("-d")) {
|
||||||
|
outputPath = arg.substring(2);
|
||||||
|
}else if(arg.equals("-cp") || arg.equals("-classpath")){
|
||||||
|
String[] cps = it.next().split(":");
|
||||||
|
for(String cp : cps){
|
||||||
|
classpath.add(new File(cp));
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
input.add(new File(arg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JavaTXCompiler compiler = new JavaTXCompiler(input, classpath);
|
||||||
|
//compiler.typeInference();
|
||||||
|
compiler.generateBytecode(outputPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package de.dhbwstuttgart.core;
|
||||||
|
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public interface IItemWithOffset
|
||||||
|
{
|
||||||
|
Token getOffset();
|
||||||
|
}
|
@ -0,0 +1,827 @@
|
|||||||
|
//PL 2018-12-19: typeInferenceOld nach typeInference uebertragen
|
||||||
|
package de.dhbwstuttgart.core;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import de.dhbwstuttgart.bytecode.Codegen;
|
||||||
|
import de.dhbwstuttgart.environment.CompilationEnvironment;
|
||||||
|
import de.dhbwstuttgart.environment.DirectoryClassLoader;
|
||||||
|
import de.dhbwstuttgart.exceptions.DebugException;
|
||||||
|
import de.dhbwstuttgart.parser.JavaTXParser;
|
||||||
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
|
import de.dhbwstuttgart.parser.scope.GenericsRegistry;
|
||||||
|
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.SyntaxTreeGenerator;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.SourceFileContext;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.Method;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.ParameterList;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.GenericDeclarationList;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.TypeVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter;
|
||||||
|
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||||
|
import de.dhbwstuttgart.target.generate.GenericsResult;
|
||||||
|
import de.dhbwstuttgart.target.tree.expression.TargetBinaryOp;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.Pair;
|
||||||
|
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||||
|
import de.dhbwstuttgart.typeinference.typeAlgo.TYPE;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.RuleSet;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.TypeUnify;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.distributeVariance;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.UnifyResultListener;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.UnifyResultListenerImpl;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.UnifyResultModel;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.UnifyTaskModel;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.commons.io.output.NullOutputStream;
|
||||||
|
|
||||||
|
public class JavaTXCompiler {
|
||||||
|
|
||||||
|
// public static JavaTXCompiler INSTANCE;
|
||||||
|
final CompilationEnvironment environment;
|
||||||
|
Boolean resultmodel = true;
|
||||||
|
public final Map<File, SourceFile> sourceFiles = new HashMap<>();
|
||||||
|
|
||||||
|
Boolean log = false; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll?
|
||||||
|
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
|
||||||
|
private final DirectoryClassLoader classLoader;
|
||||||
|
|
||||||
|
private final List<File> classPath;
|
||||||
|
|
||||||
|
public DirectoryClassLoader getClassLoader() {
|
||||||
|
return classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
|
||||||
|
this(Arrays.asList(sourceFile), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaTXCompiler(File sourceFile, Boolean log) throws IOException, ClassNotFoundException {
|
||||||
|
this(sourceFile);
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaTXCompiler(List<File> sourceFiles) throws IOException, ClassNotFoundException {
|
||||||
|
this(sourceFiles, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaTXCompiler(List<File> sources, List<File> contextPath) throws IOException, ClassNotFoundException {
|
||||||
|
if (contextPath == null || contextPath.isEmpty()) {
|
||||||
|
// When no contextPaths are given, the working directory is the sources root
|
||||||
|
contextPath = Lists.newArrayList(new File(System.getProperty("user.dir")));
|
||||||
|
}
|
||||||
|
classLoader = new DirectoryClassLoader(contextPath, ClassLoader.getSystemClassLoader());
|
||||||
|
environment = new CompilationEnvironment(sources);
|
||||||
|
classPath = contextPath;
|
||||||
|
|
||||||
|
for (File s : sources) {
|
||||||
|
parse(s);
|
||||||
|
}
|
||||||
|
// INSTANCE = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSourceFile(File file, SourceFile sf) {
|
||||||
|
sourceFiles.put(file, sf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassOrInterface getClass(JavaClassName name) {
|
||||||
|
for (var sf : sourceFiles.values()) {
|
||||||
|
for (var clazz : sf.KlassenVektor) {
|
||||||
|
if (clazz.getClassName().equals(name)) return clazz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var clazz = classLoader.loadClass(name.toString());
|
||||||
|
if (clazz != null)
|
||||||
|
return ASTFactory.createClass(clazz);
|
||||||
|
} catch (ClassNotFoundException ignored) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstraintSet<Pair> getConstraints() throws ClassNotFoundException, IOException {
|
||||||
|
List<ClassOrInterface> allClasses = new ArrayList<>();// environment.getAllAvailableClasses();
|
||||||
|
List<ClassOrInterface> importedClasses = new ArrayList<>();
|
||||||
|
ClassOrInterface objectClass = ASTFactory.createClass(classLoader.loadClass(new JavaClassName("java.lang.Object").toString()));
|
||||||
|
// Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC
|
||||||
|
for (Entry<File, SourceFile> source : sourceFiles.entrySet()) {
|
||||||
|
for (JavaClassName name : source.getValue().getImports()) {
|
||||||
|
importedClasses.addAll(getAvailableClasses(name));
|
||||||
|
}
|
||||||
|
for (Class c : CompilationEnvironment.loadDefaultPackageClasses(source.getValue().getPkgName(), source.getKey(), this)) {
|
||||||
|
ClassOrInterface importedClass = ASTFactory.createClass(c);
|
||||||
|
importedClasses.add(importedClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (File f : this.sourceFiles.keySet()) {
|
||||||
|
SourceFile sf = sourceFiles.get(f);
|
||||||
|
sf = 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.
|
||||||
|
SourceFile sf_new = sf;
|
||||||
|
sf.KlassenVektor.forEach(cl -> addMethods(sf_new, cl, importedClasses, objectClass));
|
||||||
|
allClasses.addAll(sf.getClasses());
|
||||||
|
}
|
||||||
|
allClasses.addAll(importedClasses);
|
||||||
|
TYPE ty = new TYPE(sourceFiles.values(), allClasses);
|
||||||
|
return ty.getConstraints();
|
||||||
|
}
|
||||||
|
|
||||||
|
void addMethods(SourceFile sf, ClassOrInterface cl, List<ClassOrInterface> importedClasses, ClassOrInterface objectClass) {
|
||||||
|
if (!cl.areMethodsAdded()) {
|
||||||
|
ClassOrInterface superclass = null;
|
||||||
|
Optional<ClassOrInterface> optSuperclass = importedClasses.stream().filter(x -> x.getClassName().equals(cl.getSuperClass().getName())).findFirst();
|
||||||
|
if (optSuperclass.isPresent()) {
|
||||||
|
superclass = optSuperclass.get();
|
||||||
|
} else {
|
||||||
|
optSuperclass = sf.KlassenVektor.stream().filter(x -> x.getClassName().equals(cl.getSuperClass().getName())).findFirst();
|
||||||
|
if (optSuperclass.isPresent()) {
|
||||||
|
superclass = optSuperclass.get();
|
||||||
|
addMethods(sf, superclass, importedClasses, objectClass);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
var className = cl.getSuperClass().getName().toString();
|
||||||
|
superclass = ASTFactory.createClass(classLoader.loadClass(className));
|
||||||
|
} catch (ClassNotFoundException ignored) {}
|
||||||
|
// throw new ClassNotFoundException("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<RefTypeOrTPHOrWildcardOrGeneric> paraIt = cl.getSuperClass().getParaList().iterator();
|
||||||
|
Iterator<GenericTypeVar> tvarVarIt = superclass.getGenerics().iterator();
|
||||||
|
|
||||||
|
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs = new HashMap<>();
|
||||||
|
while (paraIt.hasNext()) {
|
||||||
|
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
|
||||||
|
// werden
|
||||||
|
while (methodIt.hasNext()) {
|
||||||
|
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());
|
||||||
|
cl.getMethods().add(new Method(m.modifier, m.name, m.getReturnType().acceptTV(new TypeExchanger(gtvs)), newParaList, m.block,
|
||||||
|
// new GenericDeclarationList(newGenericsList,
|
||||||
|
// ((GenericDeclarationList)m.getGenerics()).getOffset()),
|
||||||
|
(GenericDeclarationList) m.getGenerics(), m.getOffset(), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
cl.setMethodsAdded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ClassOrInterface> getAvailableClasses(JavaClassName name) throws ClassNotFoundException {
|
||||||
|
Set<ClassOrInterface> allClasses = new HashSet<>();
|
||||||
|
if (loadJavaTXClass(name)) {
|
||||||
|
var file = findFileForClass(name);
|
||||||
|
var sf = sourceFiles.get(file);
|
||||||
|
if (sf != null) allClasses.addAll(sf.KlassenVektor);
|
||||||
|
} else {
|
||||||
|
ClassOrInterface importedClass = ASTFactory.createClass(classLoader.loadClass(name.toString()));
|
||||||
|
allClasses.add(importedClass);
|
||||||
|
}
|
||||||
|
return new ArrayList<>(allClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ClassOrInterface> getAvailableClasses(SourceFile forSourceFile) throws ClassNotFoundException {
|
||||||
|
// PL 2018-09-18: List durch Set ersetzt, damit die Klassen nur einmal
|
||||||
|
// hinzugefuegt werden
|
||||||
|
// List<ClassOrInterface> allClasses = new
|
||||||
|
// ArrayList<>();//environment.getAllAvailableClasses();
|
||||||
|
Set<ClassOrInterface> allClasses = new HashSet<>();
|
||||||
|
|
||||||
|
for (JavaClassName name : forSourceFile.getImports()) {
|
||||||
|
allClasses.addAll(getAvailableClasses(name));
|
||||||
|
}
|
||||||
|
return new ArrayList<>(allClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* public List<ResultSet> typeInferenceOld() throws ClassNotFoundException { List<ClassOrInterface> allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); //Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC for(SourceFile sf : this.sourceFiles.values()) { allClasses.addAll(getAvailableClasses(sf)); allClasses.addAll(sf.getClasses()); }
|
||||||
|
*
|
||||||
|
* final ConstraintSet<Pair> cons = getConstraints();
|
||||||
|
*
|
||||||
|
* FiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses); System.out.println(finiteClosure); ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(cons);
|
||||||
|
*
|
||||||
|
* TypeUnify unify = new TypeUnify(); Set<Set<UnifyPair>> results = new HashSet<>(); try { File logPath = new File(System.getProperty("user.dir")+"/target/logFiles/"); logPath.mkdirs(); FileWriter logFile = new FileWriter(new File(logPath, "log")); logFile.write("FC:\\" + finiteClosure.toString()+"\n"); for(SourceFile sf : this.sourceFiles.values()) { logFile.write(ASTTypePrinter.print(sf)); } logFile.flush(); Set<List<Constraint<UnifyPair>>> cardProd = unifyCons.cartesianProduct(); for
|
||||||
|
* (List<Constraint<UnifyPair>> xCons : cardProd ){ Set<UnifyPair> xConsSet = new HashSet<>(); for (Constraint<UnifyPair> constraint : xCons) { xConsSet.addAll(constraint); } //.collect(Collectors.toCollection(ArrayList::new)))) System.out.println(xConsSet); 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) -> { a.addAll(b); return a;}, (a,b) -> { a.addAll(b); return a;} ) ) .reduce(new HashSet<String>(), (a,b) -> { a.addAll(b); return a;} );
|
||||||
|
*
|
||||||
|
* Set<String> constructorParaTypeVarNames = allClasses.stream().map(x -> x.getConstructors().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) -> { a.addAll(b); return a;}, (a,b) -> { a.addAll(b); return a;} ) ) .reduce(new HashSet<String>(), (a,b) -> { a.addAll(b); return a;} );
|
||||||
|
*
|
||||||
|
* Set<String> paraTypeVarNames = methodParaTypeVarNames; paraTypeVarNames.addAll(constructorParaTypeVarNames);
|
||||||
|
*
|
||||||
|
* Set<String> returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) .map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors. toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get();
|
||||||
|
*
|
||||||
|
* Set<String> fieldTypeVarNames = allClasses.stream().map(x -> x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) .map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors. toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get();
|
||||||
|
*
|
||||||
|
* returnTypeVarNames.addAll(fieldTypeVarNames);
|
||||||
|
*
|
||||||
|
* xConsSet = xConsSet.stream().map(x -> { //Hier muss ueberlegt werden, ob //1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs // mit disableWildcardtable() werden. //2. alle Typvariablen mit Argument- oder Retuntyp-Variablen //in Beziehung auch auf disableWildcardtable() gesetzt werden muessen //PL 2018-04-23 if ((x.getLhsType() instanceof PlaceholderType)) { if (paraTypeVarNames.contains(x.getLhsType().getName())) { ((PlaceholderType)x.getLhsType()).setVariance((byte)1);
|
||||||
|
* ((PlaceholderType)x.getLhsType()).disableWildcardtable(); } if (returnTypeVarNames.contains(x.getLhsType().getName())) { ((PlaceholderType)x.getLhsType()).setVariance((byte)-1); ((PlaceholderType)x.getLhsType()).disableWildcardtable(); } } if ((x.getRhsType() instanceof PlaceholderType)) { if (paraTypeVarNames.contains(x.getRhsType().getName())) { ((PlaceholderType)x.getRhsType()).setVariance((byte)1); ((PlaceholderType)x.getRhsType()).disableWildcardtable(); } if
|
||||||
|
* (returnTypeVarNames.contains(x.getRhsType().getName())) { ((PlaceholderType)x.getRhsType()).setVariance((byte)-1); ((PlaceholderType)x.getRhsType()).disableWildcardtable(); } } return x;//HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE JEWEILS ANDERE SEITE }).map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 &&
|
||||||
|
* ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( )).getVariance()); } } return y; } ) .collect(Collectors.toCollection(HashSet::new)); varianceInheritance(xConsSet); Set<Set<UnifyPair>> result =
|
||||||
|
* unify.unifySequential(xConsSet, finiteClosure, logFile, log); //Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure); System.out.println("RESULT: " + result); logFile.write("RES: " + result.toString()+"\n"); logFile.flush(); results.addAll(result); }
|
||||||
|
*
|
||||||
|
* results = results.stream().map(x -> { Optional<Set<UnifyPair>> res = new RuleSet().subst(x.stream().map(y -> { if (y.getPairOp() == PairOperator.SMALLERDOTWC) y.setPairOp(PairOperator.EQUALSDOT); return y; //alle Paare a <.? b erden durch a =. b ersetzt }).collect(Collectors.toCollection(HashSet::new))); if (res.isPresent()) {//wenn subst ein Erg liefert wurde was veraendert return new TypeUnifyTask().applyTypeUnificationRules(res.get(), finiteClosure); } else return x; //wenn nichts
|
||||||
|
* veraendert wurde wird x zurueckgegeben }).collect(Collectors.toCollection(HashSet::new)); System.out.println("RESULT Final: " + results); logFile.write("RES_FINAL: " + results.toString()+"\n"); logFile.flush(); logFile.write("PLACEHOLDERS: " + PlaceholderType.EXISTING_PLACEHOLDERS); logFile.flush(); } catch (IOException e) { e.printStackTrace(); } return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs,
|
||||||
|
* generateTPHMap(cons))))).collect(Collectors.toList()); }
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) wenn a eine Variance !=0 hat auf alle Typvariablen in Theta.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* private void varianceInheritance(Set<UnifyPair> eq) { Set<PlaceholderType> usedTPH = new HashSet<>(); Set<PlaceholderType> phSet = eq.stream().map(x -> { Set<PlaceholderType> pair = new HashSet<>(); if (x.getLhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getLhsType()); if (x.getRhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getRhsType()); return pair; }).reduce(new HashSet<>(), (a,b) -> { a.addAll(b); return a;} , (c,d) -> { c.addAll(d); return c;});
|
||||||
|
*
|
||||||
|
* ArrayList<PlaceholderType> phSetVariance = new ArrayList<>(phSet); phSetVariance.removeIf(x -> (x.getVariance() == 0)); while(!phSetVariance.isEmpty()) { PlaceholderType a = phSetVariance.remove(0); usedTPH.add(a); //HashMap<PlaceholderType,Integer> ht = new HashMap<>(); //ht.put(a, a.getVariance()); Set<UnifyPair> eq1 = new HashSet<>(eq); eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType && ((PlaceholderType)x.getLhsType()).equals(a))); eq1.stream().forEach(x -> {
|
||||||
|
* x.getRhsType().accept(new distributeVariance(), a.getVariance());}); eq1 = new HashSet<>(eq); eq1.removeIf(x -> !(x.getRhsType() instanceof PlaceholderType && ((PlaceholderType)x.getRhsType()).equals(a))); eq1.stream().forEach(x -> { x.getLhsType().accept(new distributeVariance(), a.getVariance());}); phSetVariance = new ArrayList<>(phSet); phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x))); } }
|
||||||
|
*/
|
||||||
|
|
||||||
|
public UnifyResultModel typeInferenceAsync(UnifyResultListener resultListener, Writer logFile) throws ClassNotFoundException, IOException {
|
||||||
|
List<ClassOrInterface> allClasses = new ArrayList<>();// environment.getAllAvailableClasses();
|
||||||
|
// Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC
|
||||||
|
for (Entry<File, SourceFile> source : this.sourceFiles.entrySet()) {
|
||||||
|
SourceFile sf = source.getValue();
|
||||||
|
allClasses.addAll(getAvailableClasses(sf));
|
||||||
|
allClasses.addAll(sf.getClasses());
|
||||||
|
allClasses.addAll(CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), this).stream().map(ASTFactory::createClass).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
final ConstraintSet<Pair> cons = getConstraints();
|
||||||
|
Set<Set<UnifyPair>> results = new HashSet<>();
|
||||||
|
UnifyResultModel urm = null;
|
||||||
|
// urm.addUnifyResultListener(resultListener);
|
||||||
|
try {
|
||||||
|
logFile = logFile == null ? new FileWriter(new File("log_" + sourceFiles.keySet().iterator().next().getName())) : logFile;
|
||||||
|
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, getClassLoader());
|
||||||
|
System.out.println(finiteClosure);
|
||||||
|
urm = new UnifyResultModel(cons, finiteClosure);
|
||||||
|
urm.addUnifyResultListener(resultListener);
|
||||||
|
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(cons);
|
||||||
|
|
||||||
|
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
|
||||||
|
UnifyType lhs, rhs;
|
||||||
|
if (((lhs = x.getLhsType()) instanceof PlaceholderType) && ((rhs = x.getRhsType()) instanceof PlaceholderType) && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) {
|
||||||
|
((PlaceholderType) lhs).setInnerType(true);
|
||||||
|
((PlaceholderType) rhs).setInnerType(true);
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
|
||||||
|
};
|
||||||
|
logFile.write(unifyCons.toString());
|
||||||
|
unifyCons = unifyCons.map(distributeInnerVars);
|
||||||
|
logFile.write(unifyCons.toString());
|
||||||
|
TypeUnify unify = new TypeUnify();
|
||||||
|
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
|
||||||
|
logFile.write("FC:\\" + finiteClosure.toString() + "\n");
|
||||||
|
for (SourceFile sf : this.sourceFiles.values()) {
|
||||||
|
logFile.write(ASTTypePrinter.print(sf));
|
||||||
|
}
|
||||||
|
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) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
}, (a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
})).reduce(new HashSet<String>(), (a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
});
|
||||||
|
|
||||||
|
Set<String> constructorParaTypeVarNames = allClasses.stream().map(x -> x.getConstructors().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) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
}, (a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
})).reduce(new HashSet<String>(), (a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
});
|
||||||
|
|
||||||
|
Set<String> paraTypeVarNames = methodParaTypeVarNames;
|
||||||
|
paraTypeVarNames.addAll(constructorParaTypeVarNames);
|
||||||
|
|
||||||
|
Set<String> returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
}).get();
|
||||||
|
|
||||||
|
Set<String> fieldTypeVarNames = allClasses.stream().map(x -> x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
}).get();
|
||||||
|
|
||||||
|
returnTypeVarNames.addAll(fieldTypeVarNames);
|
||||||
|
|
||||||
|
unifyCons = unifyCons.map(x -> {
|
||||||
|
// Hier muss ueberlegt werden, ob
|
||||||
|
// 1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs
|
||||||
|
// mit disableWildcardtable() werden.
|
||||||
|
// 2. alle Typvariablen mit Argument- oder Retuntyp-Variablen
|
||||||
|
// in Beziehung auch auf disableWildcardtable() gesetzt werden muessen
|
||||||
|
// PL 2018-04-23
|
||||||
|
if ((x.getLhsType() instanceof PlaceholderType)) {
|
||||||
|
if (paraTypeVarNames.contains(x.getLhsType().getName())) {
|
||||||
|
((PlaceholderType) x.getLhsType()).setVariance((byte) 1);
|
||||||
|
((PlaceholderType) x.getLhsType()).disableWildcardtable();
|
||||||
|
}
|
||||||
|
if (returnTypeVarNames.contains(x.getLhsType().getName())) {
|
||||||
|
((PlaceholderType) x.getLhsType()).setVariance((byte) -1);
|
||||||
|
((PlaceholderType) x.getLhsType()).disableWildcardtable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((x.getRhsType() instanceof PlaceholderType)) {
|
||||||
|
if (paraTypeVarNames.contains(x.getRhsType().getName())) {
|
||||||
|
((PlaceholderType) x.getRhsType()).setVariance((byte) 1);
|
||||||
|
((PlaceholderType) x.getRhsType()).disableWildcardtable();
|
||||||
|
}
|
||||||
|
if (returnTypeVarNames.contains(x.getRhsType().getName())) {
|
||||||
|
((PlaceholderType) x.getRhsType()).setVariance((byte) -1);
|
||||||
|
((PlaceholderType) x.getRhsType()).disableWildcardtable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x;// HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE
|
||||||
|
// JEWEILS ANDERE SEITE
|
||||||
|
});
|
||||||
|
Set<PlaceholderType> varianceTPHold;
|
||||||
|
Set<PlaceholderType> varianceTPH = new HashSet<>();
|
||||||
|
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PL 2018-11-07 wird in varianceInheritanceConstraintSet erledigt do { //PL 2018-11-05 Huellenbildung Variance auf alle TPHs der Terme auf der jeweiligen //anderen Seite übertragen varianceTPHold = new HashSet<>(varianceTPH); varianceTPH = varianceInheritanceConstraintSet(unifyCons); unifyCons.map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 &&
|
||||||
|
* ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( )).getVariance()); } } return y; } ); } while (!varianceTPHold.equals(varianceTPH));
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Set<Set<UnifyPair>> result = unify.unifySequential(xConsSet, finiteClosure,
|
||||||
|
// logFile, log);
|
||||||
|
// Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure);
|
||||||
|
List<Set<Constraint<UnifyPair>>> oderConstraints = unifyCons.getOderConstraints()/*
|
||||||
|
* .stream().map(x -> { Set<Set<UnifyPair>> ret = new HashSet<>(); for (Constraint<UnifyPair> y : x) { ret.add(new HashSet<>(y)); } return ret; }).collect(Collectors. toCollection(ArrayList::new))
|
||||||
|
*/;
|
||||||
|
unify.unifyAsync(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm, usedTasks);
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("kein LogFile");
|
||||||
|
}
|
||||||
|
return urm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ResultSet> typeInference() throws ClassNotFoundException, IOException {
|
||||||
|
List<ClassOrInterface> allClasses = new ArrayList<>();// environment.getAllAvailableClasses();
|
||||||
|
// Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC
|
||||||
|
for (Entry<File, SourceFile> source : this.sourceFiles.entrySet()) {
|
||||||
|
SourceFile sf = source.getValue();
|
||||||
|
allClasses.addAll(getAvailableClasses(sf));
|
||||||
|
allClasses.addAll(sf.getClasses());
|
||||||
|
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), this).stream().map(ASTFactory::createClass).collect(Collectors.toList());
|
||||||
|
for (var clazz : newClasses) {
|
||||||
|
// Don't load classes that get recompiled
|
||||||
|
if (sf.getClasses().stream().anyMatch(nf -> nf.getClassName().equals(clazz.getClassName())))
|
||||||
|
continue;
|
||||||
|
if (allClasses.stream().noneMatch(old -> old.getClassName().equals(clazz.getClassName())))
|
||||||
|
allClasses.add(clazz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final ConstraintSet<Pair> cons = getConstraints();
|
||||||
|
Set<Set<UnifyPair>> results = new HashSet<>();
|
||||||
|
try {
|
||||||
|
var logFolder = new File(System.getProperty("user.dir") + "/logFiles/");
|
||||||
|
if (log) logFolder.mkdirs();
|
||||||
|
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);
|
||||||
|
System.out.println(finiteClosure);
|
||||||
|
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(cons);
|
||||||
|
System.out.println("xxx1");
|
||||||
|
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
|
||||||
|
UnifyType lhs, rhs;
|
||||||
|
if (((lhs = x.getLhsType()) instanceof PlaceholderType) && ((rhs = x.getRhsType()) instanceof PlaceholderType) && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) {
|
||||||
|
((PlaceholderType) lhs).setInnerType(true);
|
||||||
|
((PlaceholderType) rhs).setInnerType(true);
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
logFile.write("Unify:" + unifyCons.toString());
|
||||||
|
System.out.println("Unify:" + unifyCons.toString());
|
||||||
|
unifyCons = unifyCons.map(distributeInnerVars);
|
||||||
|
logFile.write("\nUnify_distributeInnerVars: " + unifyCons.toString());
|
||||||
|
TypeUnify unify = new TypeUnify();
|
||||||
|
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
|
||||||
|
logFile.write("FC:\\" + finiteClosure.toString() + "\n");
|
||||||
|
for (SourceFile sf : this.sourceFiles.values()) {
|
||||||
|
logFile.write(ASTTypePrinter.print(sf));
|
||||||
|
System.out.println(ASTTypePrinter.print(sf));
|
||||||
|
}
|
||||||
|
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) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
}, (a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
})).reduce(new HashSet<String>(), (a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
});
|
||||||
|
|
||||||
|
Set<String> constructorParaTypeVarNames = allClasses.stream().map(x -> x.getConstructors().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) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
}, (a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
})).reduce(new HashSet<String>(), (a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
});
|
||||||
|
|
||||||
|
Set<String> paraTypeVarNames = methodParaTypeVarNames;
|
||||||
|
paraTypeVarNames.addAll(constructorParaTypeVarNames);
|
||||||
|
|
||||||
|
Set<String> returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
}).get();
|
||||||
|
|
||||||
|
Set<String> fieldTypeVarNames = allClasses.stream().map(x -> x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
}).get();
|
||||||
|
|
||||||
|
returnTypeVarNames.addAll(fieldTypeVarNames);
|
||||||
|
|
||||||
|
unifyCons = unifyCons.map(x -> {
|
||||||
|
// Hier muss ueberlegt werden, ob
|
||||||
|
// 1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs
|
||||||
|
// mit disableWildcardtable() werden.
|
||||||
|
// 2. alle Typvariablen mit Argument- oder Retuntyp-Variablen
|
||||||
|
// in Beziehung auch auf disableWildcardtable() gesetzt werden muessen
|
||||||
|
// PL 2018-04-23
|
||||||
|
if ((x.getLhsType() instanceof PlaceholderType)) {
|
||||||
|
if (paraTypeVarNames.contains(x.getLhsType().getName())) {
|
||||||
|
((PlaceholderType) x.getLhsType()).setVariance((byte) 1);
|
||||||
|
((PlaceholderType) x.getLhsType()).disableWildcardtable();
|
||||||
|
}
|
||||||
|
if (returnTypeVarNames.contains(x.getLhsType().getName())) {
|
||||||
|
((PlaceholderType) x.getLhsType()).setVariance((byte) -1);
|
||||||
|
((PlaceholderType) x.getLhsType()).disableWildcardtable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((x.getRhsType() instanceof PlaceholderType)) {
|
||||||
|
if (paraTypeVarNames.contains(x.getRhsType().getName())) {
|
||||||
|
((PlaceholderType) x.getRhsType()).setVariance((byte) 1);
|
||||||
|
((PlaceholderType) x.getRhsType()).disableWildcardtable();
|
||||||
|
}
|
||||||
|
if (returnTypeVarNames.contains(x.getRhsType().getName())) {
|
||||||
|
((PlaceholderType) x.getRhsType()).setVariance((byte) -1);
|
||||||
|
((PlaceholderType) x.getRhsType()).disableWildcardtable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x;// HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE
|
||||||
|
// JEWEILS ANDERE SEITE
|
||||||
|
});
|
||||||
|
|
||||||
|
// PL 2020-02-05 alle Oder-Constraints Receiver und Parameter werden auf
|
||||||
|
// variance 1 gesetzt
|
||||||
|
// Es wird davon ausgegangen, dass in OderConstraints in Bedingungen für
|
||||||
|
// Parameter die Typen der Argumente links stehen
|
||||||
|
// und die Typen der Rückgabewerte immer rechts stehen
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unifyCons.getOderConstraints().forEach(z -> z.forEach(y -> y.forEach(x -> { if ((x.getLhsType() instanceof PlaceholderType) && x.getPairOp().compareTo(PairOperator.SMALLERDOT) == 0) { ((PlaceholderType) x.getLhsType()).setVariance((byte)1); } else if ((x.getRhsType() instanceof PlaceholderType) && x.getPairOp().compareTo(PairOperator.EQUALSDOT) == 0) { ((PlaceholderType) x.getRhsType()).setVariance((byte)-1); } })));
|
||||||
|
*/
|
||||||
|
|
||||||
|
System.out.println("Unify nach Oder-Constraints-Anpassung:" + unifyCons.toString());
|
||||||
|
Set<PlaceholderType> varianceTPHold;
|
||||||
|
Set<PlaceholderType> varianceTPH = new HashSet<>();
|
||||||
|
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PL 2018-11-07 wird in varianceInheritanceConstraintSet erledigt do { //PL 2018-11-05 Huellenbildung Variance auf alle TPHs der Terme auf der jeweiligen //anderen Seite übertragen varianceTPHold = new HashSet<>(varianceTPH); varianceTPH = varianceInheritanceConstraintSet(unifyCons); unifyCons.map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 &&
|
||||||
|
* ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( )).getVariance()); } } return y; } ); } while (!varianceTPHold.equals(varianceTPH));
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Set<Set<UnifyPair>> result = unify.unifySequential(xConsSet, finiteClosure,
|
||||||
|
// logFile, log);
|
||||||
|
// Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure);
|
||||||
|
List<Set<Constraint<UnifyPair>>> oderConstraints = unifyCons.getOderConstraints()// .stream().map(x -> {
|
||||||
|
/*
|
||||||
|
* Set<Set<UnifyPair>> ret = new HashSet<>(); for (Constraint<UnifyPair> y : x) { ret.add(new HashSet<>(y)); } return ret; }).collect(Collectors.toCollection(ArrayList::new))
|
||||||
|
*/;
|
||||||
|
if (resultmodel) {
|
||||||
|
/* UnifyResultModel Anfang */
|
||||||
|
UnifyResultModel urm = new UnifyResultModel(cons, finiteClosure);
|
||||||
|
UnifyResultListenerImpl li = new UnifyResultListenerImpl();
|
||||||
|
urm.addUnifyResultListener(li);
|
||||||
|
unify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm, usedTasks);
|
||||||
|
System.out.println("RESULT Final: " + li.getResults());
|
||||||
|
System.out.println("Constraints for Generated Generics: " + " ???");
|
||||||
|
logFile.write("RES_FINAL: " + li.getResults().toString() + "\n");
|
||||||
|
logFile.flush();
|
||||||
|
return li.getResults();
|
||||||
|
}
|
||||||
|
/* UnifyResultModel End */
|
||||||
|
else {
|
||||||
|
// Set<Set<UnifyPair>> result = unify.unify(unifyCons.getUndConstraints(),
|
||||||
|
// oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons,
|
||||||
|
// finiteClosure));
|
||||||
|
Set<Set<UnifyPair>> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure), usedTasks);
|
||||||
|
System.out.println("RESULT: " + result);
|
||||||
|
logFile.write("RES: " + result.toString() + "\n");
|
||||||
|
logFile.flush();
|
||||||
|
results.addAll(result);
|
||||||
|
|
||||||
|
results = results.stream().map(x -> {
|
||||||
|
Optional<Set<UnifyPair>> res = new RuleSet().subst(x.stream().map(y -> {
|
||||||
|
if (y.getPairOp() == PairOperator.SMALLERDOTWC)
|
||||||
|
y.setPairOp(PairOperator.EQUALSDOT);
|
||||||
|
return y; // alle Paare a <.? b erden durch a =. b ersetzt
|
||||||
|
}).collect(Collectors.toCollection(HashSet::new)));
|
||||||
|
if (res.isPresent()) {// wenn subst ein Erg liefert wurde was veraendert
|
||||||
|
return new TypeUnifyTask().applyTypeUnificationRules(res.get(), finiteClosure);
|
||||||
|
} else
|
||||||
|
return x; // wenn nichts veraendert wurde wird x zurueckgegeben
|
||||||
|
}).collect(Collectors.toCollection(HashSet::new));
|
||||||
|
System.out.println("RESULT Final: " + results);
|
||||||
|
System.out.println("Constraints for Generated Generics: " + " ???");
|
||||||
|
logFile.write("RES_FINAL: " + results.toString() + "\n");
|
||||||
|
logFile.flush();
|
||||||
|
logFile.write("PLACEHOLDERS: " + PlaceholderType.EXISTING_PLACEHOLDERS);
|
||||||
|
logFile.flush();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("kein LogFile");
|
||||||
|
}
|
||||||
|
return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons))))).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) wenn a eine Variance !=0 hat auf alle Typvariablen in Theta.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private Set<PlaceholderType> varianceInheritanceConstraintSet(ConstraintSet<UnifyPair> cons) {
|
||||||
|
Set<UnifyPair> eq = cons.getAll();
|
||||||
|
Set<PlaceholderType> usedTPH = new HashSet<>();
|
||||||
|
Set<PlaceholderType> phSet = eq.stream().map(x -> {
|
||||||
|
Set<PlaceholderType> pair = new HashSet<>();
|
||||||
|
if (x.getLhsType() instanceof PlaceholderType)
|
||||||
|
pair.add((PlaceholderType) x.getLhsType());
|
||||||
|
if (x.getRhsType() instanceof PlaceholderType)
|
||||||
|
pair.add((PlaceholderType) x.getRhsType());
|
||||||
|
return pair;
|
||||||
|
}).reduce(new HashSet<>(), (a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
}, (c, d) -> {
|
||||||
|
c.addAll(d);
|
||||||
|
return c;
|
||||||
|
});
|
||||||
|
|
||||||
|
ArrayList<PlaceholderType> phSetVariance = new ArrayList<>(phSet);
|
||||||
|
phSetVariance.removeIf(x -> (x.getVariance() == 0));
|
||||||
|
while (!phSetVariance.isEmpty()) {
|
||||||
|
PlaceholderType a = phSetVariance.remove(0);
|
||||||
|
usedTPH.add(a);
|
||||||
|
// HashMap<PlaceholderType,Integer> ht = new HashMap<>();
|
||||||
|
// ht.put(a, a.getVariance());
|
||||||
|
// ConstraintSet<UnifyPair> eq1 = cons;
|
||||||
|
// eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType &&
|
||||||
|
// ((PlaceholderType)x.getLhsType()).equals(a)));
|
||||||
|
// durch if-Abfrage im foreach geloest
|
||||||
|
cons.forEach(x -> {
|
||||||
|
if (x.getLhsType() instanceof PlaceholderType && ((PlaceholderType) x.getLhsType()).equals(a)) {
|
||||||
|
x.getRhsType().accept(new distributeVariance(), a.getVariance());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// ` eq1 = new HashSet<>(eq);
|
||||||
|
// eq1.removeIf(x -> !(x.getRhsType() instanceof PlaceholderType &&
|
||||||
|
// ((PlaceholderType)x.getRhsType()).equals(a)));
|
||||||
|
// durch if-Abfrage im foreach geloest
|
||||||
|
cons.forEach(x -> {
|
||||||
|
if (x.getRhsType() instanceof PlaceholderType && ((PlaceholderType) x.getRhsType()).equals(a)) {
|
||||||
|
x.getLhsType().accept(new distributeVariance(), a.getVariance());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
phSetVariance = new ArrayList<>(phSet); // macht vermutlich keinen Sinn PL 2018-10-18, doch, es koennen neue
|
||||||
|
// TPHs mit Variancen dazugekommen sein PL 2018-11-07
|
||||||
|
phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x)));
|
||||||
|
}
|
||||||
|
return usedTPH;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final JavaClassRegistry classRegistry = new JavaClassRegistry();
|
||||||
|
|
||||||
|
private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException {
|
||||||
|
SourceFileContext tree = JavaTXParser.parse(sourceFile);
|
||||||
|
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
|
||||||
|
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null));
|
||||||
|
var classes = new ArrayList<ClassOrInterface>();
|
||||||
|
var sf = new SourceFile(generator.pkgName, classes, generator.imports);
|
||||||
|
addSourceFile(sourceFile, sf);
|
||||||
|
generator.convert(classes, tree, environment.packageCrawler);
|
||||||
|
sf.imports.addAll(generator.imports);
|
||||||
|
return sf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When an import tries to import a JavaTX class it first looks it up in the cache and
|
||||||
|
* if it doesn't exist it's going to compile it and add it to the source files list
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
public boolean loadJavaTXClass(JavaClassName name) {
|
||||||
|
var file = findFileForClass(name);
|
||||||
|
if (file != null) {
|
||||||
|
try {
|
||||||
|
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?
|
||||||
|
environment.addClassesToRegistry(classRegistry, tree, file, this);
|
||||||
|
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null));
|
||||||
|
var classes = new ArrayList<ClassOrInterface>();
|
||||||
|
var sf = new SourceFile(generator.pkgName, classes, generator.imports);
|
||||||
|
addSourceFile(file, sf);
|
||||||
|
generator.convert(classes, tree, environment.packageCrawler);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File findFileForClass(JavaClassName name) {
|
||||||
|
var packageName = name.getPackageName();
|
||||||
|
var className = name.getClassName().split("\\.")[0];
|
||||||
|
for (var cp : classPath) {
|
||||||
|
var file = new File(cp, packageName.replaceAll("\\.", "/") + "/" + className + ".jav");
|
||||||
|
if (file.exists()) return file;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generateBytecode() throws ClassNotFoundException, IOException {
|
||||||
|
generateBytecode((File) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param path - can be null, then class file output is in the same directory as the parsed source files
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
public void generateBytecode(File path) throws ClassNotFoundException, IOException {
|
||||||
|
List<ResultSet> typeinferenceResult = this.typeInference();
|
||||||
|
generateBytecode(path, typeinferenceResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<SourceFile, List<GenericsResult>> generatedGenerics = new HashMap<>();
|
||||||
|
|
||||||
|
public Map<SourceFile, List<GenericsResult>> getGeneratedGenerics() {
|
||||||
|
return generatedGenerics;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param outputPath - can be null, then class file output is in the same directory as the parsed source files
|
||||||
|
* @param typeinferenceResult
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void generateBytecode(File outputPath, List<ResultSet> typeinferenceResult) throws IOException {
|
||||||
|
for (File f : sourceFiles.keySet()) {
|
||||||
|
HashMap<JavaClassName, byte[]> classFiles = new HashMap<>();
|
||||||
|
SourceFile sf = sourceFiles.get(f);
|
||||||
|
File path;
|
||||||
|
if (outputPath == null) {
|
||||||
|
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);
|
||||||
|
writeClassFile(generatedClasses, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Map<JavaClassName, byte[]> generateBytecode(SourceFile sf, List<ResultSet> typeInferenceResult) {
|
||||||
|
var converter = new ASTToTargetAST(this, typeInferenceResult, sf, classLoader);
|
||||||
|
var generatedClasses = new HashMap<JavaClassName, byte[]>();
|
||||||
|
for (var clazz : sf.getClasses()) {
|
||||||
|
var codegen = new Codegen(converter.convert(clazz), this);
|
||||||
|
var code = codegen.generate();
|
||||||
|
generatedClasses.put(clazz.getClassName(), code);
|
||||||
|
converter.auxiliaries.forEach((name, source) -> {
|
||||||
|
generatedClasses.put(new JavaClassName(name), source);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
generatedGenerics.put(sf, converter.javaGenerics());
|
||||||
|
return generatedClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void writeClassFile(Map<JavaClassName, byte[]> classFiles, File path) throws IOException {
|
||||||
|
FileOutputStream output;
|
||||||
|
for (JavaClassName name : classFiles.keySet()) {
|
||||||
|
byte[] bytecode = classFiles.get(name);
|
||||||
|
System.out.println("generating " + name + ".class file ...");
|
||||||
|
// output = new FileOutputStream(new File(System.getProperty("user.dir") +
|
||||||
|
// "/testBytecode/generatedBC/" +name+".class"));
|
||||||
|
File outputFile = new File(path, name.getClassName() + ".class");
|
||||||
|
outputFile.getAbsoluteFile().getParentFile().mkdirs();
|
||||||
|
output = new FileOutputStream(outputFile);
|
||||||
|
output.write(bytecode);
|
||||||
|
output.close();
|
||||||
|
System.out.println(name + ".class file generated");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PL 2020-03-17 mit TypeExchanger in FCGenerator.java zusammenfuehren */
|
||||||
|
/**
|
||||||
|
* Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus.
|
||||||
|
*/
|
||||||
|
private static class TypeExchanger implements TypeVisitor<RefTypeOrTPHOrWildcardOrGeneric> {
|
||||||
|
|
||||||
|
private final HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs;
|
||||||
|
|
||||||
|
TypeExchanger(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) {
|
||||||
|
SuperWildcardType ret = new SuperWildcardType(superWildcardType.getInnerType().acceptTV(this), superWildcardType.getOffset());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric visit(TypePlaceholder typePlaceholder) {
|
||||||
|
return typePlaceholder; // TypePlaceholder der vererbert wird kann bei der Vererbung nicht instanziert
|
||||||
|
// werden.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric visit(ExtendsWildcardType extendsWildcardType) {
|
||||||
|
ExtendsWildcardType ret = new ExtendsWildcardType(extendsWildcardType.getInnerType().acceptTV(this), extendsWildcardType.getOffset());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric visit(GenericRefType genericRefType) {
|
||||||
|
if (!gtvs.containsKey(genericRefType.getParsedName()))
|
||||||
|
throw new DebugException("Dieser Fall darf nicht auftreten");
|
||||||
|
return gtvs.get(genericRefType.getParsedName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package de.dhbwstuttgart.environment;
|
||||||
|
|
||||||
|
public class ByteArrayClassLoader extends ClassLoader implements IByteArrayClassLoader {
|
||||||
|
@Override
|
||||||
|
public Class _defineClass(String name, byte[] code, int i, int length) throws ClassFormatError {
|
||||||
|
return defineClass(name, code, i, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> findClass(String name) throws ClassNotFoundException {
|
||||||
|
return super.findClass(name);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
package de.dhbwstuttgart.environment;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.exceptions.DebugException;
|
||||||
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
|
import de.dhbwstuttgart.parser.JavaTXParser;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.SourceFileContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.SrcfileContext;
|
||||||
|
import de.dhbwstuttgart.parser.scope.GatherNames;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stellt die Java-Environment dar und speichert alle Binarys, Librarys und Sourcefiles im zu kompilierenden Projekt Sie erstellt anhand dieser Informationen die JavaClassNameRegistry
|
||||||
|
*
|
||||||
|
* TODO: Zur Initialisierung der CompilationEnvironment sollten alle SourceFiles mit ANTLR geparst werden und alle Klassen Generics und Typen herausgefunden werden
|
||||||
|
*/
|
||||||
|
public class CompilationEnvironment {
|
||||||
|
private final List<URL> librarys;
|
||||||
|
private final List<File> sourceFiles;
|
||||||
|
public final PackageCrawler packageCrawler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imitiert die Environment beim Aufruf des JavaCompilers auf einer Menge von java-Dateien Die Environment enth<EFBFBD>lt automatisch die Java Standard Library
|
||||||
|
*
|
||||||
|
* @param sourceFiles die zu kompilierenden Dateien
|
||||||
|
*/
|
||||||
|
public CompilationEnvironment(List<File> sourceFiles) {
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
// String bootClassPath = System.getProperty("sun.boot.class.path");
|
||||||
|
// DirectoryClassLoader cl = DirectoryClassLoader.getPlatformClassLoader();
|
||||||
|
String bootClassPath = System.getProperty("java.class.path");
|
||||||
|
librarys = new ArrayList<>();
|
||||||
|
for (String path : bootClassPath.split(File.pathSeparator)) {
|
||||||
|
try {
|
||||||
|
librarys.add(new URL("file:" + path));
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
new DebugException("Fehler im Classpath auf diesem System");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// URLClassLoader loader = new URLClassLoader(new URL[0], cl);
|
||||||
|
// librarys = Arrays.asList(loader.getURLs());
|
||||||
|
|
||||||
|
this.sourceFiles = sourceFiles;
|
||||||
|
this.packageCrawler = new PackageCrawler(librarys);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addClassesToRegistry(JavaClassRegistry registry, SourceFileContext tree, File sourceFile, JavaTXCompiler compiler) throws ClassNotFoundException, IOException {
|
||||||
|
Map<String, Integer> allNames;
|
||||||
|
if (tree instanceof SrcfileContext srcfile) {
|
||||||
|
allNames = GatherNames.getNames((SrcfileContext) tree, packageCrawler, compiler);
|
||||||
|
for (Class c : loadDefaultPackageClasses(getPackageName(srcfile), sourceFile, compiler)) {
|
||||||
|
allNames.put(c.getName(), c.getTypeParameters().length);
|
||||||
|
}
|
||||||
|
registry.addNames(allNames);
|
||||||
|
} else {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Class> loadDefaultPackageClasses(String packageName, File sourceFile, JavaTXCompiler compiler) throws IOException, ClassNotFoundException {
|
||||||
|
ClassLoader classLoader = compiler.getClassLoader();
|
||||||
|
List<Class> ret = new ArrayList<>();
|
||||||
|
// Set classLoader to include default package for this specific source file
|
||||||
|
File dir = sourceFile.getAbsoluteFile().getParentFile();
|
||||||
|
String dirPath = dir.toString() + "/";
|
||||||
|
if (packageName.length() > 0)
|
||||||
|
dirPath = dirPath.substring(0, dirPath.length() - packageName.length() - 1);
|
||||||
|
String path = dirPath;
|
||||||
|
ArrayList<File> defaultPath = Lists.newArrayList(new File(path));
|
||||||
|
classLoader = new DirectoryClassLoader(defaultPath, classLoader);
|
||||||
|
// Gather all names in the default package for this source file (classes that are imported by default)
|
||||||
|
File[] files = dir.listFiles((dir1, name) -> name.endsWith(".class"));
|
||||||
|
if (files != null)
|
||||||
|
for (File classFile : files) {
|
||||||
|
String className = classFile.getName().substring(0, classFile.getName().length() - 6);
|
||||||
|
if (className.matches("Fun\\d+\\$\\$.*"))
|
||||||
|
continue;
|
||||||
|
ret.add(classLoader.loadClass(packageName + className));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getPackageName(SrcfileContext forTree) {
|
||||||
|
String packageName = "";
|
||||||
|
if (forTree.packageDeclaration() != null && !forTree.packageDeclaration().qualifiedName().identifier().isEmpty())
|
||||||
|
packageName = forTree.packageDeclaration().qualifiedName().getText();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package de.dhbwstuttgart.environment;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class DirectoryClassLoader extends URLClassLoader implements IByteArrayClassLoader {
|
||||||
|
public DirectoryClassLoader(File directory, java.lang.ClassLoader parent) {
|
||||||
|
super(generateURLArray(dirToURL(directory)), parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DirectoryClassLoader(List<File> directory, java.lang.ClassLoader parent) {
|
||||||
|
super(directory.stream().map(DirectoryClassLoader::dirToURL).collect(Collectors.toList()).toArray(new URL[0]), parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static URL[] generateURLArray(URL url) {
|
||||||
|
return new URL[]{url};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static URL dirToURL(File url){
|
||||||
|
if(!url.isDirectory())throw new RuntimeException(url.toString() + " is not a directory");
|
||||||
|
try {
|
||||||
|
return url.toURI().toURL();
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> _defineClass(String name, byte[] code, int i, int length) throws ClassFormatError {
|
||||||
|
return defineClass(name, code, i, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> findClass(String name) throws ClassNotFoundException {
|
||||||
|
return super.findClass(name);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package de.dhbwstuttgart.environment;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public interface IByteArrayClassLoader {
|
||||||
|
|
||||||
|
Class loadClass(String path) throws ClassNotFoundException;
|
||||||
|
|
||||||
|
default Class loadClass(byte[] code) {
|
||||||
|
return this._defineClass(null, code, 0, code.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Class loadClass(Path path) throws IOException {
|
||||||
|
var code = Files.readAllBytes(path);
|
||||||
|
return this._defineClass(null, code, 0, code.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> findClass(String name) throws ClassNotFoundException;
|
||||||
|
|
||||||
|
Class _defineClass(String name, byte[] code, int i, int length) throws ClassFormatError;
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package de.dhbwstuttgart.environment;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
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
|
||||||
|
* Benutzt die Reflections-Library (https://github.com/ronmamo/reflections)
|
||||||
|
* Hilfe dazu: http://stackoverflow.com/a/9571146
|
||||||
|
*/
|
||||||
|
public class PackageCrawler {
|
||||||
|
|
||||||
|
final URL[] urls;
|
||||||
|
public PackageCrawler(List<URL> urlList) {
|
||||||
|
urls = urlList.toArray(new URL[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Class<?>> getClassesInPackage(String packageName){
|
||||||
|
/*
|
||||||
|
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);
|
||||||
|
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Class<?>> getAllAvailableClasses(){
|
||||||
|
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){
|
||||||
|
Map<String, Integer> nameList = new HashMap<>();
|
||||||
|
Set<Class<?>> classes = getClassesInPackage(packageName);
|
||||||
|
if(packageName.equals("java.lang") && ! classes.contains(Object.class)) {
|
||||||
|
classes.add(Object.class);
|
||||||
|
}
|
||||||
|
for(Class c : classes){
|
||||||
|
nameList.put(c.getName(), c.getTypeParameters().length);
|
||||||
|
}
|
||||||
|
return nameList;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package de.dhbwstuttgart.exceptions;
|
||||||
|
|
||||||
|
public class DebugException extends RuntimeException {
|
||||||
|
|
||||||
|
public DebugException(String message) {
|
||||||
|
System.err.print(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package de.dhbwstuttgart.exceptions;
|
||||||
|
|
||||||
|
public class NotImplementedException extends RuntimeException {
|
||||||
|
|
||||||
|
public NotImplementedException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotImplementedException(String string) {
|
||||||
|
super(string);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package de.dhbwstuttgart.exceptions;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public class ParserError extends TypeinferenceException{
|
||||||
|
|
||||||
|
public ParserError(Token offset){
|
||||||
|
super("Fehler beim Parsen", offset);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package de.dhbwstuttgart.exceptions;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eine RuntimeException, welche bei einem Fehler während des Typinferenzalgorithmus ausgelöst wird.
|
||||||
|
* Dies wird zum Beispiel durch Programmierfehler in der Java-Eingabedatei ausgelöst.
|
||||||
|
* @author Andreas Stadelmeier, a10023
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
//TODO: Diese Klasse muss von Exception erben
|
||||||
|
public class TypeinferenceException extends RuntimeException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Das Offset im Quelltext bei dem das Problem aufgetaucht ist
|
||||||
|
*/
|
||||||
|
private Token offset;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
public TypeinferenceException(String message, SyntaxTreeNode problemSource)
|
||||||
|
{
|
||||||
|
super(message);
|
||||||
|
this.message=message;
|
||||||
|
if(problemSource == null)throw new DebugException("TypinferenzException ohne Offset: "+this.message);
|
||||||
|
this.offset=problemSource.getOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeinferenceException(String message, Token offset){
|
||||||
|
this.message=message;
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return Der Offset an dem im Quellcode der Fehler aufgetreten ist.
|
||||||
|
*/
|
||||||
|
public Token getOffset(){
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage(){
|
||||||
|
return this.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package de.dhbwstuttgart.parser;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.environment.CompilationEnvironment;
|
||||||
|
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.SyntaxTreeGenerator;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Lexer;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.CharStream;
|
||||||
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class JavaTXParser {
|
||||||
|
public static Java17Parser.SourceFileContext parse(File source) throws IOException, java.lang.ClassNotFoundException {
|
||||||
|
InputStream stream = new FileInputStream(source);
|
||||||
|
// DEPRECATED: ANTLRInputStream input = new ANTLRInputStream(stream);
|
||||||
|
CharStream input = CharStreams.fromStream(stream);
|
||||||
|
Java17Lexer lexer = new Java17Lexer(input);
|
||||||
|
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
|
Java17Parser parser = new Java17Parser(tokens);
|
||||||
|
return parser.sourceFile();
|
||||||
|
/*
|
||||||
|
* SyntaxTreeGenerator generator = new SyntaxTreeGenerator(environment.getRegistry(source)); return generator.convert(tree);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Für das Typsystem ist es notwendig, dass sich der Source in einer Datei befindet: public SourceFile parse(String fileContent) throws IOException, java.lang.ClassNotFoundException { return this.parse(new ByteArrayInputStream(fileContent.getBytes(StandardCharsets.UTF_8))); }
|
||||||
|
*/
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package de.dhbwstuttgart.parser;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.CharStream;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
import org.antlr.v4.runtime.TokenSource;
|
||||||
|
|
||||||
|
public class NullToken implements Token {
|
||||||
|
@Override
|
||||||
|
public String getText() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getType() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLine() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCharPositionInLine() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChannel() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTokenIndex() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStartIndex() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStopIndex() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TokenSource getTokenSource() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharStream getInputStream() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.AssignLeftSide;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Expression;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.LocalVar;
|
||||||
|
|
||||||
|
public class AssignToLocal extends AssignLeftSide {
|
||||||
|
public final LocalVar localVar;
|
||||||
|
|
||||||
|
public AssignToLocal(LocalVar leftSide) {
|
||||||
|
super(leftSide.getType(), leftSide.getOffset());
|
||||||
|
localVar = leftSide;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,203 @@
|
|||||||
|
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.exceptions.DebugException;
|
||||||
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.Method;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.Pattern;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.Pair;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.model.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public class FCGenerator {
|
||||||
|
/**
|
||||||
|
* Baut die FiniteClosure aus availableClasses.
|
||||||
|
* Klassen welche nicht in availableClasses vorkommen werden im Java Classpath nachgeschlagen.
|
||||||
|
*
|
||||||
|
* @param availableClasses - Alle geparsten Klassen
|
||||||
|
*/
|
||||||
|
public static Set<UnifyPair> toUnifyFC(Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException {
|
||||||
|
return toFC(availableClasses, classLoader).stream().map(t -> UnifyTypeFactory.convert(t)).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Set<Pair> toFC(Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException {
|
||||||
|
HashSet<Pair> pairs = new HashSet<>();
|
||||||
|
//PL 2018-09-18: gtvs vor die for-Schleife gezogen, damit immer die gleichen Typeplaceholder eingesetzt werden.
|
||||||
|
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs = new HashMap<>();
|
||||||
|
for(ClassOrInterface cly : availableClasses){
|
||||||
|
List<Pair> newPairs = getSuperTypes(cly, availableClasses, gtvs, classLoader);
|
||||||
|
pairs.addAll(newPairs);
|
||||||
|
|
||||||
|
//For all Functional Interfaces FI: FunN$$<... args auf dem Functional Interface ...> <. FI is added to FC
|
||||||
|
if (isFunctionalInterface(cly)) {
|
||||||
|
pairs.add(genImplFunType(cly, newPairs.get(0).TA1, gtvs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Boolean isFunctionalInterface(ClassOrInterface cly) {
|
||||||
|
return (cly.isInterface() && (cly.isFunctionalInterface() || cly.getMethods().size() == 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Pair genImplFunType(ClassOrInterface cly, RefTypeOrTPHOrWildcardOrGeneric fIType, HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs) {
|
||||||
|
for(Method m : cly.getMethods()) {
|
||||||
|
if (!java.lang.reflect.Modifier.isAbstract(m.modifier))
|
||||||
|
continue;
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> tl =
|
||||||
|
(m.getParameterList().getFormalparalist()
|
||||||
|
.stream().map(p -> p.getType().acceptTV(new TypeExchanger(gtvs)))
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
tl.add(m.getReturnType().acceptTV(new TypeExchanger(gtvs)));
|
||||||
|
return new Pair(new RefType(new JavaClassName("Fun" + (tl.size()-1) + "$$"), tl, new NullToken()),
|
||||||
|
fIType);
|
||||||
|
}
|
||||||
|
return null; //kann nicht passieren, da die Methode nur aufgerufen wird wenn cl Functional Interface ist
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bildet eine Kette vom übergebenen Typ bis hin zum höchsten bekannten Typ
|
||||||
|
* Als Generics werden TPHs benutzt, welche der Unifikationsalgorithmus korrekt interpretieren muss.
|
||||||
|
* Die verwendeten TPHs werden in der Kette nach oben gereicht, so erhält der selbe GTV immer den selben TPH
|
||||||
|
* @param forType
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static List<Pair> getSuperTypes(ClassOrInterface forType, Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException {
|
||||||
|
return getSuperTypes(forType, availableClasses, new HashMap<>(), classLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param forType
|
||||||
|
* @param availableClasses
|
||||||
|
* @param gtvs
|
||||||
|
* @return
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
private static List<Pair> getSuperTypes(ClassOrInterface forType, Collection<ClassOrInterface> availableClasses,
|
||||||
|
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs, ClassLoader classLoader) throws ClassNotFoundException {
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
|
||||||
|
//Die GTVs, die in forType hinzukommen:
|
||||||
|
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> newGTVs = new HashMap<>();
|
||||||
|
//Generics mit gleichem Namen müssen den selben TPH bekommen
|
||||||
|
for(GenericTypeVar gtv : forType.getGenerics()){
|
||||||
|
if(!gtvs.containsKey(gtv.getName())){
|
||||||
|
TypePlaceholder replacePlaceholder = TypePlaceholder.fresh(new NullToken());
|
||||||
|
gtvs.put(gtv.getName(), replacePlaceholder);
|
||||||
|
newGTVs.put(gtv.getName(), replacePlaceholder);
|
||||||
|
}
|
||||||
|
params.add(gtvs.get(gtv.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
List<RefType> superClasses = new ArrayList<>();
|
||||||
|
superClasses.add(forType.getSuperClass());
|
||||||
|
superClasses.addAll(forType.getSuperInterfaces());
|
||||||
|
|
||||||
|
List<Pair> retList = new ArrayList<>();
|
||||||
|
for(RefType superType : superClasses){
|
||||||
|
Optional<ClassOrInterface> hasSuperclass = availableClasses.stream().filter(cl -> superType.getName().equals(cl.getClassName())).findAny();
|
||||||
|
ClassOrInterface superClass;
|
||||||
|
if(!hasSuperclass.isPresent()) //Wenn es die Klasse in den available Klasses nicht gibt wird sie im Classpath gesucht. Ansonsten Exception
|
||||||
|
{
|
||||||
|
superClass = ASTFactory.createClass(classLoader.loadClass(superType.getName().toString()));
|
||||||
|
}else{
|
||||||
|
superClass = hasSuperclass.get();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Die Parameter der superklasse müssen jetzt nach den Angaben in der Subklasse
|
||||||
|
modifiziert werden
|
||||||
|
Beispie: Matrix<A> extends Vector<Vector<A>>
|
||||||
|
Den ersten Parameter mit Vector<A> austauschen und dort alle Generics zu den Typplaceholdern in gtvs austauschen
|
||||||
|
*/
|
||||||
|
//Hier vermerken, welche Typen in der Superklasse ausgetauscht werden müssen
|
||||||
|
Iterator<GenericTypeVar> itGenParams = superClass.getGenerics().iterator();
|
||||||
|
Iterator<RefTypeOrTPHOrWildcardOrGeneric> itSetParams = superType.getParaList().iterator();
|
||||||
|
while(itSetParams.hasNext()){
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric setType = itSetParams.next();
|
||||||
|
//In diesem Typ die GTVs durch TPHs und Einsetzungen austauschen:
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric setSetType = setType.acceptTV(new TypeExchanger(gtvs));
|
||||||
|
newGTVs.put(itGenParams.next().getName(), setSetType);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Für den superType kann man nun zum Austauschen der Generics wieder die gtvs nehmen:
|
||||||
|
//Die newGTVs sind nur für den superClass ClassOrInterface welches möglicherweise per reflection geladen wurde abgestimmt
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric superRefType = superType.acceptTV(new TypeExchanger(gtvs));
|
||||||
|
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric t1 = new RefType(forType.getClassName(), params, new NullToken());
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric t2 = superRefType;
|
||||||
|
|
||||||
|
Pair ret = new Pair(t1, t2, PairOperator.SMALLER);
|
||||||
|
|
||||||
|
List<Pair> superTypes;
|
||||||
|
//Rekursiver Aufruf. Abbruchbedingung ist Object als Superklasse:
|
||||||
|
if(superClass.getClassName().equals(ASTFactory.createObjectClass().getClassName())){
|
||||||
|
superTypes = Arrays.asList(new Pair(ASTFactory.createObjectType(), ASTFactory.createObjectType(), PairOperator.SMALLER));
|
||||||
|
}else{
|
||||||
|
superTypes = getSuperTypes(superClass, availableClasses, newGTVs, classLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
retList.add(ret);
|
||||||
|
retList.addAll(superTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus.
|
||||||
|
*/
|
||||||
|
private static class TypeExchanger implements TypeVisitor<RefTypeOrTPHOrWildcardOrGeneric>{
|
||||||
|
|
||||||
|
private final HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs;
|
||||||
|
|
||||||
|
TypeExchanger(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) {
|
||||||
|
throw new DebugException("Dieser Fall darf nicht auftreten");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric visit(TypePlaceholder typePlaceholder) {
|
||||||
|
throw new DebugException("Dieser Fall darf nicht auftreten");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric visit(ExtendsWildcardType extendsWildcardType) {
|
||||||
|
throw new DebugException("Dieser Fall darf nicht auftreten");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric visit(GenericRefType genericRefType) {
|
||||||
|
if(! gtvs.containsKey(genericRefType.getParsedName()))
|
||||||
|
throw new DebugException("Dieser Fall darf nicht auftreten");
|
||||||
|
return gtvs.get(genericRefType.getParsedName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
|
||||||
|
public record FieldEntry(String name, RefTypeOrTPHOrWildcardOrGeneric type, int modifiers) {
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
|
||||||
|
public class GenericContext {
|
||||||
|
private final String parentMethod;
|
||||||
|
private final JavaClassName parentClass;
|
||||||
|
|
||||||
|
public GenericContext(JavaClassName parentClass, String parentMethod) {
|
||||||
|
if(parentMethod == null)parentMethod = "";
|
||||||
|
this.parentClass = parentClass;
|
||||||
|
this.parentMethod = parentMethod;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,46 @@
|
|||||||
|
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.AbstractASTWalker;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.Constructor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SyntacticSugar {
|
||||||
|
|
||||||
|
public static List<Statement> addTrailingReturn(List<Statement> statements) {
|
||||||
|
if (statements.size() != 0) {
|
||||||
|
Statement lastStmt = statements.get(statements.size() - 1);
|
||||||
|
ReturnFinder hasReturn = new ReturnFinder();
|
||||||
|
lastStmt.accept(hasReturn);
|
||||||
|
if (hasReturn.hasReturn)
|
||||||
|
return statements;
|
||||||
|
}
|
||||||
|
statements.add(new ReturnVoid(new NullToken()));
|
||||||
|
return statements;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ReturnFinder extends AbstractASTWalker {
|
||||||
|
public boolean hasReturn = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Return aReturn) {
|
||||||
|
hasReturn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ReturnVoid aReturn) {
|
||||||
|
hasReturn = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasReturn(Block block) {
|
||||||
|
for (Statement s : block.getStatements())
|
||||||
|
if (s instanceof Return)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,639 @@
|
|||||||
|
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
|
||||||
|
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.*;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.Record;
|
||||||
|
import org.antlr.v4.runtime.CommonToken;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import com.google.common.graph.ElementOrder.Type;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.environment.PackageCrawler;
|
||||||
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
|
import de.dhbwstuttgart.exceptions.TypeinferenceException;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassBodyDeclarationContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassOrInterfaceTypeContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassorinterfacedeclContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.ConstructorDeclarationContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.ConstructordeclContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.EmptymethodContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.GenericConstructorDeclarationContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.GenericDeclarationListContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.GenericInterfaceMethodDeclarationContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.GenericconstructorContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.GenericinterfacemethodContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.GenericmethodContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.InterfaceBodyDeclarationContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.InterfaceCommonBodyDeclarationContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.InterfaceMethodDeclarationContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.InterfaceMethodModifierContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.InterfaceconstContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.InterfacememberContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.InterfacemethodContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.MemberclassorinterfaceContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.MemberconstructorContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.MemberdeclContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.MemberfieldContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.MembermethodContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.MethodBodyContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.MethodDeclarationContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.MethodHeaderContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.MethodblockContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.MethoddeclContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.ModifierContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.NoclassorinterfaceContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.RecordComponentContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.RecordDeclarationContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.RefType2Context;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.SrcfileContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.TypeArgumentsContext;
|
||||||
|
import de.dhbwstuttgart.parser.scope.GatherNames;
|
||||||
|
import de.dhbwstuttgart.parser.scope.GenericsRegistry;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Assign;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.AssignLeftSide;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.AssignToField;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Block;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.FieldVar;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.LocalVar;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Return;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Statement;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.This;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
|
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 {
|
||||||
|
private JavaClassRegistry reg;
|
||||||
|
private final GenericsRegistry globalGenerics;
|
||||||
|
public String pkgName = "";
|
||||||
|
public Set<JavaClassName> imports = new HashSet<>();
|
||||||
|
HashMap<String, Integer> allmodifiers = new HashMap<>();
|
||||||
|
// PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH
|
||||||
|
// bekommen
|
||||||
|
private final Map<String, FieldEntry> fields = new HashMap<>();
|
||||||
|
// PL 2019-10-23: Muss für jede Klasse neu initilisiert werden
|
||||||
|
List<Statement> fieldInitializations = new ArrayList<>();
|
||||||
|
List<Statement> staticFieldInitializations = new ArrayList<>();
|
||||||
|
|
||||||
|
private final JavaTXCompiler compiler;
|
||||||
|
private RefType superClass;
|
||||||
|
|
||||||
|
public SyntaxTreeGenerator(JavaTXCompiler compiler, JavaClassRegistry reg, GenericsRegistry globalGenerics) {
|
||||||
|
// Die Generics müssen während des Bauens des AST erstellt werden,
|
||||||
|
// da diese mit der Methode oder Klasse, in welcher sie deklariert werden
|
||||||
|
// verknüpft sein müssen. Dennoch werden die Namen aller Generics in einer
|
||||||
|
// globalen Datenbank benötigt.
|
||||||
|
this.globalGenerics = globalGenerics;
|
||||||
|
this.reg = reg;
|
||||||
|
this.allmodifiers.put(Modifier.toString(Modifier.PUBLIC), Modifier.PUBLIC);
|
||||||
|
this.allmodifiers.put(Modifier.toString(Modifier.PRIVATE), Modifier.PRIVATE);
|
||||||
|
this.allmodifiers.put(Modifier.toString(Modifier.PROTECTED), Modifier.PROTECTED);
|
||||||
|
this.allmodifiers.put(Modifier.toString(Modifier.ABSTRACT), Modifier.ABSTRACT);
|
||||||
|
this.allmodifiers.put(Modifier.toString(Modifier.STATIC), Modifier.STATIC);
|
||||||
|
this.allmodifiers.put(Modifier.toString(Modifier.STRICT), Modifier.STRICT);
|
||||||
|
this.allmodifiers.put(Modifier.toString(Modifier.FINAL), Modifier.FINAL);
|
||||||
|
this.allmodifiers.put(Modifier.toString(Modifier.TRANSIENT), Modifier.TRANSIENT);
|
||||||
|
this.allmodifiers.put(Modifier.toString(Modifier.VOLATILE), Modifier.VOLATILE);
|
||||||
|
this.allmodifiers.put(Modifier.toString(Modifier.SYNCHRONIZED), Modifier.SYNCHRONIZED);
|
||||||
|
this.allmodifiers.put(Modifier.toString(Modifier.NATIVE), Modifier.NATIVE);
|
||||||
|
this.allmodifiers.put(Modifier.toString(Modifier.INTERFACE), Modifier.INTERFACE);
|
||||||
|
this.allmodifiers.put("sealed", 4096);
|
||||||
|
this.allmodifiers.put("non-sealed", 8192);
|
||||||
|
this.allmodifiers.put("default", 16384);
|
||||||
|
this.allmodifiers.put("strictfp", 32768);
|
||||||
|
|
||||||
|
this.compiler = compiler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaClassRegistry getReg() {
|
||||||
|
return this.reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String convertQualifiedName(Java17Parser.QualifiedNameContext ctx) {
|
||||||
|
/*
|
||||||
|
* String ret = ""; for (Java17Parser.IdentifierContext ident : ctx.identifier()) { ret += ident.getText(); if (ctx.identifier().iterator().hasNext()) { ret += '.'; } }
|
||||||
|
*/
|
||||||
|
return ctx.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convert(List<ClassOrInterface> classes, Java17Parser.SourceFileContext ctx, PackageCrawler packageCrawler) throws ClassNotFoundException, NotImplementedException {
|
||||||
|
SrcfileContext srcfile;
|
||||||
|
if (ctx instanceof Java17Parser.SrcfileContext) {
|
||||||
|
srcfile = (SrcfileContext) ctx;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (srcfile.packageDeclaration() != null)
|
||||||
|
this.pkgName = convert(srcfile.packageDeclaration());
|
||||||
|
Map<String, Integer> imports = GatherNames.getImports(srcfile, packageCrawler, compiler);
|
||||||
|
this.imports = imports.keySet().stream().map(name -> reg.getName(name)).collect(Collectors.toSet());
|
||||||
|
for (Java17Parser.ClassOrInterfaceContext type : srcfile.classOrInterface()) {
|
||||||
|
ClassorinterfacedeclContext clsoif;
|
||||||
|
if (type instanceof NoclassorinterfaceContext) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
clsoif = (ClassorinterfacedeclContext) type;
|
||||||
|
}
|
||||||
|
ClassOrInterface newClass;
|
||||||
|
int modifiers = 0;
|
||||||
|
if (!clsoif.classOrInterfaceModifier().isEmpty()) {
|
||||||
|
for (Java17Parser.ClassOrInterfaceModifierContext mod : clsoif.classOrInterfaceModifier()) {
|
||||||
|
modifiers += allmodifiers.get(mod.getText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fieldInitializations = new ArrayList<>(); // PL 2019-10-22: muss für jede Klasse neu initilisiert werden
|
||||||
|
staticFieldInitializations = new ArrayList<>();
|
||||||
|
if (!Objects.isNull(clsoif.classDeclaration())) {
|
||||||
|
newClass = convertClass(clsoif.classDeclaration(), modifiers);
|
||||||
|
} else if (!Objects.isNull(clsoif.interfaceDeclaration())) {
|
||||||
|
newClass = convertInterface(clsoif.interfaceDeclaration(), modifiers);
|
||||||
|
} else if (!Objects.isNull(clsoif.recordDeclaration())) {
|
||||||
|
newClass = convertRecord(clsoif.recordDeclaration(), modifiers);
|
||||||
|
} else {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
classes.add(newClass);
|
||||||
|
}
|
||||||
|
if (classes.isEmpty()) {
|
||||||
|
throw new NotImplementedException("SourceFile enthält keine Klassen");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String convert(Java17Parser.PackageDeclarationContext ctx) {
|
||||||
|
return convertQualifiedName(ctx.qualifiedName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClassOrInterface convertClass(Java17Parser.ClassDeclarationContext ctx, int modifiers) {
|
||||||
|
String className = this.pkgName + (this.pkgName.length() > 0 ? "." : "") + ctx.identifier().getText();
|
||||||
|
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?
|
||||||
|
throw new TypeinferenceException("Name " + className + " bereits vorhanden in " + reg.getName(className).toString(), ctx.getStart());
|
||||||
|
}
|
||||||
|
GenericsRegistry generics = createGenerics(ctx.genericDeclarationList(), name, "", reg, new GenericsRegistry(globalGenerics));
|
||||||
|
Token offset = ctx.getStart();
|
||||||
|
GenericDeclarationList genericClassParameters;
|
||||||
|
if (ctx.genericDeclarationList() == null) {
|
||||||
|
genericClassParameters = new GenericDeclarationList(new ArrayList<>(), ctx.classBody().getStart());
|
||||||
|
} else {
|
||||||
|
genericClassParameters = TypeGenerator.convert(ctx.genericDeclarationList(), name, "", reg, generics);
|
||||||
|
}
|
||||||
|
RefType superClass;
|
||||||
|
if (ctx.EXTENDS() != null) {
|
||||||
|
superClass = convertSuperType(ctx.typeType());
|
||||||
|
} else {
|
||||||
|
superClass = new RefType(ASTFactory.createObjectClass().getClassName(), ctx.getStart());
|
||||||
|
}
|
||||||
|
this.superClass = superClass;
|
||||||
|
List<Field> fielddecl = new ArrayList<>();
|
||||||
|
List<Method> methods = new ArrayList<>();
|
||||||
|
List<Constructor> constructors = new ArrayList<>();
|
||||||
|
Boolean isInterface = false;
|
||||||
|
Boolean isFunctionalInterface = false;
|
||||||
|
List<RefType> implementedInterfaces = new ArrayList<>();
|
||||||
|
List<RefType> permittedSubtypes = new ArrayList<>();
|
||||||
|
for (ClassBodyDeclarationContext clsbodydecl : ctx.classBody().classBodyDeclaration()) {
|
||||||
|
convert(clsbodydecl, fielddecl, constructors, methods, name, superClass, generics);
|
||||||
|
}
|
||||||
|
if (constructors.isEmpty()) {
|
||||||
|
constructors.add(generateStandardConstructor(ctx.identifier().getText(), name, superClass, genericClassParameters, offset));
|
||||||
|
}
|
||||||
|
if (ctx.IMPLEMENTS() != null) {
|
||||||
|
implementedInterfaces.addAll(convert(ctx.typeList(0), generics));
|
||||||
|
}
|
||||||
|
// Ist Bit für 'sealed'-Modifier gesetzt
|
||||||
|
if ((modifiers & 4096) != 0) {
|
||||||
|
if (!Objects.isNull(ctx.PERMITS())) {
|
||||||
|
// permitted subtypes sind letzte typeList (siehe Grammatikregel 'classDeclaration')
|
||||||
|
permittedSubtypes.addAll(convert(ctx.typeList(ctx.typeList().size() - 1), generics));
|
||||||
|
} else {
|
||||||
|
// falls sealed modifier ohne 'permits'-List oder umgekehrt
|
||||||
|
throw new NotImplementedException("Invalid sealed class declaration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var ctor = Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), fieldInitializations, genericClassParameters, offset));
|
||||||
|
var staticCtor = Optional.of(this.generateStaticConstructor(ctx.identifier().getText(), staticFieldInitializations, genericClassParameters, offset));
|
||||||
|
return new ClassOrInterface(modifiers, name, fielddecl, ctor, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, isFunctionalInterface, implementedInterfaces, permittedSubtypes, offset);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private de.dhbwstuttgart.syntaxtree.Record convertRecord(RecordDeclarationContext recordDeclaration, int modifiers) {
|
||||||
|
this.superClass = new RefType(new JavaClassName("java.lang.Record"), new NullToken());
|
||||||
|
String identifier = recordDeclaration.identifier().getText();
|
||||||
|
String className = this.pkgName + (this.pkgName.length() > 0 ? "." : "") + identifier;
|
||||||
|
JavaClassName name = reg.getName(className); // Holt den Package Namen mit dazu
|
||||||
|
Token offset = recordDeclaration.getStart();
|
||||||
|
GenericsRegistry generics = createGenerics(recordDeclaration.genericDeclarationList(), name, "", reg, new GenericsRegistry(globalGenerics));
|
||||||
|
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(), recordDeclaration.getStart());
|
||||||
|
}
|
||||||
|
GenericDeclarationList genericClassParameters;
|
||||||
|
if (recordDeclaration.genericDeclarationList() == null) {
|
||||||
|
genericClassParameters = new GenericDeclarationList(new ArrayList<>(), recordDeclaration.recordBody().getStart());
|
||||||
|
} else {
|
||||||
|
genericClassParameters = TypeGenerator.convert(recordDeclaration.genericDeclarationList(), name, "", reg, generics);
|
||||||
|
}
|
||||||
|
RefType superClass = new RefType(ASTFactory.createClass(java.lang.Record.class).getClassName(), offset);
|
||||||
|
List<Field> fielddecl = new ArrayList<>();
|
||||||
|
List<Method> methods = new ArrayList<>();
|
||||||
|
List<Constructor> constructors = new ArrayList<>();
|
||||||
|
Boolean isInterface = false;
|
||||||
|
List<RefType> implementedInterfaces = new ArrayList<>();
|
||||||
|
List<Pattern> constructorParameters = new ArrayList<>();
|
||||||
|
List<Statement> constructorStatements = new ArrayList<>();
|
||||||
|
for (RecordComponentContext component : recordDeclaration.recordHeader().recordComponentList().recordComponent()) {
|
||||||
|
int fieldmodifiers = allmodifiers.get("private") + allmodifiers.get("final");
|
||||||
|
String fieldname = component.identifier().getText();
|
||||||
|
Token fieldoffset = component.getStart();
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric fieldtype = null;
|
||||||
|
if (Objects.isNull(component.typeType())) {
|
||||||
|
fieldtype = TypePlaceholder.fresh(offset);
|
||||||
|
} else {
|
||||||
|
fieldtype = TypeGenerator.convert(component.typeType(), reg, generics);
|
||||||
|
}
|
||||||
|
fielddecl.add(new Field(fieldname, fieldtype, fieldmodifiers, fieldoffset));
|
||||||
|
constructorParameters.add(new FormalParameter(fieldname, fieldtype, fieldoffset));
|
||||||
|
FieldVar fieldvar = new FieldVar(new This(offset), false, fieldname, fieldtype, fieldoffset);
|
||||||
|
constructorStatements.add(new Assign(new AssignToField(fieldvar), new LocalVar(fieldname, fieldtype, fieldoffset), offset));
|
||||||
|
Statement returnStatement = new Return(fieldvar, offset);
|
||||||
|
methods.add(new Method(allmodifiers.get("public"), fieldname, fieldtype, new ParameterList(new ArrayList<>(), offset), new Block(Arrays.asList(returnStatement), offset), new GenericDeclarationList(new ArrayList<>(), offset), offset));
|
||||||
|
}
|
||||||
|
RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), genericClassParameters, offset);
|
||||||
|
Constructor implicitConstructor = new Constructor(allmodifiers.get("public"), identifier, classType, new ParameterList(constructorParameters, offset), new Block(constructorStatements, offset), genericClassParameters, offset);
|
||||||
|
Optional<Constructor> initializations = Optional.of(implicitConstructor);
|
||||||
|
constructors.add(implicitConstructor);
|
||||||
|
for (ClassBodyDeclarationContext bodyDeclaration : recordDeclaration.recordBody().classBodyDeclaration()) {
|
||||||
|
convert(bodyDeclaration, fielddecl, constructors, methods, name, superClass, generics);
|
||||||
|
}
|
||||||
|
if (!Objects.isNull(recordDeclaration.IMPLEMENTS())) {
|
||||||
|
implementedInterfaces.addAll(convert(recordDeclaration.typeList(), generics));
|
||||||
|
}
|
||||||
|
var staticCtor = Optional.of(this.generateStaticConstructor(recordDeclaration.identifier().getText(), staticFieldInitializations, genericClassParameters, offset));
|
||||||
|
return new Record(modifiers, name, fielddecl, initializations, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void convert(ClassBodyDeclarationContext classBody, List<Field> fields, List<Constructor> constructors, List<Method> methods, JavaClassName name, RefType superClass, GenericsRegistry generics) {
|
||||||
|
MemberdeclContext member;
|
||||||
|
if (classBody instanceof MemberdeclContext) {
|
||||||
|
member = (MemberdeclContext) classBody;
|
||||||
|
Integer membermodifiers = 0;
|
||||||
|
for (ModifierContext mod : member.modifier()) {
|
||||||
|
membermodifiers += allmodifiers.get(mod.getText());
|
||||||
|
}
|
||||||
|
switch (member.memberDeclaration()) {
|
||||||
|
case MemberclassorinterfaceContext memberclsoif: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MemberfieldContext memberfield: {
|
||||||
|
fields.addAll(convert(memberfield.fieldDeclaration(), membermodifiers, generics));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MembermethodContext membermethod: {
|
||||||
|
Method convertedMethod = convert(membermodifiers, membermethod.method(), name, superClass, generics);
|
||||||
|
if (convertedMethod instanceof Constructor constructor) {
|
||||||
|
constructors.add(constructor);
|
||||||
|
} else {
|
||||||
|
methods.add(convertedMethod);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MemberconstructorContext memberconstructor: {
|
||||||
|
constructors.add(convert(membermodifiers, memberconstructor.constructor(), name, superClass, generics));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (classBody instanceof Java17Parser.ClassblockContext ctx && ctx.STATIC() != null) {
|
||||||
|
// Static blocks
|
||||||
|
var stmtgen = new StatementGenerator(superClass, compiler, reg, generics, this.fields, new HashMap<>());
|
||||||
|
var block = stmtgen.convert(((Java17Parser.ClassblockContext) classBody).block(), false);
|
||||||
|
staticFieldInitializations.addAll(block.statements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClassOrInterface convertInterface(Java17Parser.InterfaceDeclarationContext ctx, int modifiers) {
|
||||||
|
this.superClass = new RefType(new JavaClassName("java.lang.Object"), new NullToken());
|
||||||
|
String className = this.pkgName.length() > 0 ? this.pkgName + "." : "" + ctx.identifier().getText();
|
||||||
|
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?
|
||||||
|
throw new TypeinferenceException("Name " + className + " bereits vorhanden in " + reg.getName(className).toString(), ctx.getStart());
|
||||||
|
}
|
||||||
|
if (!Modifier.isInterface(modifiers))
|
||||||
|
modifiers += Modifier.INTERFACE;
|
||||||
|
|
||||||
|
GenericsRegistry generics = createGenerics(ctx.genericDeclarationList(), name, "", reg, new GenericsRegistry(globalGenerics));
|
||||||
|
|
||||||
|
GenericDeclarationList genericParams;
|
||||||
|
if (!Objects.isNull(ctx.genericDeclarationList())) {
|
||||||
|
genericParams = TypeGenerator.convert(ctx.genericDeclarationList(), name, "", reg, generics);
|
||||||
|
} else {
|
||||||
|
genericParams = createEmptyGenericDeclarationList(ctx.identifier().getStart());
|
||||||
|
}
|
||||||
|
RefType superClass = ASTFactory.createObjectType();
|
||||||
|
|
||||||
|
List<Field> fields = new ArrayList<>();
|
||||||
|
List<Method> methods = new ArrayList<>();
|
||||||
|
for (InterfaceBodyDeclarationContext interfacebody : ctx.interfaceBody().interfaceBodyDeclaration()) {
|
||||||
|
if (interfacebody instanceof Java17Parser.EmptyinterfaceContext) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
InterfacememberContext interfacemember = (InterfacememberContext) interfacebody;
|
||||||
|
int membermodifiers = 0;
|
||||||
|
for (ModifierContext mod : interfacemember.modifier()) {
|
||||||
|
membermodifiers += allmodifiers.get(mod.getText());
|
||||||
|
}
|
||||||
|
int methodmodifiers = membermodifiers;
|
||||||
|
switch (interfacemember.interfaceMemberDeclaration()) {
|
||||||
|
case InterfaceconstContext constant:
|
||||||
|
fields.add(convert(constant));
|
||||||
|
break;
|
||||||
|
case InterfacemethodContext method:
|
||||||
|
InterfaceMethodDeclarationContext declaration = method.interfaceMethodDeclaration();
|
||||||
|
for (InterfaceMethodModifierContext mod : declaration.interfaceMethodModifier()) {
|
||||||
|
methodmodifiers += allmodifiers.get(mod.getText());
|
||||||
|
}
|
||||||
|
InterfaceCommonBodyDeclarationContext commonbody = declaration.interfaceCommonBodyDeclaration();
|
||||||
|
methods.add(convert(methodmodifiers, commonbody, new GenericDeclarationList(new ArrayList<>(), commonbody.getStart()), generics));
|
||||||
|
break;
|
||||||
|
case GenericinterfacemethodContext genericmethod:
|
||||||
|
GenericInterfaceMethodDeclarationContext genericdeclaration = genericmethod.genericInterfaceMethodDeclaration();
|
||||||
|
int genericmethodmodifiers = 0;
|
||||||
|
for (InterfaceMethodModifierContext mod : genericdeclaration.interfaceMethodModifier()) {
|
||||||
|
genericmethodmodifiers += allmodifiers.get(mod.getText());
|
||||||
|
}
|
||||||
|
commonbody = genericdeclaration.interfaceCommonBodyDeclaration();
|
||||||
|
GenericDeclarationList gtv = TypeGenerator.convert(genericdeclaration.genericDeclarationList(), name, commonbody.identifier().getText(), reg, generics);
|
||||||
|
methods.add(convert(genericmethodmodifiers, commonbody, gtv, generics));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<RefType> extendedInterfaces = new ArrayList<>();
|
||||||
|
if (!Objects.isNull(ctx.EXTENDS())) {
|
||||||
|
extendedInterfaces.addAll(convert(ctx.typeList(0), generics));
|
||||||
|
}
|
||||||
|
List<RefType> permittedSubtypes = new ArrayList<>();
|
||||||
|
// Ist Bit für 'sealed'-Modifier gesetzt
|
||||||
|
if ((modifiers & 4096) != 0) {
|
||||||
|
if (!Objects.isNull(ctx.PERMITS())) {
|
||||||
|
// permitted subtypes sind letzte typeList (siehe Grammatikregel 'classDeclaration')
|
||||||
|
permittedSubtypes.addAll(convert(ctx.typeList(ctx.typeList().size() - 1), generics));
|
||||||
|
} else {
|
||||||
|
// falls sealed modifier ohne 'permits'-List oder umgekehrt
|
||||||
|
throw new NotImplementedException("Invalid sealed class declaration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var staticCtor = Optional.of(this.generateStaticConstructor(ctx.identifier().getText(), staticFieldInitializations, genericParams, ctx.getStart()));
|
||||||
|
return new ClassOrInterface(modifiers, name, fields, Optional.empty(), staticCtor, methods, new ArrayList<>(), genericParams, superClass, true, methods.size() == 1 ? true : false, extendedInterfaces, permittedSubtypes, ctx.getStart());
|
||||||
|
}
|
||||||
|
|
||||||
|
private GenericDeclarationList createEmptyGenericDeclarationList(Token classNameIdentifier) {
|
||||||
|
CommonToken gtvOffset = new CommonToken(classNameIdentifier);
|
||||||
|
gtvOffset.setCharPositionInLine(gtvOffset.getCharPositionInLine() + classNameIdentifier.getText().length());
|
||||||
|
gtvOffset.setStartIndex(gtvOffset.getStopIndex() + 1);
|
||||||
|
return new GenericDeclarationList(new ArrayList<>(), gtvOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Field convert(InterfaceconstContext constant) {
|
||||||
|
// TODO: Erstelle hier ein Feld!
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Method convert(int modifiers, InterfaceCommonBodyDeclarationContext bodydeclaration, GenericDeclarationList gtvDeclarations, GenericsRegistry generics) {
|
||||||
|
String name = bodydeclaration.identifier().getText();
|
||||||
|
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric retType;
|
||||||
|
if (Objects.isNull(bodydeclaration.refType())) {
|
||||||
|
retType = TypePlaceholder.fresh(bodydeclaration.getStart());
|
||||||
|
} else {
|
||||||
|
if (bodydeclaration.refType() instanceof RefType2Context reftype) {
|
||||||
|
retType = TypeGenerator.convert(reftype.typeType(), reg, generics);
|
||||||
|
} else {
|
||||||
|
retType = new Void(bodydeclaration.refType().getStart());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
|
||||||
|
ParameterList paramlist = stmtgen.convert(bodydeclaration.formalParameters().formalParameterList());
|
||||||
|
MethodBodyContext body = bodydeclaration.methodBody();
|
||||||
|
Block block = null;
|
||||||
|
if (!(body instanceof EmptymethodContext)) {
|
||||||
|
MethodblockContext methodblock = (MethodblockContext) body;
|
||||||
|
block = stmtgen.convert(methodblock.block(), true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
modifiers += Modifier.ABSTRACT;
|
||||||
|
}
|
||||||
|
return new Method(modifiers, name, retType, paramlist, block, gtvDeclarations, bodydeclaration.getStart());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.9
|
||||||
|
*/
|
||||||
|
private Constructor generateStandardConstructor(String className, JavaClassName parentClass, RefType superClass, GenericDeclarationList classGenerics, Token offset) {
|
||||||
|
RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset);
|
||||||
|
ParameterList params = new ParameterList(new ArrayList<>(), offset);
|
||||||
|
Block block = new Block(new ArrayList<>(), offset);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset); // fieldInitializations
|
||||||
|
// geloescht PL
|
||||||
|
// 2018-11-24
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fieldInitializations werden in einem Psedokonstruktor in der abstrakten Syntax gespeichert
|
||||||
|
*/
|
||||||
|
private Constructor generatePseudoConstructor(String className, List<Statement> initializations, GenericDeclarationList classGenerics, Token offset) {
|
||||||
|
RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset);
|
||||||
|
ParameterList params = new ParameterList(new ArrayList<>(), offset);
|
||||||
|
Block block = new Block(new ArrayList<>(initializations), offset);
|
||||||
|
return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset /*
|
||||||
|
* fieldInitializations geloescht PL 2018-11-24
|
||||||
|
*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Method generateStaticConstructor(String className, List<Statement> initializations, GenericDeclarationList classGenerics, Token offset) {
|
||||||
|
RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset);
|
||||||
|
ParameterList params = new ParameterList(new ArrayList<>(), offset);
|
||||||
|
Block block = new Block(new ArrayList<>(initializations), offset);
|
||||||
|
return new Method(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RefType convertSuperType(Java17Parser.TypeTypeContext typeType) {
|
||||||
|
ClassOrInterfaceTypeContext supertypecontext = typeType.classOrInterfaceType();
|
||||||
|
if (supertypecontext != null && supertypecontext.DOT().size() > 0) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
} else {
|
||||||
|
TypeArgumentsContext typeArguments = (typeType.classOrInterfaceType().typeArguments().size() > 0) ? typeType.classOrInterfaceType().typeArguments().get(typeType.classOrInterfaceType().typeArguments().size() - 1) : null;
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric ret = TypeGenerator.convertTypeName(typeType.classOrInterfaceType().typeIdentifier().getText(), typeArguments, typeType.getStart(), reg, globalGenerics);
|
||||||
|
if (ret instanceof RefType) {
|
||||||
|
return (RefType) ret;
|
||||||
|
} else {
|
||||||
|
throw new TypeinferenceException(typeType.getText() + " ist kein gültiger Supertyp", typeType.getStart());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<RefType> convert(Java17Parser.TypeListContext ctx, GenericsRegistry generics) {
|
||||||
|
List<RefType> ret = new ArrayList<>();
|
||||||
|
for (Java17Parser.TypeTypeContext type : ctx.typeType()) {
|
||||||
|
ret.add((RefType) TypeGenerator.convert(type, reg, generics));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Method convert(int modifiers, Java17Parser.MethodContext methodContext, JavaClassName parentClass, RefType superClass, GenericsRegistry generics) {
|
||||||
|
GenericsRegistry localgenerics = generics;
|
||||||
|
MethodDeclarationContext methoddeclaration;
|
||||||
|
GenericDeclarationListContext genericdeclarations;
|
||||||
|
GenericDeclarationList gtvDeclarations;
|
||||||
|
MethodHeaderContext header;
|
||||||
|
String name;
|
||||||
|
if (methodContext instanceof GenericmethodContext) {
|
||||||
|
GenericmethodContext gmc = (GenericmethodContext) methodContext;
|
||||||
|
genericdeclarations = gmc.genericMethodDeclaration().genericDeclarationList();
|
||||||
|
methoddeclaration = gmc.genericMethodDeclaration().methodDeclaration();
|
||||||
|
header = methoddeclaration.methodHeader();
|
||||||
|
name = header.identifier().getText();
|
||||||
|
localgenerics.putAll(createGenerics(genericdeclarations, parentClass, name, reg, generics));
|
||||||
|
gtvDeclarations = TypeGenerator.convert(genericdeclarations, parentClass, name, reg, localgenerics);
|
||||||
|
} else {
|
||||||
|
MethoddeclContext mdc = (MethoddeclContext) methodContext;
|
||||||
|
methoddeclaration = mdc.methodDeclaration();
|
||||||
|
header = methoddeclaration.methodHeader();
|
||||||
|
gtvDeclarations = new GenericDeclarationList(new ArrayList<>(), header.getStart());
|
||||||
|
name = header.identifier().getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric retType;
|
||||||
|
if (Objects.isNull(header.refType())) {
|
||||||
|
retType = TypePlaceholder.fresh(header.getStart());
|
||||||
|
} else {
|
||||||
|
if (header.refType() instanceof RefType2Context reftype) {
|
||||||
|
retType = TypeGenerator.convert(reftype.typeType(), reg, generics);
|
||||||
|
} else {
|
||||||
|
retType = new Void(header.refType().getStart());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>());
|
||||||
|
ParameterList paramlist = stmtgen.convert(header.formalParameters().formalParameterList());
|
||||||
|
MethodBodyContext body = methoddeclaration.methodBody();
|
||||||
|
Block block = null;
|
||||||
|
if (body instanceof EmptymethodContext emptymethod) {
|
||||||
|
if (!Modifier.isAbstract(modifiers)) {
|
||||||
|
// TODO: Error! Abstrakte Methode ohne abstrakt Keyword
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MethodblockContext methodblock = (MethodblockContext) body;
|
||||||
|
block = stmtgen.convert(methodblock.block(), true);
|
||||||
|
}
|
||||||
|
if (name.equals(parentClass.getClassName())) {
|
||||||
|
return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, methoddeclaration.getStart());
|
||||||
|
} else {
|
||||||
|
return new Method(modifiers, name, retType, paramlist, block, gtvDeclarations, methoddeclaration.getStart());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Constructor convert(int modifiers, Java17Parser.ConstructorContext constructorContext, JavaClassName parentClass, RefType superClass, GenericsRegistry generics) {
|
||||||
|
GenericsRegistry localgenerics = generics;
|
||||||
|
GenericDeclarationListContext genericdeclarations;
|
||||||
|
GenericDeclarationList gtvDeclarations;
|
||||||
|
ConstructorDeclarationContext constructordeclaration;
|
||||||
|
String name;
|
||||||
|
if (constructorContext instanceof GenericconstructorContext) {
|
||||||
|
GenericconstructorContext genericconstructor = (GenericconstructorContext) constructorContext;
|
||||||
|
GenericConstructorDeclarationContext gcdeclaration = genericconstructor.genericConstructorDeclaration();
|
||||||
|
name = gcdeclaration.constructorDeclaration().identifier().getText();
|
||||||
|
genericdeclarations = gcdeclaration.genericDeclarationList();
|
||||||
|
constructordeclaration = gcdeclaration.constructorDeclaration();
|
||||||
|
localgenerics.putAll(createGenerics(genericdeclarations, parentClass, name, reg, generics));
|
||||||
|
gtvDeclarations = TypeGenerator.convert(genericdeclarations, parentClass, name, reg, localgenerics);
|
||||||
|
} else {
|
||||||
|
ConstructordeclContext constructordeclarationcontext = (ConstructordeclContext) constructorContext;
|
||||||
|
constructordeclaration = constructordeclarationcontext.constructorDeclaration();
|
||||||
|
name = constructordeclaration.identifier().getText();
|
||||||
|
gtvDeclarations = new GenericDeclarationList(new ArrayList<>(), constructordeclaration.getStart());
|
||||||
|
}
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric retType = TypeGenerator.convertTypeName(name, constructordeclaration.getStart(), reg, localgenerics);
|
||||||
|
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>());
|
||||||
|
ParameterList paramlist = stmtgen.convert(constructordeclaration.formalParameters().formalParameterList());
|
||||||
|
Block block = stmtgen.convert(constructordeclaration.constructorBody, true);
|
||||||
|
return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, constructordeclaration.getStart());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<? extends Field> convert(Java17Parser.FieldDeclarationContext fieldDeclContext, int modifiers, GenericsRegistry generics) {
|
||||||
|
List<Field> ret = new ArrayList<>();
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric fieldType;
|
||||||
|
if (fieldDeclContext.typeType() != null) {
|
||||||
|
fieldType = TypeGenerator.convert(fieldDeclContext.typeType(), reg, generics);
|
||||||
|
} else {
|
||||||
|
// PL 2019-12-06: variableDeclaratorList() eingefuegt, um als Token nicht die
|
||||||
|
// Modifier zu bekommen
|
||||||
|
fieldType = TypePlaceholder.fresh(fieldDeclContext.variableDeclarators().getStart());
|
||||||
|
}
|
||||||
|
for (Java17Parser.VariableDeclaratorContext varDecl : fieldDeclContext.variableDeclarators().variableDeclarator()) {
|
||||||
|
String fieldName = varDecl.variableDeclaratorId().getText();
|
||||||
|
this.fields.put(fieldName, new FieldEntry(fieldName, fieldType, modifiers));
|
||||||
|
if (varDecl.variableInitializer() != null) {
|
||||||
|
initializeField(varDecl, Modifier.isStatic(modifiers), fieldType, generics);
|
||||||
|
}
|
||||||
|
ret.add(new Field(fieldName, fieldType, modifiers, varDecl.getStart()));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String convert(Java17Parser.VariableDeclaratorIdContext variableDeclaratorIdContext) {
|
||||||
|
return variableDeclaratorIdContext.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize a field by creating implicit constructor.
|
||||||
|
private void initializeField(Java17Parser.VariableDeclaratorContext ctx, boolean isStatic, RefTypeOrTPHOrWildcardOrGeneric typeOfField, GenericsRegistry generics) {
|
||||||
|
StatementGenerator statementGenerator = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
|
||||||
|
var assignment = statementGenerator.generateFieldAssignment(ctx, typeOfField);
|
||||||
|
if (isStatic) {
|
||||||
|
staticFieldInitializations.add(assignment);
|
||||||
|
}
|
||||||
|
else fieldInitializations.add(assignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int convertModifier(String modifier) {
|
||||||
|
return allmodifiers.get(modifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GenericsRegistry createGenerics(Java17Parser.GenericDeclarationListContext ctx, JavaClassName parentClass, String parentMethod, JavaClassRegistry reg, GenericsRegistry generics) {
|
||||||
|
GenericsRegistry ret = new GenericsRegistry(this.globalGenerics);
|
||||||
|
ret.putAll(generics);
|
||||||
|
if (ctx == null)
|
||||||
|
return ret;
|
||||||
|
for (Java17Parser.GenericTypeVarContext tp : ctx.genericTypeVar()) {
|
||||||
|
ret.put(tp.identifier().getText(), new GenericContext(parentClass, parentMethod));
|
||||||
|
TypeGenerator.convert(tp, parentClass, parentMethod, reg, ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,206 @@
|
|||||||
|
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
|
import de.dhbwstuttgart.exceptions.TypeinferenceException;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.IdentifierContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.TypeArgumentsContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.TypeTypeContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.WildcardTypeContext;
|
||||||
|
import de.dhbwstuttgart.parser.scope.GenericsRegistry;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.GenericDeclarationList;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class TypeGenerator {
|
||||||
|
|
||||||
|
public static RefTypeOrTPHOrWildcardOrGeneric convert(Java17Parser.ClassOrInterfaceTypeContext classOrInterfaceTypeContext, JavaClassRegistry reg, GenericsRegistry generics) {
|
||||||
|
Java17Parser.TypeArgumentsContext arguments = null;
|
||||||
|
/*
|
||||||
|
* PL 2019-03-19 auskommentiert ANFANG if(unannClassOrInterfaceTypeContext. unannClassType_lfno_unannClassOrInterfaceType() != null){ arguments = unannClassOrInterfaceTypeContext. unannClassType_lfno_unannClassOrInterfaceType().typeArguments(); }else{// if(unannClassOrInterfaceTypeContext. unannInterfaceType_lfno_unannClassOrInterfaceType() != null){ arguments = unannClassOrInterfaceTypeContext. unannInterfaceType_lfno_unannClassOrInterfaceType().
|
||||||
|
* unannClassType_lfno_unannClassOrInterfaceType().typeArguments(); } PL 2019-03-19 auskommentiert ENDE
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Problem sind hier die verschachtelten Typen mit verschachtelten Typargumenten Beispiel: Typ<String>.InnererTyp<Integer>
|
||||||
|
*/
|
||||||
|
if (classOrInterfaceTypeContext.typeArguments().size() > 1)
|
||||||
|
throw new NotImplementedException();
|
||||||
|
|
||||||
|
String name = "";
|
||||||
|
for (IdentifierContext id : classOrInterfaceTypeContext.identifier()) {
|
||||||
|
name += id.getText() + '.';
|
||||||
|
}
|
||||||
|
name += classOrInterfaceTypeContext.typeIdentifier().getText();
|
||||||
|
if (classOrInterfaceTypeContext.getStop().getText().equals(">")) {
|
||||||
|
/*
|
||||||
|
* Fuer Debug-Zwecke unannClassOrInterfaceTypeContext. unannInterfaceType_lfno_unannClassOrInterfaceType(); unannClassOrInterfaceTypeContext. unannClassType_lfno_unannClassOrInterfaceType().getText(); //unannClassOrInterfaceTypeContext. unannInterfaceType_lfno_unannClassOrInterfaceType(). unannClassType_lfno_unannClassOrInterfaceType().typeArguments(); //UnannClassType_lfno_unannClassOrInterfaceTypeContext unannClassOrInterfaceTypeContext.unannClassType_lf_unannClassOrInterfaceType( 0);
|
||||||
|
* unannClassOrInterfaceTypeContext.unannClassType_lf_unannClassOrInterfaceType( 0).getText(); unannClassOrInterfaceTypeContext.unannClassType_lf_unannClassOrInterfaceType( 1); unannClassOrInterfaceTypeContext.unannClassType_lf_unannClassOrInterfaceType( 1).getText(); unannClassOrInterfaceTypeContext. unannClassType_lfno_unannClassOrInterfaceType().getText(); //unannClassOrInterfaceTypeContext. unannInterfaceType_lf_unannClassOrInterfaceType(); //unannClassOrInterfaceTypeContext.
|
||||||
|
* unannInterfaceType_lf_unannClassOrInterfaceType(0).getText(); //unannClassOrInterfaceTypeContext. unannInterfaceType_lf_unannClassOrInterfaceType(1).getText(); //unannClassOrInterfaceTypeContext. unannInterfaceType_lfno_unannClassOrInterfaceType().getText();
|
||||||
|
*/
|
||||||
|
List<TypeArgumentsContext> typeargs = classOrInterfaceTypeContext.typeArguments();
|
||||||
|
arguments = typeargs.size() != 0 ? classOrInterfaceTypeContext.typeArguments(0) : null;
|
||||||
|
}
|
||||||
|
return convertTypeName(name, arguments, classOrInterfaceTypeContext.getStart(), reg, generics);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RefTypeOrTPHOrWildcardOrGeneric convert(Java17Parser.TypeTypeContext typeContext, JavaClassRegistry reg, GenericsRegistry genericsRegistry) {
|
||||||
|
if (typeContext.primitiveType() != null) {
|
||||||
|
switch (typeContext.primitiveType().getText()) {
|
||||||
|
case "boolean":
|
||||||
|
return new RefType(ASTFactory.createClass(Boolean.class).getClassName(), typeContext.getStart());
|
||||||
|
case "int":
|
||||||
|
return new RefType(ASTFactory.createClass(Integer.class).getClassName(), typeContext.getStart());
|
||||||
|
case "double":
|
||||||
|
return new RefType(ASTFactory.createClass(Double.class).getClassName(), typeContext.getStart());
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
} else if (!typeContext.LBRACK().isEmpty()) { // ArrayType über eckige Klammer prüfen
|
||||||
|
// System.out.println(unannTypeContext.getText());
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* else if (typeContext.classOrInterfaceType() != null) { JavaClassName name = reg .getName(typeContext.classOrInterfaceType().typeIdentifier().getText()); return new RefType(name, typeContext.getStart()); }
|
||||||
|
*/
|
||||||
|
return TypeGenerator.convert(typeContext.classOrInterfaceType(), reg, genericsRegistry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GenericDeclarationList convert(Java17Parser.GenericDeclarationListContext typeParametersContext, JavaClassName parentClass, String parentMethod, JavaClassRegistry reg, GenericsRegistry generics) {
|
||||||
|
Token endOffset = typeParametersContext.getStop();
|
||||||
|
List<GenericTypeVar> typeVars = new ArrayList<>();
|
||||||
|
for (Java17Parser.GenericTypeVarContext typeParameter : typeParametersContext.genericTypeVar()) {
|
||||||
|
typeVars.add(convert(typeParameter, parentClass, parentMethod, reg, generics));
|
||||||
|
endOffset = typeParameter.getStop();
|
||||||
|
}
|
||||||
|
return new GenericDeclarationList(typeVars, endOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GenericTypeVar convert(Java17Parser.GenericTypeVarContext typeVar, JavaClassName parentClass, String parentMethod, JavaClassRegistry reg, GenericsRegistry generics) {
|
||||||
|
String name = typeVar.identifier().getText();
|
||||||
|
// TODO: Es müssen erst alle GenericTypeVars generiert werden, dann können die
|
||||||
|
// bounds dieser Generics ermittelt werden
|
||||||
|
// Problem <A extends B, B> ist erlaubt, würde aber bei den Bounds von A den
|
||||||
|
// Generic B nicht als solchen erkennen
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> bounds = TypeGenerator.convert(typeVar.typeBound(), reg, generics);
|
||||||
|
|
||||||
|
GenericTypeVar ret = new GenericTypeVar(name, bounds, typeVar.getStart(), typeVar.getStop());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<RefTypeOrTPHOrWildcardOrGeneric> convert(Java17Parser.TypeBoundContext typeBoundContext, JavaClassRegistry reg, GenericsRegistry generics) {
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> ret = new ArrayList<>();
|
||||||
|
if (Objects.isNull(typeBoundContext)) {
|
||||||
|
ret.add(ASTFactory.createObjectType());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (typeBoundContext.typeType().size() > 0) {
|
||||||
|
for (TypeTypeContext tt : typeBoundContext.typeType()) {
|
||||||
|
ret.add(convert(tt, reg, generics));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RefTypeOrTPHOrWildcardOrGeneric convert(Java17Parser.WildcardTypeContext wildcardContext, JavaClassRegistry reg, GenericsRegistry generics) {
|
||||||
|
if (wildcardContext.getChildCount() < 3) {
|
||||||
|
if (!Objects.isNull(wildcardContext.extendsWildcardType())) {
|
||||||
|
return new ExtendsWildcardType(convert(wildcardContext.extendsWildcardType().typeType(), reg, generics), wildcardContext.getStart());
|
||||||
|
} else {
|
||||||
|
return new SuperWildcardType(convert(wildcardContext.superWildcardType().typeType(), reg, generics), wildcardContext.getStart());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new NotImplementedException(); // Wildcard ohne Bound
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RefTypeOrTPHOrWildcardOrGeneric convertTypeName(String name, Token offset, JavaClassRegistry reg, GenericsRegistry generics) {
|
||||||
|
return convertTypeName(name, (Java17Parser.TypeArgumentsContext) null, offset, reg, generics);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RefTypeOrTPHOrWildcardOrGeneric convertTypeName(String name, Java17Parser.TypeArgumentsContext typeArguments, Token offset, JavaClassRegistry reg, GenericsRegistry generics) {
|
||||||
|
if (!reg.contains(name)) { // Dann könnte es ein generischer Type oder ein FunN$$-Type sein
|
||||||
|
if (generics.contains(name)) {
|
||||||
|
return new GenericRefType(name, offset);
|
||||||
|
} else {
|
||||||
|
Pattern p = Pattern.compile("Fun(\\d+)[$][$]");
|
||||||
|
Matcher m = p.matcher(name);
|
||||||
|
if (m.matches()) {// es ist FunN$$-Type
|
||||||
|
return new RefType(new JavaClassName(name), convert(typeArguments, reg, generics), offset);
|
||||||
|
} else {
|
||||||
|
throw new TypeinferenceException("Der Typ " + name + " ist nicht vorhanden", offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeArguments == null) {
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
|
||||||
|
for (int i = 0; i < reg.getNumberOfGenerics(name); i++) {
|
||||||
|
params.add(TypePlaceholder.fresh(offset));
|
||||||
|
}
|
||||||
|
return new RefType(reg.getName(name), params, offset);
|
||||||
|
} else {
|
||||||
|
return new RefType(reg.getName(name), convert(typeArguments, reg, generics), offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RefTypeOrTPHOrWildcardOrGeneric convertTypeName(String name, Java17Parser.NonWildcardTypeArgumentsContext typeArguments, Token offset, JavaClassRegistry reg, GenericsRegistry generics) {
|
||||||
|
if (!reg.contains(name)) { // Dann könnte es ein generischer Type oder ein FunN$$-Type sein
|
||||||
|
if (generics.contains(name)) {
|
||||||
|
return new GenericRefType(name, offset);
|
||||||
|
} else {
|
||||||
|
Pattern p = Pattern.compile("Fun(\\d+)[$][$]");
|
||||||
|
Matcher m = p.matcher(name);
|
||||||
|
if (m.matches()) {// es ist FunN$$-Type
|
||||||
|
return new RefType(new JavaClassName(name), convert(typeArguments, reg, generics), offset);
|
||||||
|
} else {
|
||||||
|
throw new TypeinferenceException("Der Typ " + name + " ist nicht vorhanden", offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeArguments == null) {
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
|
||||||
|
for (int i = 0; i < reg.getNumberOfGenerics(name); i++) {
|
||||||
|
params.add(TypePlaceholder.fresh(offset));
|
||||||
|
}
|
||||||
|
return new RefType(reg.getName(name), params, offset);
|
||||||
|
} else {
|
||||||
|
return new RefType(reg.getName(name), convert(typeArguments, reg, generics), offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<RefTypeOrTPHOrWildcardOrGeneric> convert(Java17Parser.TypeArgumentsContext typeArguments, JavaClassRegistry reg, GenericsRegistry generics) {
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> ret = new ArrayList<>();
|
||||||
|
for (Java17Parser.TypeArgumentContext arg : typeArguments.typeArgument()) {
|
||||||
|
WildcardTypeContext wc = arg.wildcardType();
|
||||||
|
if (!Objects.isNull(wc)) {
|
||||||
|
ret.add(convert(wc, reg, generics));
|
||||||
|
} else {
|
||||||
|
ret.add(convert(arg.typeType(), reg, generics));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<RefTypeOrTPHOrWildcardOrGeneric> convert(Java17Parser.NonWildcardTypeArgumentsContext typeArguments, JavaClassRegistry reg, GenericsRegistry generics) {
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> ret = new ArrayList<>();
|
||||||
|
for (Java17Parser.TypeTypeContext arg : typeArguments.typeList().typeType()) {
|
||||||
|
ret.add(convert(arg, reg, generics));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
5
javatx-src-backup/main/java/de/dhbwstuttgart/parser/TODO
Normal file
5
javatx-src-backup/main/java/de/dhbwstuttgart/parser/TODO
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
= Grammatik =
|
||||||
|
|
||||||
|
* Core-Problem: Typinferenz vs. Konstruktoren
|
||||||
|
* möglicherweise Problem: falsche Return-Expressions
|
||||||
|
|
@ -9,6 +9,8 @@ import org.antlr.v4.runtime.atn.*;
|
|||||||
import org.antlr.v4.runtime.dfa.DFA;
|
import org.antlr.v4.runtime.dfa.DFA;
|
||||||
import org.antlr.v4.runtime.misc.*;
|
import org.antlr.v4.runtime.misc.*;
|
||||||
|
|
||||||
|
import java.lang.Integer;
|
||||||
|
|
||||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue"})
|
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue"})
|
||||||
public class Java17Lexer extends Lexer {
|
public class Java17Lexer extends Lexer {
|
||||||
static { RuntimeMetaData.checkVersion("4.11.1", RuntimeMetaData.VERSION); }
|
static { RuntimeMetaData.checkVersion("4.11.1", RuntimeMetaData.VERSION); }
|
@ -0,0 +1,15 @@
|
|||||||
|
* Methode als statische Klasse
|
||||||
|
* Methode gibt eine JavaClassRegistry zurück (für mehr als 1 S0ourcefile).
|
||||||
|
* Suchmuster: \n rule
|
||||||
|
* Generell: lieber leere Listen und wenig null verwenden (Spezialfälle ausgenommen).
|
||||||
|
|
||||||
|
== Fehler/Exceptions ==
|
||||||
|
|
||||||
|
* Eigene wie z.B. TypeCheckExceptions
|
||||||
|
* Fehler sollen an Semantikchecker usw. weiter gegeben werden.
|
||||||
|
|
||||||
|
== Offset ==
|
||||||
|
|
||||||
|
* Evtl. Zeichen im File/in der Klasse durch Antlr ermitteln.
|
||||||
|
* z.B. ParserRuleContext.getStart()
|
||||||
|
* Anstatt offset: Instanz des entsprechenden ParserRuleContext (liefert evtl. noch mehr Infos)
|
@ -0,0 +1,3 @@
|
|||||||
|
* fieldDeclarations
|
||||||
|
* Imports
|
||||||
|
* (Q)Generics
|
@ -0,0 +1,2 @@
|
|||||||
|
* Ablegen der Type Parameter: kompletter Name?
|
||||||
|
* Typen (unannType etc.)
|
@ -0,0 +1,18 @@
|
|||||||
|
* Listener-Pattern für das Projekt eher ungeeignet.
|
||||||
|
|
||||||
|
= Herangehensweise/Format =
|
||||||
|
|
||||||
|
* CompilatunUnit (Rot) wird zu Source-File (Root)
|
||||||
|
* Im Paket Syntaxtree finden sich die Klassen, die ich letztendlich erzeugen muss.
|
||||||
|
* Kann hier auch Veränderungen vornehmen (Pull Request)
|
||||||
|
* Wichtig! Typnamen müssen aufgelöst werden können (also z.B. java.lang.util.ArrayList (JavaClassRegistry).
|
||||||
|
|
||||||
|
= Idee bei mehreren Files =
|
||||||
|
* Zunächst alle Files anschauen und Pakate/Klassen für die spätere Verwendung "registrieren".
|
||||||
|
* Danach erst das komplette Package/alle Klassen imselben Verzeichnis parsen.
|
||||||
|
|
||||||
|
== Fragen/PProbleme SyntaxTreeGenerator ==
|
||||||
|
|
||||||
|
* ClassRegistry: Unklar, woher diese kommen soll.
|
||||||
|
* Konstruktor für Class fehlt.
|
||||||
|
* Namenskonflikt Class vs. Class in Java?
|
@ -0,0 +1,166 @@
|
|||||||
|
package de.dhbwstuttgart.parser.scope;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
|
import de.dhbwstuttgart.environment.PackageCrawler;
|
||||||
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.AnnotationTypeElementDeclarationContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassBodyContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassBodyDeclarationContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassOrInterfaceContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassorinterfacedeclContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.EnumConstantContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.EnumConstantsContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.InterfaceBodyDeclarationContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.InterfacememberContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.MemberclassorinterfaceContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.MemberdeclContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.NoclassorinterfaceContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.SrcfileContext;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.SubclassorinterfaceContext;
|
||||||
|
|
||||||
|
public class GatherNames {
|
||||||
|
|
||||||
|
public static Map<String, Integer> getNames(SrcfileContext ctx, PackageCrawler packages, JavaTXCompiler compiler) throws ClassNotFoundException {
|
||||||
|
Map<String, Integer> ret = new HashMap<>();
|
||||||
|
for (Java17Parser.ClassOrInterfaceContext clsoifctx : ctx.classOrInterface()) {
|
||||||
|
if (clsoifctx instanceof NoclassorinterfaceContext) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ret.putAll(getNames(clsoifctx, getPackageName(ctx), packages, compiler));
|
||||||
|
}
|
||||||
|
ret.putAll(getImports(ctx, packages, compiler));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, Integer> getNames(ClassOrInterfaceContext clsoifctx, String pkgName, PackageCrawler packages, JavaTXCompiler compiler) throws ClassNotFoundException {
|
||||||
|
Map<String, Integer> ret = new HashMap<>();
|
||||||
|
ClassorinterfacedeclContext clsoif = (ClassorinterfacedeclContext) clsoifctx;
|
||||||
|
String nameString = "";
|
||||||
|
String fullname = clsoif.getChild(clsoif.getChildCount() - 1).getClass().getName();
|
||||||
|
String classname = fullname.substring(fullname.indexOf("$") + 1);
|
||||||
|
int numGenerics = 0;
|
||||||
|
/*
|
||||||
|
* Es werden alle Namen gesammelt, die syntaktisch von Java-TX (sprich der Grammatik) erkannt werden. Auch wenn z.B. Annotationen oder Enumerationen noch nicht im Compiler implementiert sind. Die "NotImplementedException" wird dann im "SyntaxTreeGenerator" geworfen. Das Statement soll als Vorbereitung dienen, für den Fall, dass weitere Sprachkonstrukte in den Compiler aufgenommen werden.
|
||||||
|
*/
|
||||||
|
switch (classname) {
|
||||||
|
case "ClassDeclarationContext":
|
||||||
|
if (!pkgName.isEmpty()) {
|
||||||
|
nameString = pkgName + "." + clsoif.classDeclaration().identifier().getText();
|
||||||
|
} else {
|
||||||
|
nameString = clsoif.classDeclaration().identifier().getText();
|
||||||
|
}
|
||||||
|
numGenerics = clsoif.classDeclaration().genericDeclarationList() != null ? clsoif.classDeclaration().genericDeclarationList().genericTypeVar().size() : 0;
|
||||||
|
ret.put(nameString, numGenerics);
|
||||||
|
ret.putAll(getNames(clsoif.classDeclaration().classBody().classBodyDeclaration(), pkgName, packages, compiler));
|
||||||
|
break;
|
||||||
|
case "EnumDeclarationContext":
|
||||||
|
if (!pkgName.isEmpty()) {
|
||||||
|
nameString = pkgName + "." + clsoif.enumDeclaration().identifier().getText();
|
||||||
|
} else {
|
||||||
|
nameString = clsoif.enumDeclaration().identifier().getText();
|
||||||
|
}
|
||||||
|
numGenerics = 0;
|
||||||
|
ret.put(nameString, numGenerics);
|
||||||
|
EnumConstantsContext enumConstants = clsoif.enumDeclaration().enumConstants();
|
||||||
|
if (!Objects.isNull(enumConstants)) {
|
||||||
|
for (EnumConstantContext enumConstant : enumConstants.enumConstant()) {
|
||||||
|
ClassBodyContext enumConstClassBody = enumConstant.classBody();
|
||||||
|
if (!Objects.isNull(enumConstClassBody)) {
|
||||||
|
ret.putAll(getNames(enumConstClassBody.classBodyDeclaration(), pkgName, packages, compiler));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "InterfaceDeclarationContext":
|
||||||
|
if (pkgName != "") {
|
||||||
|
nameString = pkgName + "." + clsoif.interfaceDeclaration().identifier().getText();
|
||||||
|
} else {
|
||||||
|
nameString = clsoif.interfaceDeclaration().identifier().getText();
|
||||||
|
}
|
||||||
|
numGenerics = clsoif.interfaceDeclaration().genericDeclarationList() != null ? clsoif.interfaceDeclaration().genericDeclarationList().genericTypeVar().size() : 0;
|
||||||
|
ret.put(nameString, numGenerics);
|
||||||
|
for (InterfaceBodyDeclarationContext ifbody : clsoif.interfaceDeclaration().interfaceBody().interfaceBodyDeclaration()) {
|
||||||
|
if (ifbody instanceof InterfacememberContext member && member.interfaceMemberDeclaration() instanceof SubclassorinterfaceContext sub) {
|
||||||
|
ret.putAll(getNames(sub.classOrInterface(), pkgName, packages, compiler));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "AnnotationTypeDeclarationContext":
|
||||||
|
if (pkgName != "") {
|
||||||
|
nameString = pkgName + "." + clsoif.annotationTypeDeclaration().identifier().getText();
|
||||||
|
} else {
|
||||||
|
nameString = clsoif.annotationTypeDeclaration().identifier().getText();
|
||||||
|
}
|
||||||
|
numGenerics = 0;
|
||||||
|
ret.put(nameString, numGenerics);
|
||||||
|
for (AnnotationTypeElementDeclarationContext anTypeElem : clsoif.annotationTypeDeclaration().annotationTypeBody().annotationTypeElementDeclaration()) {
|
||||||
|
ClassOrInterfaceContext anClsoifctx = anTypeElem.annotationTypeElementRest().classOrInterface();
|
||||||
|
if (!Objects.isNull(anClsoifctx)) {
|
||||||
|
ret.putAll(getNames(anClsoifctx, pkgName, packages, compiler));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "RecordDeclarationContext":
|
||||||
|
if (pkgName != "") {
|
||||||
|
nameString = pkgName + "." + clsoif.recordDeclaration().identifier().getText();
|
||||||
|
} else {
|
||||||
|
nameString = clsoif.recordDeclaration().identifier().getText();
|
||||||
|
}
|
||||||
|
numGenerics = clsoif.recordDeclaration().genericDeclarationList() != null ? clsoif.recordDeclaration().genericDeclarationList().genericTypeVar().size() : 0;
|
||||||
|
ret.put(nameString, numGenerics);
|
||||||
|
ret.putAll(getNames(clsoif.recordDeclaration().recordBody().classBodyDeclaration(), pkgName, packages, compiler));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, Integer> getNames(List<ClassBodyDeclarationContext> clsBodyDecl, String pkgName, PackageCrawler packages, JavaTXCompiler compiler) throws ClassNotFoundException {
|
||||||
|
Map<String, Integer> ret = new HashMap<>();
|
||||||
|
for (ClassBodyDeclarationContext clsbody : clsBodyDecl) {
|
||||||
|
if (clsbody instanceof MemberdeclContext member && member.memberDeclaration() instanceof MemberclassorinterfaceContext memberclsoifctx) {
|
||||||
|
ret.putAll(getNames(memberclsoifctx.classOrInterface(), pkgName, packages, compiler));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, Integer> getImports(Java17Parser.SrcfileContext ctx, PackageCrawler packages, JavaTXCompiler compiler) throws ClassNotFoundException {
|
||||||
|
Map<String, Integer> ret = new HashMap<>();
|
||||||
|
// ret.putAll(packages.getClassNames("java.lang"));
|
||||||
|
for (Java17Parser.ImportDeclarationContext importDeclCtx : ctx.importDeclaration()) {
|
||||||
|
if (importDeclCtx.MUL() == null) {
|
||||||
|
var name = importDeclCtx.qualifiedName().getText();
|
||||||
|
var className = new JavaClassName(name);
|
||||||
|
if (compiler.loadJavaTXClass(className)) {
|
||||||
|
ret.put(name, compiler.classRegistry.getNumberOfGenerics(name));
|
||||||
|
} else {
|
||||||
|
Class<?> cl = compiler.getClassLoader().loadClass(name);
|
||||||
|
ret.put(cl.getName(), cl.getTypeParameters().length);
|
||||||
|
}
|
||||||
|
} else if (importDeclCtx.MUL() != null) {
|
||||||
|
// TODO Find stuff in user defined packages
|
||||||
|
ret.putAll(packages.getClassNames(importDeclCtx.qualifiedName().getText()));
|
||||||
|
}
|
||||||
|
// Die Unterscheidungen für 'static imports' wurden herausgenommen, da sie den
|
||||||
|
// auszuführenden Code nicht beeinflussen
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getPackageName(Java17Parser.SrcfileContext ctx) {
|
||||||
|
String pkgName = "";
|
||||||
|
if (ctx.packageDeclaration() != null) {
|
||||||
|
pkgName = ctx.packageDeclaration().qualifiedName().getText();
|
||||||
|
}
|
||||||
|
return pkgName;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package de.dhbwstuttgart.parser.scope;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.GenericContext;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class GenericsRegistry {
|
||||||
|
private final List<GenericVariable> registry = new ArrayList<>();
|
||||||
|
public final GenericsRegistry globalRegistry;
|
||||||
|
|
||||||
|
public GenericsRegistry(GenericsRegistry globalRegistry){
|
||||||
|
this.globalRegistry = globalRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(String name, GenericContext genericContext){
|
||||||
|
registry.add(new GenericVariable(genericContext,name));
|
||||||
|
if(globalRegistry != null)globalRegistry.put(name, genericContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(String name) {
|
||||||
|
Optional<Boolean> ret = registry.stream().<Boolean>map(((GenericVariable genericVariable) -> genericVariable.name.equals(name)))
|
||||||
|
.reduce(((a, b) -> a || b));
|
||||||
|
if(ret.isPresent())
|
||||||
|
return ret.get();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GenericContext get(String name) {
|
||||||
|
return registry.stream()
|
||||||
|
.filter((genericVariable -> genericVariable.name.equals(name))).findAny().get().context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putAll(GenericsRegistry generics) {
|
||||||
|
for(GenericVariable generic : generics.registry){
|
||||||
|
this.put(generic.name, generic.context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GenericVariable{
|
||||||
|
final GenericContext context;
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
GenericVariable(GenericContext context, String name){
|
||||||
|
this.context = context;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,159 @@
|
|||||||
|
package de.dhbwstuttgart.parser.scope;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stellt den Namen einer Java Klasse dar.
|
||||||
|
* Dieser kann auch den Packagenamen mit beinhalten:
|
||||||
|
* de.dhbwstuttgart.typeinference.Menge
|
||||||
|
*
|
||||||
|
* @author Andreas Stadelmeier
|
||||||
|
*/
|
||||||
|
public class JavaClassName {
|
||||||
|
|
||||||
|
// FIXME It's very much possible to have imports to inner classes
|
||||||
|
// In that case a.package.Foo.Bar, a.package is the Package and Foo.Bar the class name
|
||||||
|
// Its impossible to decide what's the package based solely on the name of the class
|
||||||
|
|
||||||
|
public static final JavaClassName Void = new JavaClassName("void");
|
||||||
|
private String name;
|
||||||
|
private PackageName packageName;
|
||||||
|
|
||||||
|
public JavaClassName(String name) {
|
||||||
|
if (name == null)
|
||||||
|
throw new NullPointerException();
|
||||||
|
|
||||||
|
String[] names = name.split("[.]");
|
||||||
|
boolean match = true;
|
||||||
|
if (names.length == 1) {
|
||||||
|
// packageName = new PackageName();
|
||||||
|
this.name = name;
|
||||||
|
} else {
|
||||||
|
name = names[names.length - 1];
|
||||||
|
List<String> packageNames = new ArrayList<String>();
|
||||||
|
for (int i = 0; i < names.length - 1; i++) {
|
||||||
|
packageNames.add(names[i]);
|
||||||
|
}
|
||||||
|
packageName = new PackageName(packageNames);
|
||||||
|
this.name = names[names.length - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gibt von einem Klassennamen nur den Namen der Klasse zur<EFBFBD>ck
|
||||||
|
* Beispiel:
|
||||||
|
* java.lang.Object wird zu: Object
|
||||||
|
*/
|
||||||
|
public static String stripClassName(String className) {
|
||||||
|
return new JavaClassName(className).name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
|
/*
|
||||||
|
* result = prime * result
|
||||||
|
* + ((packageName == null) ? 0 : packageName.hashCode()); //PackageName does
|
||||||
|
* not infect hashCode
|
||||||
|
*/
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Namen sind nur gleich, wenn bei den beiden zu vergleichenden JavaClassNames
|
||||||
|
* auch das Package angegeben ist
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (obj instanceof String)
|
||||||
|
return this.toString().equals(obj) || (this.name != null && this.name.equals(obj)); // Auch mit Strings als
|
||||||
|
// Klassennamen kompatibel
|
||||||
|
// TODO: sollte bald obsolet
|
||||||
|
// sein
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
JavaClassName other = (JavaClassName) obj;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
if (packageName != null && other.packageName != null) {
|
||||||
|
if (!packageName.equals(other.packageName))
|
||||||
|
return false;// Spezialfall, nicht beide Typen müssen eindeutig mit Packagenamen angegeben
|
||||||
|
// werden
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return (packageName != null ? packageName.toString() + "." : "") + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPackageName() {
|
||||||
|
return (packageName != null ? packageName.toString() : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClassName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PackageName {
|
||||||
|
|
||||||
|
List<String> names = new ArrayList<>();
|
||||||
|
|
||||||
|
public PackageName(List<String> packageNames) {
|
||||||
|
names = packageNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PackageName() {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((names == null) ? 0 : names.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
PackageName other = (PackageName) obj;
|
||||||
|
if (names == null) {
|
||||||
|
if (other.names != null)
|
||||||
|
return false;
|
||||||
|
} else if (!names.equals(other.names))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String ret = "";
|
||||||
|
if (names == null)
|
||||||
|
return "";
|
||||||
|
for (String n : names)
|
||||||
|
ret += n + ".";
|
||||||
|
if (ret != null && ret.length() > 0 && ret.charAt(ret.length() - 1) == '.') {
|
||||||
|
ret = ret.substring(0, ret.length() - 1);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package de.dhbwstuttgart.parser.scope;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speichert die Klassen f<EFBFBD>r einen bestimmten Projektscope
|
||||||
|
*/
|
||||||
|
public class JavaClassRegistry {
|
||||||
|
final Map<JavaClassName, Integer> existingClasses = new HashMap<>();
|
||||||
|
|
||||||
|
public JavaClassRegistry(Map<String, Integer> initialNames) {
|
||||||
|
addNames(initialNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaClassRegistry() {}
|
||||||
|
|
||||||
|
public void addNames(Map<String, Integer> names) {
|
||||||
|
for (String name : names.keySet()) {
|
||||||
|
existingClasses.put(new JavaClassName(name), names.get(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addName(String className, int numberOfGenerics) {
|
||||||
|
existingClasses.put(new JavaClassName(className), numberOfGenerics);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaClassName getName(String className) {
|
||||||
|
for (JavaClassName name : existingClasses.keySet()) {
|
||||||
|
if (name.equals(new JavaClassName(className)))
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return existingClasses.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<JavaClassName> getAllFromPackage(String packageName) {
|
||||||
|
List<JavaClassName> ret = new ArrayList<>();
|
||||||
|
for (JavaClassName className : this.existingClasses.keySet()) {
|
||||||
|
JavaClassName toCompare = new JavaClassName(
|
||||||
|
packageName + "." + JavaClassName.stripClassName(className.toString()));
|
||||||
|
if (toCompare.toString().equals(className.toString())) {
|
||||||
|
ret.add(className);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(String whole) {
|
||||||
|
return existingClasses.containsKey(new JavaClassName(whole));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberOfGenerics(String name) {
|
||||||
|
return existingClasses.get(new JavaClassName(name));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||||
|
|
||||||
|
public interface ASTVisitor extends StatementVisitor{
|
||||||
|
|
||||||
|
void visit(SourceFile sourceFile);
|
||||||
|
|
||||||
|
void visit(GenericTypeVar genericTypeVar);
|
||||||
|
|
||||||
|
void visit(FormalParameter formalParameter);
|
||||||
|
|
||||||
|
void visit(GenericDeclarationList genericTypeVars);
|
||||||
|
|
||||||
|
void visit(Field field);
|
||||||
|
|
||||||
|
void visit(Method field);
|
||||||
|
|
||||||
|
void visit(Constructor field);
|
||||||
|
|
||||||
|
void visit(ParameterList formalParameters);
|
||||||
|
|
||||||
|
void visit(ClassOrInterface classOrInterface);
|
||||||
|
|
||||||
|
void visit(RefType refType);
|
||||||
|
|
||||||
|
void visit(SuperWildcardType superWildcardType);
|
||||||
|
|
||||||
|
void visit(TypePlaceholder typePlaceholder);
|
||||||
|
|
||||||
|
void visit(ExtendsWildcardType extendsWildcardType);
|
||||||
|
|
||||||
|
void visit(GenericRefType genericRefType);
|
||||||
|
|
||||||
|
void visit(ExpressionPattern aPattern);
|
||||||
|
|
||||||
|
void visit(RecordPattern aRecordPattern);
|
||||||
|
|
||||||
|
void visit(GuardedPattern aGuardedPattern);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,320 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public abstract class AbstractASTWalker implements ASTVisitor {
|
||||||
|
@Override
|
||||||
|
public void visit(Constructor cons) {
|
||||||
|
visitMethod(cons);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SourceFile sourceFile) {
|
||||||
|
for (ClassOrInterface cl : sourceFile.getClasses()) {
|
||||||
|
cl.accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ArgumentList argumentList) {
|
||||||
|
for (Expression expr : argumentList.getArguments()) {
|
||||||
|
expr.accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(GenericTypeVar genericTypeVar) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(FormalParameter formalParameter) {
|
||||||
|
formalParameter.getType().accept((ASTVisitor) this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(GenericDeclarationList genericTypeVars) {
|
||||||
|
Iterator<GenericTypeVar> genericIterator = genericTypeVars.iterator();
|
||||||
|
if (genericIterator.hasNext()) {
|
||||||
|
while (genericIterator.hasNext()) {
|
||||||
|
genericIterator.next().accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Field field) {
|
||||||
|
field.getType().accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Method method) {
|
||||||
|
visitMethod(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitMethod(Method method) {
|
||||||
|
method.getReturnType().accept(this);
|
||||||
|
method.getParameterList().accept(this);
|
||||||
|
if (method.block != null)
|
||||||
|
method.block.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ParameterList formalParameters) {
|
||||||
|
Iterator<Pattern> it = formalParameters.getFormalparalist().iterator();
|
||||||
|
if (it.hasNext()) {
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next().accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ClassOrInterface classOrInterface) {
|
||||||
|
classOrInterface.getGenerics().accept(this);
|
||||||
|
for (Field f : classOrInterface.getFieldDecl()) {
|
||||||
|
f.accept(this);
|
||||||
|
}
|
||||||
|
for (Constructor c : classOrInterface.getConstructors()) {
|
||||||
|
c.accept(this);
|
||||||
|
}
|
||||||
|
for (Method m : classOrInterface.getMethods()) {
|
||||||
|
m.accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(RefType refType) {
|
||||||
|
Iterator<RefTypeOrTPHOrWildcardOrGeneric> genericIterator = refType.getParaList().iterator();
|
||||||
|
if (genericIterator.hasNext()) {
|
||||||
|
while (genericIterator.hasNext()) {
|
||||||
|
genericIterator.next().accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SuperWildcardType superWildcardType) {
|
||||||
|
superWildcardType.getInnerType().accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(TypePlaceholder typePlaceholder) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ExtendsWildcardType extendsWildcardType) {
|
||||||
|
extendsWildcardType.getInnerType().accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(GenericRefType genericRefType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LambdaExpression lambdaExpression) {
|
||||||
|
lambdaExpression.params.accept(this);
|
||||||
|
lambdaExpression.methodBody.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Assign assign) {
|
||||||
|
assign.lefSide.accept(this);
|
||||||
|
assign.rightSide.accept(this);
|
||||||
|
assign.rightSide.getType().accept((ASTVisitor) this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryExpr binary) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BoolExpression logical) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Block block) {
|
||||||
|
for (Statement stmt : block.getStatements()) {
|
||||||
|
stmt.accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CastExpr castExpr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(EmptyStmt emptyStmt) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(FieldVar fieldVar) {
|
||||||
|
fieldVar.receiver.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ForStmt forStmt) {
|
||||||
|
forStmt.block.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IfStmt ifStmt) {
|
||||||
|
ifStmt.then_block.accept(this);
|
||||||
|
if (!Objects.isNull(ifStmt.else_block))
|
||||||
|
ifStmt.else_block.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InstanceOf instanceOf) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LocalVar localVar) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LocalVarDecl localVarDecl) {
|
||||||
|
localVarDecl.getType().accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(MethodCall methodCall) {
|
||||||
|
methodCall.receiver.accept(this);
|
||||||
|
methodCall.getArgumentList().accept(this);
|
||||||
|
methodCall.getArgumentList().getArguments().forEach(a -> a.getType().accept((ASTVisitor) this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewClass methodCall) {
|
||||||
|
visit((MethodCall) methodCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewArray newArray) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ExpressionReceiver receiver) {
|
||||||
|
receiver.expr.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(UnaryExpr unaryExpr) {
|
||||||
|
unaryExpr.expr.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Return aReturn) {
|
||||||
|
aReturn.retexpr.accept(this);
|
||||||
|
aReturn.getType().accept((ASTVisitor) this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ReturnVoid aReturn) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Break aBreak) {
|
||||||
|
aBreak.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(StaticClassName staticClassName) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Super aSuper) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(This aThis) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WhileStmt whileStmt) {
|
||||||
|
whileStmt.loopBlock.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(DoStmt whileStmt) {
|
||||||
|
whileStmt.loopBlock.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Literal literal) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignToField assignLeftSide) {
|
||||||
|
assignLeftSide.field.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignToLocal assignLeftSide) {
|
||||||
|
assignLeftSide.localVar.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SuperCall superCall) {
|
||||||
|
this.visit((MethodCall) superCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Switch switchStmt) {
|
||||||
|
switchStmt.getSwitch().accept(this);
|
||||||
|
switchStmt.getBlocks().stream().forEach((switchBlock) -> {
|
||||||
|
switchBlock.accept(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SwitchBlock switchBlock) {
|
||||||
|
switchBlock.getLabels().stream().forEach((label) -> {
|
||||||
|
label.accept(this);
|
||||||
|
});
|
||||||
|
switchBlock.getStatements().stream().forEach((stmt) -> {
|
||||||
|
stmt.accept(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SwitchLabel switchLabel) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Yield aYield) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ExpressionPattern aPattern) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(RecordPattern aRecordPattern) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(GuardedPattern aGuardedPattern) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,184 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces
|
||||||
|
*/
|
||||||
|
public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
||||||
|
private Boolean methodAdded = false; // wird benoetigt bei in JavaTXCompiler.getConstraints()
|
||||||
|
protected int modifiers;
|
||||||
|
protected JavaClassName name;
|
||||||
|
private List<Field> fields = new ArrayList<>();
|
||||||
|
private Optional<Constructor> fieldInitializations; // PL 2018-11-24: Noetig, um Bytecode fuer initializators nur einmal zu erzeugen
|
||||||
|
private Optional<Method> staticInitializer;
|
||||||
|
private List<Method> methods = new ArrayList<>();
|
||||||
|
private GenericDeclarationList genericClassParameters;
|
||||||
|
private RefType superClass;
|
||||||
|
protected boolean isInterface;
|
||||||
|
protected boolean isFunctionalInterface;
|
||||||
|
private List<RefType> implementedInterfaces;
|
||||||
|
private List<RefType> permittedSubtypes;
|
||||||
|
private List<Constructor> constructors;
|
||||||
|
|
||||||
|
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, Boolean isFunctionalInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset) {
|
||||||
|
super(offset);
|
||||||
|
if (isInterface) {
|
||||||
|
modifiers |= Modifier.INTERFACE | Modifier.ABSTRACT;
|
||||||
|
}
|
||||||
|
this.modifiers = modifiers;
|
||||||
|
this.name = name;
|
||||||
|
this.fields = fielddecl;
|
||||||
|
this.fieldInitializations = fieldInitializations;
|
||||||
|
this.staticInitializer = staticInitializer;
|
||||||
|
this.genericClassParameters = genericClassParameters;
|
||||||
|
this.superClass = superClass;
|
||||||
|
this.isInterface = isInterface;
|
||||||
|
this.isFunctionalInterface= isFunctionalInterface;
|
||||||
|
this.implementedInterfaces = implementedInterfaces;
|
||||||
|
this.permittedSubtypes = permittedSubtypes;
|
||||||
|
this.methods = methods;
|
||||||
|
this.constructors = constructors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* erzeugt fuer Fields, Konstruktoren und Methoden neue ArrayList-Objekte alle anderen Datenobjekte werden nur kopiert.
|
||||||
|
*/
|
||||||
|
public ClassOrInterface(ClassOrInterface cl) {
|
||||||
|
super(cl.getOffset());
|
||||||
|
this.modifiers = cl.modifiers;
|
||||||
|
this.name = cl.name;
|
||||||
|
this.fields = new ArrayList<>(cl.fields);
|
||||||
|
this.fieldInitializations = cl.fieldInitializations;
|
||||||
|
this.staticInitializer = cl.staticInitializer;
|
||||||
|
this.genericClassParameters = cl.genericClassParameters;
|
||||||
|
this.superClass = cl.superClass;
|
||||||
|
this.isInterface = cl.isInterface;
|
||||||
|
this.isFunctionalInterface= cl.isFunctionalInterface;
|
||||||
|
this.implementedInterfaces = cl.implementedInterfaces;
|
||||||
|
this.methods = new ArrayList<>(cl.methods);
|
||||||
|
this.constructors = new ArrayList<>(cl.constructors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Field> getField(String name) {
|
||||||
|
// TODO This should be a map
|
||||||
|
return fields.stream().filter(field -> field.getName().equals(name)).findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Method> getStaticInitializer() {
|
||||||
|
return staticInitializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInterface() {
|
||||||
|
return (Modifier.INTERFACE & this.getModifiers()) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFunctionalInterface() {
|
||||||
|
return this.isFunctionalInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets if it is added
|
||||||
|
public Boolean areMethodsAdded() {
|
||||||
|
return methodAdded;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets that it is added
|
||||||
|
public void setMethodsAdded() {
|
||||||
|
methodAdded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets class name
|
||||||
|
public JavaClassName getClassName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get modifiers
|
||||||
|
public int getModifiers() {
|
||||||
|
return this.modifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Field> getFieldDecl() {
|
||||||
|
return this.fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Constructor> getfieldInitializations() {
|
||||||
|
return this.fieldInitializations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Method> getMethods() {
|
||||||
|
return this.methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* public RefType getType() { return generateTypeOfClass(this.getClassName(), this.getGenerics(), this.getOffset()); }
|
||||||
|
*/
|
||||||
|
// TODO: Das hier ist ein Problem. Je nach Kontext wird hier ein anderer Typ benötigt
|
||||||
|
public static RefType generateTypeOfClass(JavaClassName name, GenericDeclarationList genericsOfClass, Token offset) {
|
||||||
|
// Hier wird immer ein generischer Typ generiert, also mit Type placeholdern
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
|
||||||
|
for (GenericTypeVar genericTypeVar : genericsOfClass) {
|
||||||
|
// params.add(genericTypeVar.getTypePlaceholder());
|
||||||
|
params.add(TypePlaceholder.fresh(offset));
|
||||||
|
}
|
||||||
|
return new RefType(name, params, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return die aktuelle Klasse als RefType
|
||||||
|
*/
|
||||||
|
public RefType generateTypeOfThisClass() {
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
|
||||||
|
for (GenericTypeVar genericTypeVar : this.getGenerics()) {
|
||||||
|
// params.add(genericTypeVar.getTypePlaceholder());
|
||||||
|
params.add(new GenericRefType(genericTypeVar.getName(), new NullToken()));
|
||||||
|
}
|
||||||
|
return new RefType(name, params, new NullToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Superklasse im Kontext dieser ClassOrInterface Das bedeutet, dass generische Variablen als GenericRefTypes dargestellt sind
|
||||||
|
*/
|
||||||
|
public RefType getSuperClass() {
|
||||||
|
return superClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GenericDeclarationList getGenerics() {
|
||||||
|
return this.genericClassParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Constructor> getConstructors() {
|
||||||
|
return constructors;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(ASTVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<RefType> getSuperInterfaces() {
|
||||||
|
return implementedInterfaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return this.name.toString() + this.genericClassParameters.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Statement;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.SuperCall;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Block;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Constructor extends Method {
|
||||||
|
|
||||||
|
// TODO: Constructor braucht ein super-Statement
|
||||||
|
public Constructor(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block codeInsideConstructor, GenericDeclarationList gtvDeclarations, Token offset /* , List<Statement> fieldInitializations geloescht PL 2018-11-24 */) {
|
||||||
|
super(modifier, name, returnType, parameterList, /* codeInsideConstructor, */ prepareBlock(codeInsideConstructor) /* ,fieldInitializations )geloescht PL 2018-11-24 ) */, gtvDeclarations, offset);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param fieldInitializations - Das sind die Statements, welche die Felder der zugehörigen Klasse dieses Konstruktor initialisieren
|
||||||
|
*/
|
||||||
|
protected static Block prepareBlock(Block constructorBlock /* , List<Statement> fieldInitializations new ArrayList<>() geloescht PL 2018-11-24 */) {
|
||||||
|
List<Statement> statements = constructorBlock.getStatements();
|
||||||
|
statements.add(0, new SuperCall(null, null, constructorBlock.getOffset()));
|
||||||
|
/* statements.addAll(fieldInitializations); geloescht PL 2018-11-24 */
|
||||||
|
return new Block(statements, constructorBlock.getOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(ASTVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ExceptionList
|
||||||
|
{
|
||||||
|
private List<RefTypeOrTPHOrWildcardOrGeneric> exceptions;
|
||||||
|
|
||||||
|
public ExceptionList(List<RefTypeOrTPHOrWildcardOrGeneric> exceptions){
|
||||||
|
this.exceptions = exceptions;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Expression;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public class ExpressionPattern extends Pattern {
|
||||||
|
private final Expression expression;
|
||||||
|
|
||||||
|
public ExpressionPattern(Expression expression, Token offset) {
|
||||||
|
super(expression.getType(), offset);
|
||||||
|
this.expression = expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression getExpression() {
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(ASTVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExpressionPattern withType(RefTypeOrTPHOrWildcardOrGeneric type) {
|
||||||
|
return new ExpressionPattern(expression, getOffset());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class Field extends SyntaxTreeNode implements TypeScope {
|
||||||
|
|
||||||
|
public final int modifier;
|
||||||
|
private String name;
|
||||||
|
private RefTypeOrTPHOrWildcardOrGeneric type;
|
||||||
|
|
||||||
|
public Field(String name, RefTypeOrTPHOrWildcardOrGeneric type, int modifier, Token offset) {
|
||||||
|
super(offset);
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
this.modifier = modifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(ASTVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends GenericTypeVar> getGenerics() {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Expression;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eine Feldinitialisation steht für eine Felddeklaration mit gleichzeitiger Wertzuweisung
|
||||||
|
* Beispiel: 'public Feld FeldVar = FeldWert;'
|
||||||
|
* @author janulrich
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class FieldDeclaration extends Field{
|
||||||
|
|
||||||
|
private Expression wert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dieser Konstruktor der FieldDeclaration erstellt den Syntaxknoten vollständig.
|
||||||
|
* Kein nachträgliches hinzfügen von Informationen oder aufrufen von parserPostProcessing ist notwendig.
|
||||||
|
*/
|
||||||
|
public FieldDeclaration(String name, RefTypeOrTPHOrWildcardOrGeneric typ, int modifier, Expression value, Token offset){
|
||||||
|
super(name, typ, modifier, offset);//Dieser Deklarator wird nicht vom Parser aufgerufen. Dadurch gibt es auch keinen Offset
|
||||||
|
this.wert = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public class FormalParameter extends Pattern {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public FormalParameter(String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||||
|
super(type, offset);
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(ASTVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FormalParameter withType(RefTypeOrTPHOrWildcardOrGeneric type) {
|
||||||
|
return new FormalParameter(name, type, getOffset());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stellt eine Deklarations-Liste von Generischen Variablen dar.
|
||||||
|
* Kann vor Methoden und Klassen auftauchen. (<....>)
|
||||||
|
* @author janulrich
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class GenericDeclarationList extends SyntaxTreeNode implements Iterable<GenericTypeVar>{
|
||||||
|
|
||||||
|
private Token offsetOfLastElement;
|
||||||
|
private List<GenericTypeVar> gtvs = new ArrayList<>();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public GenericDeclarationList(Iterable<? extends GenericTypeVar> values, Token endOffset) {
|
||||||
|
super(endOffset);
|
||||||
|
gtvs = isListOfGenericTypeVar(values) ? (List<GenericTypeVar>)values : Lists.newArrayList(values);
|
||||||
|
this.offsetOfLastElement = endOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GenericDeclarationList(ArrayList<GenericTypeVar> values, Token endOffset) {
|
||||||
|
super(endOffset);
|
||||||
|
gtvs = values;
|
||||||
|
this.offsetOfLastElement = endOffset; }
|
||||||
|
|
||||||
|
private boolean isListOfGenericTypeVar(Iterable<? extends GenericTypeVar> values) {
|
||||||
|
return values instanceof List && ((List<?>)values).size() > 0 && ((List<?>)values).get(0) instanceof GenericTypeVar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<GenericTypeVar> iterator() {
|
||||||
|
return gtvs.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(ASTVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return this.gtvs.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
GenericDeclarationList that = (GenericDeclarationList) o;
|
||||||
|
return gtvs.equals(that.gtvs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(gtvs);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entspricht einem GenericTypeVar, jedoch mit Bounds
|
||||||
|
* (d.h. vorgaben, von welchem Typ die Typevar sein darf
|
||||||
|
* => extends Class x
|
||||||
|
* => implements Interface y
|
||||||
|
* ...
|
||||||
|
* @author hoti 4.5.06
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class GenericTypeVar extends SyntaxTreeNode
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hier sind die Bounds in Form von Type-Objekten abgespeichert
|
||||||
|
*/
|
||||||
|
List<? extends RefTypeOrTPHOrWildcardOrGeneric> bounds=new ArrayList<RefTypeOrTPHOrWildcardOrGeneric>();
|
||||||
|
private Token endOffset;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public GenericTypeVar(String s, List<? extends RefTypeOrTPHOrWildcardOrGeneric> bounds, Token offset, Token endOffset)
|
||||||
|
{
|
||||||
|
super(offset);
|
||||||
|
name = s;
|
||||||
|
if(bounds != null)for(RefTypeOrTPHOrWildcardOrGeneric t : bounds){
|
||||||
|
//if(t!=null)this.extendVars.add(t);
|
||||||
|
}
|
||||||
|
//this.genericTypeVar = new RefType(s,offset);
|
||||||
|
this.bounds = bounds;
|
||||||
|
this.endOffset = endOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<? extends RefTypeOrTPHOrWildcardOrGeneric> getBounds()
|
||||||
|
{
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "BoGTV " + this.name + " " + this.bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName(){
|
||||||
|
return name.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
public JavaClassName definingClass(){
|
||||||
|
return name.getParentClass();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void accept(ASTVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
GenericTypeVar that = (GenericTypeVar) o;
|
||||||
|
return bounds.equals(that.bounds) && name.equals(that.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(bounds, name);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Expression;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public class GuardedPattern extends Pattern {
|
||||||
|
|
||||||
|
private final Expression condition;
|
||||||
|
private final Pattern nested;
|
||||||
|
|
||||||
|
public GuardedPattern(Expression condition, Pattern nested, Token offset) {
|
||||||
|
super(nested.getType(), offset);
|
||||||
|
this.condition = condition;
|
||||||
|
this.nested = nested;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression getCondition() {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pattern getNestedPattern() {
|
||||||
|
return nested;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(ASTVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GuardedPattern withType(RefTypeOrTPHOrWildcardOrGeneric type) {
|
||||||
|
return new GuardedPattern(condition, nested, getOffset());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
|
||||||
|
import de.dhbwstuttgart.typeinference.typeAlgo.TYPE;
|
||||||
|
import de.dhbwstuttgart.typeinference.typeAlgo.TYPEStmt;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.core.IItemWithOffset;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stellt eine Methode dar. Problem: Parser kann nicht zwischen Methode und
|
||||||
|
* Konstruktor unterscheiden. Daher kann diese Klasse beides sein. Dies wird mit
|
||||||
|
* dem ParserPostProcessing behoben.
|
||||||
|
*
|
||||||
|
* @author janulrich
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope
|
||||||
|
{
|
||||||
|
public final Block block;
|
||||||
|
public final int modifier;
|
||||||
|
public final String name;
|
||||||
|
private ParameterList parameterlist = new ParameterList(new ArrayList<>(), new NullToken());
|
||||||
|
private ExceptionList exceptionlist;
|
||||||
|
private GenericDeclarationList generics;
|
||||||
|
private final RefTypeOrTPHOrWildcardOrGeneric returnType;
|
||||||
|
public final Boolean isInherited;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* its Constraints
|
||||||
|
* eingefuegt PL 2021-02-15
|
||||||
|
*/
|
||||||
|
public final ConstraintSet constraints = new ConstraintSet();
|
||||||
|
|
||||||
|
public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block block,
|
||||||
|
GenericDeclarationList gtvDeclarations, Token offset) {
|
||||||
|
super(offset);
|
||||||
|
this.name = name;
|
||||||
|
this.modifier = modifier;
|
||||||
|
this.returnType = returnType;
|
||||||
|
this.parameterlist = parameterList;
|
||||||
|
this.block = block;
|
||||||
|
this.generics = gtvDeclarations;
|
||||||
|
this.isInherited = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block block,
|
||||||
|
GenericDeclarationList gtvDeclarations, Token offset, Boolean isInherited) {
|
||||||
|
super(offset);
|
||||||
|
this.name = name;
|
||||||
|
this.modifier = modifier;
|
||||||
|
this.returnType = returnType;
|
||||||
|
this.parameterlist = parameterList;
|
||||||
|
this.block = block;
|
||||||
|
this.generics = gtvDeclarations;
|
||||||
|
this.isInherited = isInherited;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParameterList getParameterList() {
|
||||||
|
return parameterlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GenericDeclarationList getGenerics() {
|
||||||
|
return generics;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
|
||||||
|
return this.returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstraintSet getConstraints() {
|
||||||
|
return this.constraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(ASTVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Token getOffset() {
|
||||||
|
return super.getOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ParameterList extends SyntaxTreeNode implements Iterable<Pattern> {
|
||||||
|
private List<Pattern> formalparameter;
|
||||||
|
|
||||||
|
public ParameterList(List<Pattern> params, Token offset) {
|
||||||
|
super(offset);
|
||||||
|
this.formalparameter = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pattern getParameterAt(int i) {
|
||||||
|
if (i >= formalparameter.size())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return formalparameter.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Pattern> getFormalparalist() {
|
||||||
|
return formalparameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Pattern> iterator() {
|
||||||
|
return formalparameter.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(ASTVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public abstract class Pattern extends SyntaxTreeNode {
|
||||||
|
private final RefTypeOrTPHOrWildcardOrGeneric type;
|
||||||
|
|
||||||
|
public Pattern(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||||
|
super(offset);
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric getType(){
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Pattern withType(RefTypeOrTPHOrWildcardOrGeneric type);
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||||
|
|
||||||
|
import javax.swing.text.html.Option;
|
||||||
|
|
||||||
|
public class Record extends ClassOrInterface {
|
||||||
|
|
||||||
|
public Record(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, Token offset) {
|
||||||
|
super(modifiers, name, fielddecl, fieldInitializations, staticInitializer, methods, constructors, genericClassParameters, superClass, isInterface, methods.size() == 1 ? true : false, implementedInterfaces, new ArrayList<>(), offset);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
|
||||||
|
public class RecordPattern extends FormalParameter {
|
||||||
|
|
||||||
|
private final List<Pattern> subPattern;
|
||||||
|
|
||||||
|
public RecordPattern(String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||||
|
super(name, type, offset);
|
||||||
|
subPattern = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecordPattern(List<Pattern> subPattern, String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||||
|
super(name, type, offset);
|
||||||
|
this.subPattern = subPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Pattern> getSubPattern() {
|
||||||
|
return this.subPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(ASTVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
|
||||||
|
//import sun.security.x509.X509CertInfo;
|
||||||
|
|
||||||
|
public class SourceFile extends SyntaxTreeNode {
|
||||||
|
private String pkgName;
|
||||||
|
|
||||||
|
public final List<ClassOrInterface> KlassenVektor;
|
||||||
|
public final Set<JavaClassName> imports;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die SourceFile repräsntiert eine zu einem Syntaxbaum eingelesene Java-Datei.
|
||||||
|
* SourceFile stellt dabei den Wurzelknoten des Syntaxbaumes dar.
|
||||||
|
*/
|
||||||
|
public SourceFile(String pkgName, List<ClassOrInterface> classDefinitions, Set<JavaClassName> imports) {
|
||||||
|
super(new NullToken());
|
||||||
|
//if (classDefinitions.size() > 0) { // Enthält die Liste Klassen?
|
||||||
|
this.KlassenVektor = classDefinitions; // Klassen werden übernommen
|
||||||
|
//} else {
|
||||||
|
// this.KlassenVektor = null; // es handelt sich um ein "Java Module"
|
||||||
|
//}
|
||||||
|
this.pkgName = pkgName;
|
||||||
|
this.imports = imports;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SourceFile(SourceFile sf) {
|
||||||
|
super(new NullToken());
|
||||||
|
this.KlassenVektor = new ArrayList<>(sf.KlassenVektor);
|
||||||
|
this.imports = new HashSet<>(sf.imports);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPkgName() {
|
||||||
|
return this.pkgName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get imports (to test implementation)
|
||||||
|
public Set<JavaClassName> getImports() {
|
||||||
|
return this.imports;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ClassOrInterface> getClasses() {
|
||||||
|
return KlassenVektor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Method> getAllMethods() {
|
||||||
|
List<Method> ret = new ArrayList<>();
|
||||||
|
getClasses().forEach(cl -> ret.addAll(cl.getMethods()));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(ASTVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||||
|
|
||||||
|
public interface StatementVisitor {
|
||||||
|
|
||||||
|
void visit(ArgumentList argumentList);
|
||||||
|
|
||||||
|
void visit(LambdaExpression lambdaExpression);
|
||||||
|
|
||||||
|
void visit(Assign assign);
|
||||||
|
|
||||||
|
void visit(BinaryExpr binary);
|
||||||
|
|
||||||
|
void visit(BoolExpression logical);
|
||||||
|
|
||||||
|
void visit(Block block);
|
||||||
|
|
||||||
|
void visit(CastExpr castExpr);
|
||||||
|
|
||||||
|
void visit(EmptyStmt emptyStmt);
|
||||||
|
|
||||||
|
void visit(FieldVar fieldVar);
|
||||||
|
|
||||||
|
void visit(ForStmt forStmt);
|
||||||
|
|
||||||
|
void visit(IfStmt ifStmt);
|
||||||
|
|
||||||
|
void visit(InstanceOf instanceOf);
|
||||||
|
|
||||||
|
void visit(LocalVar localVar);
|
||||||
|
|
||||||
|
void visit(LocalVarDecl localVarDecl);
|
||||||
|
|
||||||
|
void visit(MethodCall methodCall);
|
||||||
|
|
||||||
|
void visit(NewClass methodCall);
|
||||||
|
|
||||||
|
void visit(NewArray newArray);
|
||||||
|
|
||||||
|
void visit(Return aReturn);
|
||||||
|
|
||||||
|
void visit(ReturnVoid aReturn);
|
||||||
|
|
||||||
|
void visit(Switch switchStmt);
|
||||||
|
|
||||||
|
void visit(SwitchBlock switchBlock);
|
||||||
|
|
||||||
|
void visit(SwitchLabel switchLabel);
|
||||||
|
|
||||||
|
void visit(Break aBreak);
|
||||||
|
|
||||||
|
void visit(Yield aYield);
|
||||||
|
|
||||||
|
void visit(StaticClassName staticClassName);
|
||||||
|
|
||||||
|
void visit(Super aSuper);
|
||||||
|
|
||||||
|
void visit(This aThis);
|
||||||
|
|
||||||
|
void visit(WhileStmt whileStmt);
|
||||||
|
|
||||||
|
void visit(DoStmt whileStmt);
|
||||||
|
|
||||||
|
void visit(AssignToField assignLeftSide);
|
||||||
|
|
||||||
|
void visit(AssignToLocal assignLeftSide);
|
||||||
|
|
||||||
|
void visit(SuperCall superCall);
|
||||||
|
|
||||||
|
void visit(ExpressionReceiver expressionReceiver);
|
||||||
|
|
||||||
|
void visit(UnaryExpr unaryExpr);
|
||||||
|
|
||||||
|
void visit(Literal literal);
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.core.IItemWithOffset;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
//import org.antlr.v4.runtime.misc.Pair;
|
||||||
|
|
||||||
|
public abstract class SyntaxTreeNode implements IItemWithOffset{
|
||||||
|
private final Token offset;
|
||||||
|
|
||||||
|
public SyntaxTreeNode(Token offset){
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Token getOffset(){
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void accept(ASTVisitor visitor);
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
|
||||||
|
public interface TypeScope {
|
||||||
|
Iterable<? extends GenericTypeVar> getGenerics();
|
||||||
|
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric getReturnType();
|
||||||
|
}
|
@ -0,0 +1,446 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.factory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.bytecode.JavaTXSignatureAttribute;
|
||||||
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.*;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.Field;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.Method;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Block;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Statement;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.WildcardType;
|
||||||
|
import de.dhbwstuttgart.util.Pair;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.objectweb.asm.*;
|
||||||
|
import org.objectweb.asm.signature.SignatureReader;
|
||||||
|
import org.objectweb.asm.signature.SignatureVisitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Anmerkung: Die ASTFactory Methoden, welche ASTBäume aus java.lang.Class Objekten generieren, können davon ausgehen, dass alle Imports und Typnamen korrekt sind und müssen diese nicht überprüfen.
|
||||||
|
*/
|
||||||
|
public class ASTFactory {
|
||||||
|
|
||||||
|
private static final HashMap<java.lang.Class, ClassOrInterface> cache = new HashMap<>();
|
||||||
|
|
||||||
|
public static ClassOrInterface createClass(java.lang.Class jreClass) {
|
||||||
|
if (cache.containsKey(jreClass))
|
||||||
|
return cache.get(jreClass);
|
||||||
|
|
||||||
|
// TODO Inner classes
|
||||||
|
|
||||||
|
var methodSignatures = new HashMap<Pair<String, String>, String>();
|
||||||
|
String classSignature = null;
|
||||||
|
|
||||||
|
// Load class with asm to figure out if there's a JavaTX signature
|
||||||
|
try {
|
||||||
|
var path = jreClass.getName().replace('.', '/') + ".class";
|
||||||
|
var classLoader = jreClass.getClassLoader();
|
||||||
|
if (classLoader != null && new File(path).exists()) {
|
||||||
|
var bytes = IOUtils.toByteArray(Objects.requireNonNull(classLoader.getResourceAsStream(path)));
|
||||||
|
var classReader = new ClassReader(bytes);
|
||||||
|
var classVisitor = new ClassVisitor(Opcodes.ASM7) {
|
||||||
|
String classSignature;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitAttribute(Attribute attribute) {
|
||||||
|
if (attribute.type.equals("JavaTXSignature")) {
|
||||||
|
classSignature = ((JavaTXSignatureAttribute) attribute).signature;
|
||||||
|
}
|
||||||
|
super.visitAttribute(attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||||
|
classSignature = signature;
|
||||||
|
super.visit(version, access, name, signature, superName, interfaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
|
||||||
|
|
||||||
|
methodSignatures.put(new Pair<>(name, descriptor), signature);
|
||||||
|
return new MethodVisitor(Opcodes.ASM7) {
|
||||||
|
@Override
|
||||||
|
public void visitAttribute(Attribute attribute) {
|
||||||
|
if (attribute.type.equals("JavaTXSignature")) {
|
||||||
|
methodSignatures.put(new Pair<>(name, descriptor), ((JavaTXSignatureAttribute) attribute).signature);
|
||||||
|
}
|
||||||
|
super.visitAttribute(attribute);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
classReader.accept(classVisitor, new Attribute[] { new JavaTXSignatureAttribute() }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
|
||||||
|
classSignature = classVisitor.classSignature;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Skip
|
||||||
|
}
|
||||||
|
JavaClassName name = new JavaClassName(jreClass.getName());
|
||||||
|
List<Method> methoden = new ArrayList<>();
|
||||||
|
List<de.dhbwstuttgart.syntaxtree.Constructor> konstruktoren = new ArrayList<>();
|
||||||
|
for (java.lang.reflect.Constructor constructor : jreClass.getConstructors()) {
|
||||||
|
var signature = methodSignatures.get(new Pair<>(constructor.getName(), org.objectweb.asm.Type.getConstructorDescriptor(constructor)));
|
||||||
|
createConstructor(constructor, signature, jreClass).map(c -> konstruktoren.add(c));
|
||||||
|
}
|
||||||
|
Set<java.lang.reflect.Method> allMethods = new HashSet<>(Arrays.asList(jreClass.getMethods()));
|
||||||
|
Set<java.lang.reflect.Method> allDeclaredMethods = new HashSet<>(Arrays.asList(jreClass.getDeclaredMethods()));
|
||||||
|
Set<java.lang.reflect.Method> allInheritedMethods = new HashSet<>(allMethods);
|
||||||
|
allInheritedMethods.removeAll(allDeclaredMethods);
|
||||||
|
for (java.lang.reflect.Method method : allDeclaredMethods) {
|
||||||
|
var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
|
||||||
|
methoden.add(createMethod(method, signature, jreClass, false));
|
||||||
|
}
|
||||||
|
for (java.lang.reflect.Method method : allInheritedMethods) {
|
||||||
|
var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
|
||||||
|
methoden.add(createMethod(method, signature, jreClass, true));
|
||||||
|
}
|
||||||
|
List<Field> felder = new ArrayList<>();
|
||||||
|
for (java.lang.reflect.Field field : jreClass.getDeclaredFields()) {
|
||||||
|
felder.add(createField(field, name));
|
||||||
|
}
|
||||||
|
int modifier = jreClass.getModifiers();
|
||||||
|
boolean isInterface = jreClass.isInterface();
|
||||||
|
List<Annotation> aLA;
|
||||||
|
boolean isFunctionalInterface =
|
||||||
|
(aLA = Arrays.asList(jreClass.getAnnotations())).size() > 0 &&
|
||||||
|
aLA.get(0) instanceof FunctionalInterface ?
|
||||||
|
true :
|
||||||
|
false;
|
||||||
|
// see: https://stackoverflow.com/questions/9934774/getting-generic-parameter-from-supertype-class
|
||||||
|
ParameterizedType parameterSuperClass = null;
|
||||||
|
Type tempSuperClass = jreClass.getGenericSuperclass();
|
||||||
|
if (tempSuperClass != null && tempSuperClass instanceof ParameterizedType)
|
||||||
|
parameterSuperClass = (ParameterizedType) tempSuperClass;
|
||||||
|
java.lang.Class superjreClass = jreClass.getSuperclass();
|
||||||
|
RefType superClass;
|
||||||
|
if (parameterSuperClass != null) {
|
||||||
|
superClass = (RefType) createType(parameterSuperClass);
|
||||||
|
} else if (superjreClass != null) {
|
||||||
|
superClass = (RefType) createType(superjreClass);
|
||||||
|
} else {// Jede Klasse und jedes Interface erbt von Object: (auch Object selbst!)
|
||||||
|
superClass = (RefType) createType(java.lang.Object.class);
|
||||||
|
}
|
||||||
|
List<RefType> implementedInterfaces = new ArrayList<>();
|
||||||
|
for (Type jreInterface : jreClass.getGenericInterfaces()) {
|
||||||
|
implementedInterfaces.add((RefType) createType(jreInterface));
|
||||||
|
}
|
||||||
|
List<RefType> permittedSubtypes = new ArrayList<>();
|
||||||
|
if (jreClass.isSealed()) {
|
||||||
|
for (Class subclass : jreClass.getPermittedSubclasses()) {
|
||||||
|
permittedSubtypes.add((RefType) createType(subclass));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericDeclarationList genericDeclarationList = createGenerics(jreClass.getTypeParameters(), jreClass, null, classSignature);
|
||||||
|
|
||||||
|
Token offset = new NullToken(); // Braucht keinen Offset, da diese Klasse nicht aus einem Quellcode geparst wurde
|
||||||
|
|
||||||
|
var cinf = new ClassOrInterface(modifier, name, felder, Optional.empty() /* eingefuegt PL 2018-11-24 */, Optional.empty(), methoden, konstruktoren, genericDeclarationList, superClass, isInterface, isFunctionalInterface, implementedInterfaces, permittedSubtypes, offset);
|
||||||
|
cache.put(jreClass, cinf);
|
||||||
|
return cinf;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Field createField(java.lang.reflect.Field field, JavaClassName jreClass) {
|
||||||
|
return new Field(field.getName(), createType(field.getGenericType()), field.getModifiers(), new NullToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
// private static RefType createType(Class classType) {
|
||||||
|
// return createClass(classType).getType();
|
||||||
|
// }
|
||||||
|
|
||||||
|
private static Optional<de.dhbwstuttgart.syntaxtree.Constructor> createConstructor(Constructor constructor, String signature, Class inClass) {
|
||||||
|
String name = constructor.getName();
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric returnType = createType(inClass);
|
||||||
|
Parameter[] jreParams = constructor.getParameters();
|
||||||
|
Type[] jreGenericParams = constructor.getGenericParameterTypes();
|
||||||
|
List<Pattern> params = new ArrayList<>();
|
||||||
|
int i = 0;
|
||||||
|
for (Type jreParam : jreGenericParams) {
|
||||||
|
if (jreParam == null)
|
||||||
|
continue;
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam);
|
||||||
|
params.add(new FormalParameter(jreParams[i].getName(), paramType, new NullToken()));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
ParameterList parameterList = new ParameterList(params, new NullToken());
|
||||||
|
Block block = new Block(new ArrayList<Statement>(), new NullToken());
|
||||||
|
GenericDeclarationList gtvDeclarations = createGenerics(constructor.getTypeParameters(), inClass, constructor.getName(), signature);
|
||||||
|
Token offset = new NullToken();
|
||||||
|
int modifier = constructor.getModifiers();
|
||||||
|
|
||||||
|
if (inClass.equals(java.lang.Object.class)) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
String name = jreMethod.getName();
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric returnType;
|
||||||
|
Type jreRetType;
|
||||||
|
if (jreMethod.getGenericReturnType() != null) {
|
||||||
|
jreRetType = jreMethod.getGenericReturnType();
|
||||||
|
} else {
|
||||||
|
jreRetType = jreMethod.getReturnType();
|
||||||
|
}
|
||||||
|
returnType = createType(jreRetType);
|
||||||
|
Parameter[] jreParams = jreMethod.getParameters();
|
||||||
|
Type[] jreGenericParams = jreMethod.getGenericParameterTypes();
|
||||||
|
List<Pattern> params = new ArrayList<>();
|
||||||
|
int i = 0;
|
||||||
|
for (Type jreParam : jreGenericParams) {
|
||||||
|
if (jreParam == null)
|
||||||
|
continue;
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam);
|
||||||
|
params.add(new FormalParameter(jreParams[i].getName(), paramType, new NullToken()));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
ParameterList parameterList = new ParameterList(params, new NullToken());
|
||||||
|
Block block = new Block(new ArrayList<Statement>(), new NullToken());
|
||||||
|
GenericDeclarationList gtvDeclarations = createGenerics(jreMethod.getTypeParameters(), inClass, jreMethod.getName(), signature);
|
||||||
|
Token offset = new NullToken();
|
||||||
|
|
||||||
|
return new Method(jreMethod.getModifiers(), name, returnType, parameterList, block, gtvDeclarations, offset, isInherited);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName, String signature) {
|
||||||
|
if (signature == null) {
|
||||||
|
List<de.dhbwstuttgart.syntaxtree.GenericTypeVar> gtvs = new ArrayList<>();
|
||||||
|
for (TypeVariable jreTV : typeParameters) {
|
||||||
|
de.dhbwstuttgart.syntaxtree.GenericTypeVar gtv = createGeneric(jreTV, jreTV.getName(), context, methodName);
|
||||||
|
gtvs.add(gtv);
|
||||||
|
}
|
||||||
|
return new GenericDeclarationList(gtvs, new NullToken());
|
||||||
|
} else {
|
||||||
|
var res = createGenerics(signature);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GenericDeclarationList createGenerics(String signature) {
|
||||||
|
if (signature == null)
|
||||||
|
return new GenericDeclarationList(new ArrayList<>(), new NullToken());
|
||||||
|
|
||||||
|
var gtvs = new ArrayList<GenericTypeVar>();
|
||||||
|
var signatureVisitor = new SignatureVisitor(Opcodes.ASM7) {
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> bounds = new ArrayList<>();
|
||||||
|
final Stack<RefTypeOrTPHOrWildcardOrGeneric> bound = new Stack<>();
|
||||||
|
final Stack<RefType> classTypes = new Stack<>();
|
||||||
|
|
||||||
|
// All hail the mighty visitor pattern
|
||||||
|
final SignatureVisitor doNothing = new SignatureVisitor(Opcodes.ASM7) {
|
||||||
|
};
|
||||||
|
|
||||||
|
char wildcard = '=';
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureVisitor visitSuperclass() {
|
||||||
|
return doNothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureVisitor visitParameterType() {
|
||||||
|
return doNothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureVisitor visitReturnType() {
|
||||||
|
return doNothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureVisitor visitExceptionType() {
|
||||||
|
return doNothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitFormalTypeParameter(String name) {
|
||||||
|
bounds = new ArrayList<>();
|
||||||
|
gtvs.add(new GenericTypeVar(name, bounds, new NullToken(), new NullToken()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitTypeVariable(String name) {
|
||||||
|
var refType = new GenericRefType(name, new NullToken());
|
||||||
|
if (classTypes.isEmpty()) {
|
||||||
|
((List<RefTypeOrTPHOrWildcardOrGeneric>) gtvs.get(gtvs.size() - 1).getBounds()).add(refType);
|
||||||
|
} else {
|
||||||
|
pushType(refType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitClassType(String name) {
|
||||||
|
var refType = new RefType(new JavaClassName(name.replaceAll("/", ".")), new ArrayList<>(), new NullToken());
|
||||||
|
classTypes.push(refType);
|
||||||
|
pushType(refType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pushType(RefTypeOrTPHOrWildcardOrGeneric refType) {
|
||||||
|
if (wildcard == SignatureVisitor.SUPER) {
|
||||||
|
bound.push(new SuperWildcardType(refType, new NullToken()));
|
||||||
|
} else if (wildcard == SignatureVisitor.EXTENDS) {
|
||||||
|
bound.push(new ExtendsWildcardType(refType, new NullToken()));
|
||||||
|
} else {
|
||||||
|
bound.push(refType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureVisitor visitTypeArgument(char wildcard) {
|
||||||
|
this.wildcard = wildcard;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean equals(RefTypeOrTPHOrWildcardOrGeneric a, RefTypeOrTPHOrWildcardOrGeneric b) {
|
||||||
|
if (b instanceof SuperWildcardType wc)
|
||||||
|
return equals(a, wc.getInnerType());
|
||||||
|
else if (b instanceof ExtendsWildcardType wc)
|
||||||
|
return equals(a, wc.getInnerType());
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitEnd() {
|
||||||
|
wildcard = '=';
|
||||||
|
var classType = (RefType) classTypes.pop();
|
||||||
|
if (!classTypes.isEmpty()) {
|
||||||
|
var next = classTypes.peek();
|
||||||
|
var par = bound.pop();
|
||||||
|
var toAdd = new ArrayList<RefTypeOrTPHOrWildcardOrGeneric>();
|
||||||
|
while (!equals(next, par)) {
|
||||||
|
toAdd.add(par);
|
||||||
|
par = bound.pop();
|
||||||
|
}
|
||||||
|
var element = par;
|
||||||
|
if (par instanceof WildcardType wc) {
|
||||||
|
element = wc.getInnerType();
|
||||||
|
}
|
||||||
|
Collections.reverse(toAdd);
|
||||||
|
((RefType) element).getParaList().addAll(toAdd);
|
||||||
|
|
||||||
|
bound.push(par);
|
||||||
|
} else {
|
||||||
|
if (bound.peek() != classType) {
|
||||||
|
classType.getParaList().add(bound.pop());
|
||||||
|
bounds.add(classType);
|
||||||
|
} else {
|
||||||
|
bounds.add(bound.pop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var sr = new SignatureReader(signature);
|
||||||
|
sr.accept(signatureVisitor);
|
||||||
|
|
||||||
|
return new GenericDeclarationList(gtvs, new NullToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RefTypeOrTPHOrWildcardOrGeneric createType(java.lang.reflect.Type type) {
|
||||||
|
if (type == null || type.getTypeName().equals("void")) {
|
||||||
|
return new Void(new NullToken());
|
||||||
|
} else if (type.getTypeName().equals("int")) {
|
||||||
|
return new RefType(new JavaClassName("java.lang.Integer"), new ArrayList<>(), new NullToken(), true);
|
||||||
|
} else if (type.getTypeName().equals("byte")) {
|
||||||
|
return new RefType(new JavaClassName("java.lang.Byte"), new ArrayList<>(), new NullToken(), true);
|
||||||
|
} else if (type.getTypeName().equals("boolean")) {
|
||||||
|
return new RefType(new JavaClassName("java.lang.Boolean"), new ArrayList<>(), new NullToken(), true);
|
||||||
|
} else if (type.getTypeName().equals("char")) {
|
||||||
|
return new RefType(new JavaClassName("java.lang.Char"), new ArrayList<>(), new NullToken(), true);
|
||||||
|
} else if (type.getTypeName().equals("short")) {
|
||||||
|
return new RefType(new JavaClassName("java.lang.Short"), new ArrayList<>(), new NullToken(), true);
|
||||||
|
} else if (type.getTypeName().equals("double")) {
|
||||||
|
return new RefType(new JavaClassName("java.lang.Double"), new ArrayList<>(), new NullToken(), true);
|
||||||
|
} else if (type.getTypeName().equals("long")) {
|
||||||
|
return new RefType(new JavaClassName("java.lang.Long"), new ArrayList<>(), new NullToken(), true);
|
||||||
|
} else {
|
||||||
|
if (type instanceof TypeVariable) {
|
||||||
|
// GTVDeclarationContext via "(TypeVariable) type).getGenericDeclaration()"
|
||||||
|
return new GenericRefType(type.getTypeName(), new NullToken());
|
||||||
|
}
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
|
||||||
|
if (type instanceof ParameterizedType) {
|
||||||
|
for (Type t : ((ParameterizedType) type).getActualTypeArguments()) {
|
||||||
|
params.add(createType(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String name = type.getTypeName();
|
||||||
|
if (name.contains("<")) { // Komischer fix. Type von Generischen Typen kann die Generics im Namen enthalten Type<A>
|
||||||
|
// Diese entfernen:
|
||||||
|
name = name.split("<")[0];
|
||||||
|
}
|
||||||
|
if (type instanceof java.lang.reflect.WildcardType) {
|
||||||
|
java.lang.reflect.WildcardType wildcardType = (java.lang.reflect.WildcardType) type;
|
||||||
|
if (wildcardType.getLowerBounds().length > 0) {
|
||||||
|
return new SuperWildcardType(createType(wildcardType.getLowerBounds()[0]), new NullToken());
|
||||||
|
} else if (wildcardType.getUpperBounds().length > 0) {
|
||||||
|
return new ExtendsWildcardType(createType(wildcardType.getUpperBounds()[0]), new NullToken());
|
||||||
|
} else {// Es handelt sich um den '?'-Typ:
|
||||||
|
return new ExtendsWildcardType(createObjectType(), new NullToken());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RefType ret = new RefType(new JavaClassName(name), params, new NullToken());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static de.dhbwstuttgart.syntaxtree.GenericTypeVar createGeneric(TypeVariable jreTypeVar, String jreTVName, Class context, String parentMethod) {
|
||||||
|
JavaClassName parentClass = new JavaClassName(context.getName());
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> genericBounds = new ArrayList<>();
|
||||||
|
java.lang.reflect.Type[] bounds = jreTypeVar.getBounds();
|
||||||
|
if (bounds.length > 0) {
|
||||||
|
for (java.lang.reflect.Type bound : bounds) {
|
||||||
|
genericBounds.add(createType(bound));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new de.dhbwstuttgart.syntaxtree.GenericTypeVar(jreTVName, genericBounds, new NullToken(), new NullToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ClassOrInterface createObjectClass() {
|
||||||
|
return createClass(Object.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RefType createObjectType() {
|
||||||
|
return new RefType(createClass(Object.class).getClassName(), new NullToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* public Constructor createEmptyConstructor(Class parent){ Block block = new Block(); block.setType(new de.dhbwstuttgart.syntaxtree.type.Void(block, 0)); block.statements.add(new SuperCall(block));
|
||||||
|
*
|
||||||
|
* return ASTFactory.createConstructor(parent, new ParameterList(), block); }
|
||||||
|
*
|
||||||
|
* public static Constructor createConstructor(Class superClass, ParameterList paralist, Block block){ block.parserPostProcessing(superClass);
|
||||||
|
*
|
||||||
|
* Method method = ASTFactory.createMethod("<init>", paralist, block, superClass); method.setType(new de.dhbwstuttgart.syntaxtree.type.Void(block, 0));
|
||||||
|
*
|
||||||
|
* return new Constructor(method, superClass); }
|
||||||
|
*
|
||||||
|
* public static Class createClass(String className, RefType type, Modifiers modifiers, Menge supertypeGenPara, SourceFile parent) { // TODO bytecode createClass //String name, RefType superClass, Modifiers modifiers, Menge<String> supertypeGenPara Class generatedClass = new Class(className, type, modifiers, supertypeGenPara); generatedClass.addField(ASTFactory.createEmptyConstructor(generatedClass));
|
||||||
|
*
|
||||||
|
* generatedClass.parserPostProcessing(parent);
|
||||||
|
*
|
||||||
|
* return generatedClass; }
|
||||||
|
*
|
||||||
|
* public static Class createObject(){ return createClass(java.lang.Object.class); }
|
||||||
|
*
|
||||||
|
* public static Class createInterface(String className, RefType superClass, Modifiers modifiers, Menge supertypeGenPara, SourceFile parent){ Class generatedClass = new Class(new JavaClassName(className), new ArrayList<Method>(), new ArrayList<Field>(), modifiers, true, superClass, new ArrayList<RefType>(), new GenericDeclarationList(), -1); generatedClass.parserPostProcessing(parent); return generatedClass; }
|
||||||
|
*
|
||||||
|
* public static RefType createObjectType(){ return createObjectClass().getType(); }
|
||||||
|
*/
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.factory;
|
||||||
|
|
||||||
|
public class NameGenerator {
|
||||||
|
|
||||||
|
private static String strNextName = "A";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setzt den zu Beginn der Typinferenz auf "A" zurueck.
|
||||||
|
* Dies ist bei JUnit-Test noetig
|
||||||
|
* <code>TypePlaceholder</code>. <br>Author: Martin Pluemicke
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static void reset() {
|
||||||
|
strNextName = "A";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Berechnet einen neuen, eindeutigen Namen f�r eine neue
|
||||||
|
* <code>TypePlaceholder</code>. <br>Author: J�rg B�uerle
|
||||||
|
* @return Der Name
|
||||||
|
*/
|
||||||
|
public static String makeNewName()
|
||||||
|
{
|
||||||
|
// otth: Funktion berechnet einen neuen Namen anhand eines alten gespeicherten
|
||||||
|
String strReturn = strNextName;
|
||||||
|
|
||||||
|
// n�chster Name berechnen und in strNextName speichern
|
||||||
|
inc( strNextName.length() - 1 );
|
||||||
|
|
||||||
|
return strReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hilfsfunktion zur Berechnung eines neuen Namens
|
||||||
|
* <br>Author: J�rg B�uerle
|
||||||
|
* @param i
|
||||||
|
*/
|
||||||
|
private static void inc(int i)
|
||||||
|
{
|
||||||
|
// otth: Hilfsfunktion zur Berechnung eines neuen Namens
|
||||||
|
// otth: Erh�hung des Buchstabens an der Stelle i im String strNextName
|
||||||
|
// otth: Nach �berlauf: rekursiver Aufruf
|
||||||
|
|
||||||
|
// falls i = -1 --> neuer Buchstabe vorne anf�gen
|
||||||
|
if ( i == -1 )
|
||||||
|
{
|
||||||
|
strNextName = "A" + strNextName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char cBuchstabe = (char)(strNextName.charAt( i ));
|
||||||
|
cBuchstabe++;
|
||||||
|
if ( cBuchstabe - 65 > 25 )
|
||||||
|
{
|
||||||
|
// aktuelle Stelle: auf A zuruecksetzen
|
||||||
|
manipulate( i, 'A' );
|
||||||
|
|
||||||
|
// vorherige Stelle erh�hen
|
||||||
|
inc( i - 1 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// aktueller Buchstabe �ndern
|
||||||
|
manipulate( i, cBuchstabe );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hilfsfunktion zur Berechnung eines neuen Namens.
|
||||||
|
* <br>Author: J�rg B�uerle
|
||||||
|
* @param nStelle
|
||||||
|
* @param nWert
|
||||||
|
*/
|
||||||
|
private static void manipulate( int nStelle, char nWert )
|
||||||
|
{
|
||||||
|
// otth: Hilfsfunktion zur Berechnung eines neuen Namens
|
||||||
|
// otth: Ersetzt im String 'strNextName' an der Position 'nStelle' den Buchstaben durch 'nWert'
|
||||||
|
|
||||||
|
String strTemp = "";
|
||||||
|
for( int i = 0; i < strNextName.length(); i++)
|
||||||
|
{
|
||||||
|
if ( i == nStelle )
|
||||||
|
strTemp = strTemp + nWert;
|
||||||
|
else
|
||||||
|
strTemp = strTemp + strNextName.charAt( i );
|
||||||
|
}
|
||||||
|
strNextName = strTemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generiert Hilfsmethoden für die Unary und Binary Operatoren
|
||||||
|
* Diese Methoden stellen die möglichen Operationen +,-,++, etc dar
|
||||||
|
*/
|
||||||
|
public class PrimitiveMethodsGenerator {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,286 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.factory;
|
||||||
|
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
|
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.FCGenerator;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.WildcardType;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.Pair;
|
||||||
|
import de.dhbwstuttgart.typeinference.result.PairNoResult;
|
||||||
|
import de.dhbwstuttgart.typeinference.result.PairTPHEqualTPH;
|
||||||
|
import de.dhbwstuttgart.typeinference.result.PairTPHequalRefTypeOrWildcardType;
|
||||||
|
import de.dhbwstuttgart.typeinference.result.PairTPHsmallerTPH;
|
||||||
|
import de.dhbwstuttgart.typeinference.result.ResultPair;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.model.*;
|
||||||
|
|
||||||
|
public class UnifyTypeFactory {
|
||||||
|
|
||||||
|
private static ArrayList<PlaceholderType> PLACEHOLDERS = new ArrayList<>();
|
||||||
|
|
||||||
|
public static FiniteClosure generateFC(List<ClassOrInterface> fromClasses, Writer logFile, ClassLoader classLoader) throws ClassNotFoundException {
|
||||||
|
/*
|
||||||
|
Die transitive Hülle muss funktionieren.
|
||||||
|
Man darf schreiben List<A> extends AL<A>
|
||||||
|
und Vector<B> extends List<B>
|
||||||
|
hier muss dann aber dennoch die Vererbung V < L < AL
|
||||||
|
hergestellt werden.
|
||||||
|
In einem solchen Vererbungsbaum dürfen die TPH auch die gleichen Namen haben.
|
||||||
|
Generell dürfen sie immer die gleichen Namen haben.
|
||||||
|
TODO: die transitive Hülle bilden
|
||||||
|
*/
|
||||||
|
return new FiniteClosure(FCGenerator.toUnifyFC(fromClasses, classLoader), logFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr){
|
||||||
|
return new UnifyPair(tl, tr, PairOperator.SMALLER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UnifyPair generateSmallerDotPair(UnifyType tl, UnifyType tr){
|
||||||
|
return new UnifyPair(tl, tr, PairOperator.SMALLERDOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UnifyPair generateSmallNotEqualDotPair(UnifyType tl, UnifyType tr){
|
||||||
|
return new UnifyPair(tl, tr, PairOperator.SMALLERNEQDOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UnifyPair generateEqualDotPair(UnifyType tl, UnifyType tr){
|
||||||
|
return new UnifyPair(tl, tr, PairOperator.EQUALSDOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert from
|
||||||
|
* ASTType -> UnifyType
|
||||||
|
*/
|
||||||
|
public static UnifyType convert(RefTypeOrTPHOrWildcardOrGeneric t, Boolean innerType){
|
||||||
|
if(t instanceof GenericRefType){
|
||||||
|
return UnifyTypeFactory.convert((GenericRefType)t, innerType);
|
||||||
|
}else if(t instanceof TypePlaceholder){
|
||||||
|
return UnifyTypeFactory.convert((TypePlaceholder)t, innerType);
|
||||||
|
}else if(t instanceof ExtendsWildcardType){
|
||||||
|
return UnifyTypeFactory.convert((ExtendsWildcardType)t, innerType);
|
||||||
|
}else if(t instanceof SuperWildcardType){
|
||||||
|
return UnifyTypeFactory.convert((SuperWildcardType)t, innerType);
|
||||||
|
}else if(t instanceof RefType){
|
||||||
|
return UnifyTypeFactory.convert((RefType)t, innerType);
|
||||||
|
}
|
||||||
|
//Es wurde versucht ein Typ umzuwandeln, welcher noch nicht von der Factory abgedeckt ist
|
||||||
|
throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UnifyType convert(RefType t, Boolean innerType){
|
||||||
|
//Check if it is a FunN Type:
|
||||||
|
Pattern p = Pattern.compile("Fun(\\d+)[$][$]");
|
||||||
|
Matcher m = p.matcher(t.getName().toString());
|
||||||
|
boolean b = m.matches();
|
||||||
|
if(b){
|
||||||
|
Integer N = Integer.valueOf(m.group(1));
|
||||||
|
if((N + 1) == t.getParaList().size()){
|
||||||
|
return convertFunN(t.getParaList(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnifyType ret;
|
||||||
|
if(t.getParaList() != null && t.getParaList().size() > 0){
|
||||||
|
List<UnifyType> params = new ArrayList<>();
|
||||||
|
for(RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()){
|
||||||
|
params.add(UnifyTypeFactory.convert(pT, true));
|
||||||
|
}
|
||||||
|
ret = new ReferenceType(t.getName().toString(),new TypeParams(params));
|
||||||
|
}else{
|
||||||
|
ret = new ReferenceType(t.getName().toString(), false);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UnifyType convertFunN(List<RefTypeOrTPHOrWildcardOrGeneric> paraList, Boolean innerType){
|
||||||
|
UnifyType ret;
|
||||||
|
List<UnifyType> params = new ArrayList<>();
|
||||||
|
if(paraList != null && paraList.size() > 0){
|
||||||
|
for(RefTypeOrTPHOrWildcardOrGeneric pT : paraList){
|
||||||
|
params.add(UnifyTypeFactory.convert(pT, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = FunNType.getFunNType(new TypeParams(params));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UnifyType convert(TypePlaceholder tph, Boolean innerType){
|
||||||
|
if (tph.getName().equals("AFR")) {
|
||||||
|
System.out.println("XXX"+innerType);
|
||||||
|
}
|
||||||
|
PlaceholderType ntph = new PlaceholderType(tph.getName());
|
||||||
|
ntph.setVariance(tph.getVariance());
|
||||||
|
ntph.setOrCons(tph.getOrCons());
|
||||||
|
int in = PLACEHOLDERS.indexOf(ntph);
|
||||||
|
if (in == -1) {
|
||||||
|
PLACEHOLDERS.add(ntph);
|
||||||
|
ntph.setInnerType(innerType);
|
||||||
|
return ntph;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PlaceholderType oldpht = PLACEHOLDERS.get(in);
|
||||||
|
oldpht.setInnerType(oldpht.isInnerType() || innerType);
|
||||||
|
return oldpht;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UnifyType convert(GenericRefType t, Boolean innerType){
|
||||||
|
return new ReferenceType(t.getParsedName(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UnifyType convert(WildcardType t, Boolean innerType){
|
||||||
|
if(t.isExtends())
|
||||||
|
return new ExtendsType(UnifyTypeFactory.convert(t.getInnerType(), false));
|
||||||
|
else if(t.isSuper())
|
||||||
|
return new SuperType(UnifyTypeFactory.convert(t.getInnerType(), false));
|
||||||
|
else throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static ConstraintSet<UnifyPair> convert(ConstraintSet<Pair> constraints) {
|
||||||
|
return constraints.map(UnifyTypeFactory::convert);
|
||||||
|
}
|
||||||
|
|
||||||
|
//NEVER USED
|
||||||
|
//public static Constraint<UnifyPair> convert(Constraint<Pair> constraint){
|
||||||
|
// Constraint<UnifyPair> unifyPairConstraint = constraint.stream()
|
||||||
|
// .map(UnifyTypeFactory::convert)
|
||||||
|
// .collect(Collectors.toCollection( () -> new Constraint<UnifyPair> (constraint.isInherited(), convert(constraint.getExtendConstraint()))));
|
||||||
|
// return unifyPairConstraint;
|
||||||
|
//}
|
||||||
|
|
||||||
|
public static UnifyPair convert(Pair p) {
|
||||||
|
UnifyPair ret = null;
|
||||||
|
if(p.GetOperator().equals(PairOperator.SMALLERDOT)) {
|
||||||
|
ret = generateSmallerDotPair(UnifyTypeFactory.convert(p.TA1, false)
|
||||||
|
, UnifyTypeFactory.convert(p.TA2, false));
|
||||||
|
//return ret;
|
||||||
|
}else if(p.GetOperator().equals(PairOperator.SMALLERNEQDOT)) {
|
||||||
|
ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(p.TA1, false)
|
||||||
|
, UnifyTypeFactory.convert(p.TA2, false));
|
||||||
|
//return ret;
|
||||||
|
}else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) {
|
||||||
|
ret = generateEqualDotPair(UnifyTypeFactory.convert(p.TA1, false)
|
||||||
|
, UnifyTypeFactory.convert(p.TA2, false));
|
||||||
|
//return ret;
|
||||||
|
}else if(p.GetOperator().equals(PairOperator.SMALLER)){
|
||||||
|
ret = generateSmallerPair(UnifyTypeFactory.convert(p.TA1, false),
|
||||||
|
UnifyTypeFactory.convert(p.TA2, false));
|
||||||
|
}else throw new NotImplementedException();
|
||||||
|
UnifyType lhs, rhs;
|
||||||
|
if (((lhs = ret.getLhsType()) instanceof PlaceholderType)
|
||||||
|
&& ((PlaceholderType)lhs).isWildcardable()
|
||||||
|
&& (rhs = ret.getLhsType()) instanceof PlaceholderType) {
|
||||||
|
if (lhs.getName().equals("AQ")) {
|
||||||
|
System.out.println("");
|
||||||
|
}
|
||||||
|
((PlaceholderType)rhs).enableWildcardtable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((rhs = ret.getLhsType()) instanceof PlaceholderType)
|
||||||
|
&& ((PlaceholderType)rhs).isWildcardable()
|
||||||
|
&& (lhs = ret.getLhsType()) instanceof PlaceholderType) {
|
||||||
|
if (rhs.getName().equals("AQ")) {
|
||||||
|
System.out.println("");
|
||||||
|
}
|
||||||
|
((PlaceholderType)lhs).enableWildcardtable();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert from
|
||||||
|
* UnifyType -> ASTType
|
||||||
|
*/
|
||||||
|
public static Set<ResultPair> convert(Set<UnifyPair> unifyPairSet, Map<String,TypePlaceholder> tphs) {
|
||||||
|
return unifyPairSet.stream().map(
|
||||||
|
unifyPair -> convert(unifyPair, tphs))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResultPair convert(UnifyPair mp, Map<String,TypePlaceholder> tphs) {
|
||||||
|
if (mp == null) { return null;} //kann bei basePairs passieren
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric tl = UnifyTypeFactory.convert(mp.getLhsType(), tphs);
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric tr = UnifyTypeFactory.convert(mp.getRhsType(), tphs);
|
||||||
|
if(tl instanceof TypePlaceholder){
|
||||||
|
if(tr instanceof TypePlaceholder) {
|
||||||
|
|
||||||
|
if(mp.getPairOp().equals(PairOperator.EQUALSDOT)) {
|
||||||
|
return new PairTPHEqualTPH((TypePlaceholder)tl, (TypePlaceholder)tr);
|
||||||
|
//Einfach ignorieren TODO: Das hier muss ausgebessert werden:
|
||||||
|
//return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, ASTFactory.createObjectType());
|
||||||
|
}else{
|
||||||
|
return new PairTPHsmallerTPH((TypePlaceholder)tl, (TypePlaceholder)tr, convert(mp.getBasePair(), tphs));
|
||||||
|
}
|
||||||
|
}else if(tr instanceof RefType){
|
||||||
|
return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (RefType) tr);
|
||||||
|
}else if(tr instanceof WildcardType){
|
||||||
|
return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (WildcardType) tr);
|
||||||
|
}else if(tr instanceof GenericRefType){
|
||||||
|
return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (GenericRefType) tr);
|
||||||
|
}else throw new NotImplementedException();
|
||||||
|
}else return new PairNoResult(tl, tr);//throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RefTypeOrTPHOrWildcardOrGeneric convert(ReferenceType t, Map<String,TypePlaceholder> tphs) {
|
||||||
|
if(JavaClassName.Void.equals(t.getName()))return new Void(new NullToken());
|
||||||
|
if (t.isGenTypeVar()) return new GenericRefType(t.getName(),new NullToken());
|
||||||
|
RefType ret = new RefType(new JavaClassName(t.getName()),convert(t.getTypeParams(), tphs),new NullToken());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RefTypeOrTPHOrWildcardOrGeneric convert(FunNType t, Map<String,TypePlaceholder> tphs) {
|
||||||
|
RefType ret = new RefType(new JavaClassName(t.getName()), convert(t.getTypeParams(), tphs), new NullToken());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RefTypeOrTPHOrWildcardOrGeneric convert(SuperType t, Map<String,TypePlaceholder> tphs) {
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric innerType = convert(t.getSuperedType(), tphs);
|
||||||
|
return new SuperWildcardType(innerType, new NullToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RefTypeOrTPHOrWildcardOrGeneric convert(ExtendsType t, Map<String,TypePlaceholder> tphs) {
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric innerType = convert(t.getExtendedType(), tphs);
|
||||||
|
return new ExtendsWildcardType(innerType, new NullToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RefTypeOrTPHOrWildcardOrGeneric convert(PlaceholderType t, Map<String,TypePlaceholder> tphs) {
|
||||||
|
TypePlaceholder ret = tphs.get(t.getName());
|
||||||
|
if(ret == null){ //Dieser TPH wurde vom Unifikationsalgorithmus erstellt
|
||||||
|
ret = TypePlaceholder.fresh(new NullToken());
|
||||||
|
tphs.put(t.getName(), ret);
|
||||||
|
}
|
||||||
|
ret.setVariance(t.getVariance());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RefTypeOrTPHOrWildcardOrGeneric convert(UnifyType t, Map<String,TypePlaceholder> tphs) {
|
||||||
|
if(t instanceof FunNType)return convert((FunNType) t, tphs);
|
||||||
|
if(t instanceof ReferenceType)return convert((ReferenceType) t, tphs);
|
||||||
|
if(t instanceof SuperType)return convert((SuperType) t, tphs);
|
||||||
|
if(t instanceof ExtendsType)return convert((ExtendsType) t, tphs);
|
||||||
|
if(t instanceof PlaceholderType)return convert((PlaceholderType) t, tphs);
|
||||||
|
throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<RefTypeOrTPHOrWildcardOrGeneric> convert(TypeParams typeParams, Map<String,TypePlaceholder> tphs) {
|
||||||
|
List<RefTypeOrTPHOrWildcardOrGeneric> ret = new ArrayList<>();
|
||||||
|
for(UnifyType uT : typeParams){
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric toAdd = convert(uT, tphs);
|
||||||
|
ret.add(toAdd);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.ASTVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ArgumentList extends SyntaxTreeNode
|
||||||
|
{
|
||||||
|
public ArgumentList(List<Expression> expr, Token offset) {
|
||||||
|
super(offset);
|
||||||
|
this.expr = expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Expression> expr;
|
||||||
|
|
||||||
|
public List<Expression> getArguments(){
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(ASTVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Aufbau:
|
||||||
|
rightSide = leftSide
|
||||||
|
*/
|
||||||
|
public class Assign extends Statement {
|
||||||
|
public final Expression rightSide;
|
||||||
|
public final AssignLeftSide lefSide;
|
||||||
|
|
||||||
|
public Assign(AssignLeftSide leftHandSide, Expression value, Token offset) {
|
||||||
|
super(leftHandSide.getType(), offset);
|
||||||
|
this.rightSide = value;
|
||||||
|
this.lefSide = leftHandSide;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public abstract class AssignLeftSide extends TypableStatement{
|
||||||
|
|
||||||
|
public AssignLeftSide(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||||
|
super(type, offset);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
|
||||||
|
public class AssignToField extends AssignLeftSide {
|
||||||
|
public final FieldVar field;
|
||||||
|
|
||||||
|
public AssignToField(FieldVar fieldVar) {
|
||||||
|
super(fieldVar.getType(), fieldVar.getOffset());
|
||||||
|
field = fieldVar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public class BinaryExpr extends Expression {
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Operator {
|
||||||
|
ADD, // +
|
||||||
|
SUB, // -
|
||||||
|
MUL, // *
|
||||||
|
MOD, // Modulo Operator %
|
||||||
|
AND, // &
|
||||||
|
OR, // |
|
||||||
|
DIV, // /
|
||||||
|
LESSTHAN, // <
|
||||||
|
BIGGERTHAN, // >
|
||||||
|
LESSEQUAL, // <=
|
||||||
|
BIGGEREQUAL, // >=
|
||||||
|
EQUAL, // ==
|
||||||
|
NOTEQUAL // !=
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Operator operation;
|
||||||
|
public final Expression lexpr;
|
||||||
|
public final Expression rexpr;
|
||||||
|
|
||||||
|
public BinaryExpr(Operator operation, RefTypeOrTPHOrWildcardOrGeneric type, Expression lexpr, Expression rexpr, Token offset) {
|
||||||
|
super(type, offset);
|
||||||
|
|
||||||
|
this.operation = operation;
|
||||||
|
this.lexpr = lexpr;
|
||||||
|
this.rexpr = rexpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
|
|
||||||
|
public class Block extends Statement {
|
||||||
|
public Block(List<Statement> statements, Token offset) {
|
||||||
|
super(TypePlaceholder.fresh(offset), offset);
|
||||||
|
this.statements = statements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Statement> statements = new ArrayList<>();
|
||||||
|
|
||||||
|
public List<Statement> getStatements() {
|
||||||
|
return statements;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
|
||||||
|
public class BoolExpression extends Expression {
|
||||||
|
|
||||||
|
public enum Operator {
|
||||||
|
AND, // &&
|
||||||
|
OR, // ||
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Operator operation;
|
||||||
|
public final Expression lexpr;
|
||||||
|
public final Expression rexpr;
|
||||||
|
|
||||||
|
public BoolExpression(Operator operation, RefTypeOrTPHOrWildcardOrGeneric type, Expression lexpr, Expression rexpr, Token offset) {
|
||||||
|
super(type, offset);
|
||||||
|
this.operation = operation;
|
||||||
|
this.lexpr = lexpr;
|
||||||
|
this.rexpr = rexpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
|
||||||
|
public class Break extends Statement {
|
||||||
|
|
||||||
|
public Break(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||||
|
super(type, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
|
||||||
|
public class CastExpr extends Expression
|
||||||
|
{
|
||||||
|
public CastExpr(RefTypeOrTPHOrWildcardOrGeneric castType, Expression expr, Token offset)
|
||||||
|
{
|
||||||
|
super(castType, offset);
|
||||||
|
this.expr = expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression expr;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public class DoStmt extends WhileStmt
|
||||||
|
{
|
||||||
|
public DoStmt(Expression expr, Statement loopBlock, Token offset)
|
||||||
|
{
|
||||||
|
super(expr, loopBlock, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
|
||||||
|
public class EmptyStmt extends Statement
|
||||||
|
{
|
||||||
|
public EmptyStmt(Token offset)
|
||||||
|
{
|
||||||
|
super(new Void(offset),offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.ASTVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public abstract class Expression extends TypableStatement {
|
||||||
|
public Expression(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||||
|
super(type, offset);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public class ExpressionReceiver extends Receiver
|
||||||
|
{
|
||||||
|
public final Expression expr;
|
||||||
|
|
||||||
|
public ExpressionReceiver(Expression expr)
|
||||||
|
{
|
||||||
|
super(expr.getType(), expr.getOffset());
|
||||||
|
this.expr = expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.exceptions.TypeinferenceException;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class FieldVar extends Expression {
|
||||||
|
|
||||||
|
public final String fieldVarName;
|
||||||
|
public final Expression receiver;
|
||||||
|
public final boolean isStatic;
|
||||||
|
|
||||||
|
public FieldVar(Expression receiver, boolean isStatic, String fieldVarName, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||||
|
super(type, offset);
|
||||||
|
this.fieldVarName = fieldVarName;
|
||||||
|
this.receiver = receiver;
|
||||||
|
this.isStatic = isStatic;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ForStmt extends Statement
|
||||||
|
{
|
||||||
|
public final List<Statement> initializer;
|
||||||
|
public final Expression condition;
|
||||||
|
public final List<Expression> loopExpr;
|
||||||
|
public final Statement block;
|
||||||
|
|
||||||
|
public ForStmt(Token offset, List<Statement> initializer, Expression condition, List<Expression> loopExpr, Statement block)
|
||||||
|
{
|
||||||
|
super(new Void(new NullToken()), offset);
|
||||||
|
this.initializer = initializer;
|
||||||
|
this.condition = condition;
|
||||||
|
this.loopExpr = loopExpr;
|
||||||
|
this.block = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public class IfStmt extends Statement {
|
||||||
|
public final Expression expr;
|
||||||
|
public final Statement then_block;
|
||||||
|
public final Statement else_block;
|
||||||
|
|
||||||
|
public IfStmt(RefTypeOrTPHOrWildcardOrGeneric type, Expression expr, Statement thenBlock, Statement elseBlock, Token offset) {
|
||||||
|
super(type, offset);
|
||||||
|
this.expr = expr;
|
||||||
|
this.then_block = thenBlock;
|
||||||
|
this.else_block = elseBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.FormalParameter;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.Pattern;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
|
||||||
|
public class InstanceOf extends Expression {
|
||||||
|
private final Pattern pattern;
|
||||||
|
private final Expression expr;
|
||||||
|
|
||||||
|
public InstanceOf(Expression expr, RefTypeOrTPHOrWildcardOrGeneric type, RefTypeOrTPHOrWildcardOrGeneric reftype, Token offset) {
|
||||||
|
super(type, offset);
|
||||||
|
this.pattern = new FormalParameter(null, reftype, offset);
|
||||||
|
this.expr = expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InstanceOf(Expression expr, RefTypeOrTPHOrWildcardOrGeneric type, Pattern pattern, Token offset) {
|
||||||
|
super(type, offset);
|
||||||
|
this.pattern = pattern;
|
||||||
|
this.expr = expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pattern getPattern() {
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression getExpression() {
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public abstract class JavaInternalExpression extends Statement{
|
||||||
|
public JavaInternalExpression(RefTypeOrTPHOrWildcardOrGeneric retType, Token offset){
|
||||||
|
super(retType, offset);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.*;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.Pair;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
//import sun.reflect.generics.reflectiveObjects.NotImplementedException;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class LambdaExpression extends Expression implements TypeScope {
|
||||||
|
public final Block methodBody;
|
||||||
|
public final ParameterList params;
|
||||||
|
|
||||||
|
public LambdaExpression(RefTypeOrTPHOrWildcardOrGeneric type, ParameterList params, Block methodBody, Token offset) {
|
||||||
|
super(type,offset);
|
||||||
|
this.methodBody = methodBody;
|
||||||
|
this.params = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends GenericTypeVar> getGenerics() {
|
||||||
|
//Lambda-Ausdrücke haben keine Generics
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
|
||||||
|
//RefType type = (RefType) this.getType();
|
||||||
|
//return type.getParaList().get(0);
|
||||||
|
return methodBody.getType();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.Expression;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public class Literal extends Expression
|
||||||
|
{
|
||||||
|
public final Object value;
|
||||||
|
|
||||||
|
public Literal(RefTypeOrTPHOrWildcardOrGeneric type, Object value, Token offset) {
|
||||||
|
super(type, offset);
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
public class LocalVar extends Statement {
|
||||||
|
|
||||||
|
public final String name;
|
||||||
|
|
||||||
|
public LocalVar(String n, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||||
|
super(type, offset);
|
||||||
|
this.name = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalVar(Expression e1, RefTypeOrTPHOrWildcardOrGeneric type, String access) {
|
||||||
|
super(type, e1.getOffset());
|
||||||
|
this.name = access;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
|
||||||
|
public class LocalVarDecl extends Statement
|
||||||
|
{
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public LocalVarDecl(String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset)
|
||||||
|
{
|
||||||
|
super(type, offset);
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.exceptions.TypeinferenceException;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.*;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.Pair;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
public class MethodCall extends Statement
|
||||||
|
{
|
||||||
|
public final String name;
|
||||||
|
public final Receiver receiver;
|
||||||
|
|
||||||
|
public final ArgumentList arglist;
|
||||||
|
|
||||||
|
public RefTypeOrTPHOrWildcardOrGeneric receiverType;
|
||||||
|
|
||||||
|
//sind Tphs, repraesentieren im Resultset die Signatur der aufgerufenen Methoden, letztes Element ist der Returntyp
|
||||||
|
public final ArrayList<RefTypeOrTPHOrWildcardOrGeneric> signature;
|
||||||
|
|
||||||
|
public MethodCall(RefTypeOrTPHOrWildcardOrGeneric retType, Receiver receiver, String methodName, ArgumentList argumentList,
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList<RefTypeOrTPHOrWildcardOrGeneric> signature, Token offset){
|
||||||
|
super(retType,offset);
|
||||||
|
this.arglist = argumentList;
|
||||||
|
this.name = methodName;
|
||||||
|
this.receiver = receiver;
|
||||||
|
this.receiverType = receiverType;
|
||||||
|
this.signature = signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RefTypeOrTPHOrWildcardOrGeneric> signatureArguments() {
|
||||||
|
return signature.subList(0, signature.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArgumentList getArgumentList() {
|
||||||
|
return arglist;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree.statement;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||||
|
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||||
|
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||||
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||||
|
|
||||||
|
|
||||||
|
public class NewArray extends Expression
|
||||||
|
{
|
||||||
|
public NewArray(int offset,int variableLength)
|
||||||
|
{
|
||||||
|
super(null,null);
|
||||||
|
}
|
||||||
|
private RefTypeOrTPHOrWildcardOrGeneric type;
|
||||||
|
public List<Expression> expr;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(StatementVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user