update files to match newest version

This commit is contained in:
julian 2024-03-16 17:16:23 +01:00
parent 518a09b00f
commit 5bee05ac43
366 changed files with 30150 additions and 369 deletions

View File

@ -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
;

View File

@ -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? ')'
;

View 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);
}
}

View File

@ -0,0 +1,7 @@
package de.dhbwstuttgart.bytecode;
public class CodeGenException extends RuntimeException {
public CodeGenException(String cause) {
super(cause);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,9 @@
package de.dhbwstuttgart.core;
import org.antlr.v4.runtime.Token;
public interface IItemWithOffset
{
Token getOffset();
}

View File

@ -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());
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -0,0 +1,8 @@
package de.dhbwstuttgart.exceptions;
public class DebugException extends RuntimeException {
public DebugException(String message) {
System.err.print(message);
}
}

View File

@ -0,0 +1,11 @@
package de.dhbwstuttgart.exceptions;
public class NotImplementedException extends RuntimeException {
public NotImplementedException() {
}
public NotImplementedException(String string) {
super(string);
}
}

View File

@ -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);
}
}

View File

@ -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 ¤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;
}
}

View File

@ -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))); }
*/
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}
}

View File

@ -0,0 +1,6 @@
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
public record FieldEntry(String name, RefTypeOrTPHOrWildcardOrGeneric type, int modifiers) {
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,5 @@
= Grammatik =
* Core-Problem: Typinferenz vs. Konstruktoren
* möglicherweise Problem: falsche Return-Expressions

View File

@ -9,6 +9,8 @@ import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.misc.*;
import java.lang.Integer;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue"})
public class Java17Lexer extends Lexer {
static { RuntimeMetaData.checkVersion("4.11.1", RuntimeMetaData.VERSION); }

View File

@ -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)

View File

@ -0,0 +1,3 @@
* fieldDeclarations
* Imports
* (Q)Generics

View File

@ -0,0 +1,2 @@
* Ablegen der Type Parameter: kompletter Name?
* Typen (unannType etc.)

View File

@ -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?

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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 ¼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;
}
}

View File

@ -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));
}
}

View File

@ -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);
}

View File

@ -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) {
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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(); }
*/
}

View File

@ -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 ¯Â¿Â½r eine neue
* <code>TypePlaceholder</code>. <br>Author: ¯Â¿Â½rg ¯Â¿Â½uerle
* @return Der Name
*/
public static String makeNewName()
{
// otth: Funktion berechnet einen neuen Namen anhand eines alten gespeicherten
String strReturn = strNextName;
// ¯Â¿Â½chster Name berechnen und in strNextName speichern
inc( strNextName.length() - 1 );
return strReturn;
}
/**
* Hilfsfunktion zur Berechnung eines neuen Namens
* <br>Author: ¯Â¿Â½rg ¯Â¿Â½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: ¯Â¿Â½rg ¯Â¿Â½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;
}
}

View File

@ -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 {
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,42 @@
package de.dhbwstuttgart.syntaxtree.statement;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import de.dhbwstuttgart.exceptions.TypeinferenceException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption;
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 de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import org.antlr.v4.runtime.Token;
import de.dhbwstuttgart.exceptions.NotImplementedException;
public class NewClass extends MethodCall
{
/**
*
* @param newClass Typ der Instanzierten Klasse
* @param args Argumente mit denen der New-Call aufgerufen wurde
* @param start
*/
public NewClass(RefType newClass, ArgumentList args, RefTypeOrTPHOrWildcardOrGeneric receiverType,
ArrayList<RefTypeOrTPHOrWildcardOrGeneric> argTypes, Token start) {
super(newClass, new ExpressionReceiver(new EmptyStmt(start)), newClass.getName().toString(),
args, receiverType, argTypes, start);
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@ -0,0 +1,12 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
public abstract class Receiver extends Expression
{
public Receiver(RefTypeOrTPHOrWildcardOrGeneric type, Token offset)
{
super(type, offset);
}
}

View File

@ -0,0 +1,18 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import org.antlr.v4.runtime.Token;
public class Return extends Statement {
public final Expression retexpr;
public Return(Expression retExpr, Token offset) {
super(retExpr.getType(), offset);
this.retexpr = retExpr;
}
@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