From 85cfa922ca21d86a26bf5d9f3fe323d94614e7c5 Mon Sep 17 00:00:00 2001 From: Peter Zeller Date: Mon, 6 Sep 2021 00:38:24 +0200 Subject: [PATCH 1/2] starting with two phase checking: defining symbols --- .../validation/symbols/FunctionSymbol.java | 4 + .../validation/symbols/PackagePath.java | 37 +++++++ .../validation/symbols/SymbolTable.java | 32 ++++++ .../validation/symbols/TypeName.java | 37 +++++++ .../validation/symbols/TypeSymbol.java | 102 ++++++++++++++++++ .../validation/symbols/VarSymbol.java | 4 + 6 files changed, 216 insertions(+) create mode 100644 de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/FunctionSymbol.java create mode 100644 de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/PackagePath.java create mode 100644 de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/SymbolTable.java create mode 100644 de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeName.java create mode 100644 de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeSymbol.java create mode 100644 de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/VarSymbol.java diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/FunctionSymbol.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/FunctionSymbol.java new file mode 100644 index 000000000..d2334cfb7 --- /dev/null +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/FunctionSymbol.java @@ -0,0 +1,4 @@ +package de.peeeq.wurstscript.validation.symbols; + +public class FunctionSymbol { +} diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/PackagePath.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/PackagePath.java new file mode 100644 index 000000000..9824f3df9 --- /dev/null +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/PackagePath.java @@ -0,0 +1,37 @@ +package de.peeeq.wurstscript.validation.symbols; + +import com.google.common.collect.ImmutableList; + +import java.util.Objects; + +public final class PackagePath { + private final ImmutableList path; + + public PackagePath(ImmutableList path) { + this.path = path; + } + + public ImmutableList path() { + return path; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + PackagePath that = (PackagePath) obj; + return Objects.equals(this.path, that.path); + } + + @Override + public int hashCode() { + return Objects.hash(path); + } + + @Override + public String toString() { + return "PackagePath[" + + "path=" + path + ']'; + } + +} diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/SymbolTable.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/SymbolTable.java new file mode 100644 index 000000000..7eb31d215 --- /dev/null +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/SymbolTable.java @@ -0,0 +1,32 @@ +package de.peeeq.wurstscript.validation.symbols; + +import com.google.common.collect.Multimap; + +import java.util.Map; + +/** + * A symbol table for a compilation unit + */ +public class SymbolTable { + private final Map types; + private final Multimap functions; + private final Map vars; + + public SymbolTable(Map types, Multimap functions, Map vars) { + this.types = types; + this.functions = functions; + this.vars = vars; + } + + public Map getTypes() { + return types; + } + + public Multimap getFunctions() { + return functions; + } + + public Map getVars() { + return vars; + } +} diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeName.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeName.java new file mode 100644 index 000000000..31f9f6dd4 --- /dev/null +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeName.java @@ -0,0 +1,37 @@ +package de.peeeq.wurstscript.validation.symbols; + +import com.google.common.collect.ImmutableList; + +import java.util.Objects; + +public final class TypeName { + private final ImmutableList path; + + public TypeName(ImmutableList path) { + this.path = path; + } + + public ImmutableList path() { + return path; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + TypeName that = (TypeName) obj; + return Objects.equals(this.path, that.path); + } + + @Override + public int hashCode() { + return Objects.hash(path); + } + + @Override + public String toString() { + return "TypeName[" + + "path=" + path + ']'; + } + +} diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeSymbol.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeSymbol.java new file mode 100644 index 000000000..175912bdb --- /dev/null +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeSymbol.java @@ -0,0 +1,102 @@ +package de.peeeq.wurstscript.validation.symbols; + +import com.google.common.collect.ImmutableList; + +import java.util.Objects; + +public interface TypeSymbol { + + + final class ScopedType implements TypeSymbol { + private final boolean isStatic; + private final PackagePath path; + private final TypeName name; + private final ImmutableList typeArgs; + + public ScopedType(boolean isStatic, PackagePath path, TypeName name, ImmutableList typeArgs) { + this.isStatic = isStatic; + this.path = path; + this.name = name; + this.typeArgs = typeArgs; + } + + public PackagePath path() { + return path; + } + + public TypeName name() { + return name; + } + + public ImmutableList typeArgs() { + return typeArgs; + } + + public boolean isStatic() { + return isStatic; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + ScopedType that = (ScopedType) obj; + return this.isStatic == that.isStatic && + Objects.equals(this.path, that.path) && + Objects.equals(this.name, that.name) && + Objects.equals(this.typeArgs, that.typeArgs); + } + + @Override + public int hashCode() { + return Objects.hash(isStatic, path, name, typeArgs); + } + + @Override + public String toString() { + return "ScopedType[" + + "path=" + path + ", " + + "name=" + name + ", " + + "typeArgs=" + typeArgs + ']'; + } + + + } + + final class TypeParamRef implements TypeSymbol { + private final String name; + + public TypeParamRef(String name) { + this.name = name; + } + + public String name() { + return name; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + TypeParamRef that = (TypeParamRef) obj; + return Objects.equals(this.name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } + + @Override + public String toString() { + return "TypeParamRef[" + + "name=" + name + ']'; + } + + + } + + + + +} diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/VarSymbol.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/VarSymbol.java new file mode 100644 index 000000000..a10f6dd87 --- /dev/null +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/VarSymbol.java @@ -0,0 +1,4 @@ +package de.peeeq.wurstscript.validation.symbols; + +public class VarSymbol { +} From ef726f3cb01ea4e93845e1d846103f4c63dedbaa Mon Sep 17 00:00:00 2001 From: Peter Zeller Date: Fri, 17 Sep 2021 21:36:13 +0200 Subject: [PATCH 2/2] wip --- .../validation/symbols/FunctionSymbol.java | 106 +++++++++++++++ .../validation/symbols/PackagePath.java | 4 + .../symbols/PackageSymbolTable.java | 49 +++++++ .../validation/symbols/SymbolTable.java | 32 ----- .../symbols/SymbolTableCreation.java | 121 ++++++++++++++++++ .../validation/symbols/TypeDefSymbol.java | 48 +++++++ .../validation/symbols/TypeName.java | 5 + .../validation/symbols/TypeSymbol.java | 7 + .../validation/symbols/VarSymbol.java | 7 + 9 files changed, 347 insertions(+), 32 deletions(-) create mode 100644 de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/PackageSymbolTable.java delete mode 100644 de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/SymbolTable.java create mode 100644 de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/SymbolTableCreation.java create mode 100644 de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeDefSymbol.java diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/FunctionSymbol.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/FunctionSymbol.java index d2334cfb7..ab0a2afc2 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/FunctionSymbol.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/FunctionSymbol.java @@ -1,4 +1,110 @@ package de.peeeq.wurstscript.validation.symbols; +import java.util.List; +import java.util.Objects; + public class FunctionSymbol { + private final List typeVarNames; + private final String name; + private final ParameterInfo parameters; + private final TypeSymbol returnType; + + public FunctionSymbol(List typeVarNames, String name, ParameterInfo parameters, TypeSymbol returnType) { + this.typeVarNames = typeVarNames; + this.name = name; + this.parameters = parameters; + this.returnType = returnType; + } + + public List getTypeVarNames() { + return typeVarNames; + } + + public String getName() { + return name; + } + + public ParameterInfo getParameters() { + return parameters; + } + + public TypeSymbol getReturnType() { + return returnType; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + FunctionSymbol that = (FunctionSymbol) o; + return Objects.equals(typeVarNames, that.typeVarNames) && Objects.equals(name, that.name) && Objects.equals(parameters, that.parameters) && Objects.equals(returnType, that.returnType); + } + + @Override + public int hashCode() { + return Objects.hash(typeVarNames, name, parameters, returnType); + } + + static class ParameterInfo { + private final boolean isVararg; + private final List parameters; + + public ParameterInfo(boolean isVararg, List parameters) { + this.isVararg = isVararg; + this.parameters = parameters; + } + + public boolean isVararg() { + return isVararg; + } + + public List getParameters() { + return parameters; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ParameterInfo that = (ParameterInfo) o; + return isVararg == that.isVararg && Objects.equals(parameters, that.parameters); + } + + @Override + public int hashCode() { + return Objects.hash(isVararg, parameters); + } + + static class Param { + private final TypeSymbol type; + private final String name; + + public Param(TypeSymbol type, String name) { + this.type = type; + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Param param = (Param) o; + return Objects.equals(type, param.type) && Objects.equals(name, param.name); + } + + @Override + public int hashCode() { + return Objects.hash(type, name); + } + + public TypeSymbol getType() { + return type; + } + + public String getName() { + return name; + } + } + } + } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/PackagePath.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/PackagePath.java index 9824f3df9..abc97d581 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/PackagePath.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/PackagePath.java @@ -11,6 +11,10 @@ public PackagePath(ImmutableList path) { this.path = path; } + public PackagePath(String ... path) { + this(ImmutableList.copyOf(path)); + } + public ImmutableList path() { return path; } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/PackageSymbolTable.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/PackageSymbolTable.java new file mode 100644 index 000000000..4246447f9 --- /dev/null +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/PackageSymbolTable.java @@ -0,0 +1,49 @@ +package de.peeeq.wurstscript.validation.symbols; + +import com.google.common.collect.Multimap; + +import java.util.Map; + +/** + * A symbol table for a compilation unit + * + * A Wurst module can export the following elements: + * + * - Types + * - Tuples + * - Classes + * - Interfaces + * - Modules + * - Variables + * - Functions + * + */ +public class PackageSymbolTable { + private final PackagePath packageName; + private final Map types; + private final Multimap functions; + private final Map vars; + + public PackageSymbolTable(PackagePath packageName, Map types, Multimap functions, Map vars) { + this.packageName = packageName; + this.types = types; + this.functions = functions; + this.vars = vars; + } + + public PackagePath getPackageName() { + return packageName; + } + + public Map getTypes() { + return types; + } + + public Multimap getFunctions() { + return functions; + } + + public Map getVars() { + return vars; + } +} diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/SymbolTable.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/SymbolTable.java deleted file mode 100644 index 7eb31d215..000000000 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/SymbolTable.java +++ /dev/null @@ -1,32 +0,0 @@ -package de.peeeq.wurstscript.validation.symbols; - -import com.google.common.collect.Multimap; - -import java.util.Map; - -/** - * A symbol table for a compilation unit - */ -public class SymbolTable { - private final Map types; - private final Multimap functions; - private final Map vars; - - public SymbolTable(Map types, Multimap functions, Map vars) { - this.types = types; - this.functions = functions; - this.vars = vars; - } - - public Map getTypes() { - return types; - } - - public Multimap getFunctions() { - return functions; - } - - public Map getVars() { - return vars; - } -} diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/SymbolTableCreation.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/SymbolTableCreation.java new file mode 100644 index 000000000..7fb516537 --- /dev/null +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/SymbolTableCreation.java @@ -0,0 +1,121 @@ +package de.peeeq.wurstscript.validation.symbols; + + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Multimap; +import de.peeeq.wurstscript.ast.*; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * We create symbol tables in two phases: + *

+ * 1. We parse each compilation unit independently. + * 2. We resolve type symbols + */ +public class SymbolTableCreation { + + + public static ImmutableList getSymbols(CompilationUnit cu) { + ImmutableList.Builder result = ImmutableList.builder(); + for (WPackage p : cu.getPackages()) { + result.add(getPackageSymbols(p)); + } + if (!cu.getJassDecls().isEmpty()) { + result.add(getToplevelSymbols(cu.getJassDecls())); + } + return result.build(); + } + + private static PackageSymbolTable getToplevelSymbols(JassToplevelDeclarations jassDecls) { + Map types = new LinkedHashMap<>(); + Multimap functions = HashMultimap.create(); + Map vars = new LinkedHashMap<>(); + PackagePath packageName = new PackagePath(); + + for (JassToplevelDeclaration jassDecl : jassDecls) { + jassDecl.match(new JassToplevelDeclaration.MatcherVoid() { + @Override + public void case_JassGlobalBlock(JassGlobalBlock jassGlobalBlock) { + for (GlobalVarDef g : jassGlobalBlock) { + vars.put(g.getName(), new VarSymbol(g.getName(), parseType(g.getOptTyp()))); + } + } + + @Override + public void case_NativeFunc(NativeFunc nativeFunc) { + functions.put(nativeFunc.getName(), parseFunctionSymbol(nativeFunc.getName(), nativeFunc.getParameters(), nativeFunc.getReturnTyp())); + } + + @Override + public void case_FuncDef(FuncDef funcDef) { + functions.put(funcDef.getName(), parseFunctionSymbol(funcDef.getName(), funcDef.getParameters(), funcDef.getReturnTyp())); + } + + @Override + public void case_NativeType(NativeType nativeType) { + addNativeType(nativeType, types, packageName); + } + + @Override + public void case_TupleDef(TupleDef tupleDef) { + addTupleDef(tupleDef, types, packageName); + } + }); + } + + + return new PackageSymbolTable(packageName, types, functions, vars); + } + + private static void addNativeType(NativeType nativeType, Map types, PackagePath packageName) { + List superTypes; + if (nativeType.getOptTyp() instanceof TypeExpr) { + superTypes = ImmutableList.of(parseType(nativeType.getOptTyp())); + } else { + superTypes = ImmutableList.of(); + } + + TypeName typeName = new TypeName(nativeType.getName()); + types.put(typeName, new TypeDefSymbol( + ImmutableList.of(), + new TypeSymbol.ScopedType(true, packageName, typeName, ImmutableList.of()), + superTypes, + ImmutableList.of() + )); + } + + private static void addTupleDef(TupleDef tupleDef, Map types, PackagePath packageName) { + TypeName typeName = new TypeName(tupleDef.getName()); + List superTypes = ImmutableList.of(); + types.put(typeName, new TypeDefSymbol( + ImmutableList.of(), + new TypeSymbol.ScopedType(true, packageName, typeName, ImmutableList.of()), + superTypes, + ImmutableList.of() + )); + } + + private static FunctionSymbol parseFunctionSymbol(String name, WParameters parameters, OptTypeExpr returnTyp) { + return null; + } + + private static FunctionSymbol parseFunctionSymbol(NativeFunc nativeFunc) { + return null; + } + + private static TypeSymbol parseType(OptTypeExpr optTyp) { + return null; + } + + private static PackageSymbolTable getPackageSymbols(WPackage p) { + + return null; + } + + +} diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeDefSymbol.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeDefSymbol.java new file mode 100644 index 000000000..fbd2c8350 --- /dev/null +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeDefSymbol.java @@ -0,0 +1,48 @@ +package de.peeeq.wurstscript.validation.symbols; + +import java.util.List; +import java.util.Objects; + +public class TypeDefSymbol { + private final List typeParameters; + private final TypeSymbol symbol; + private final List superTypes; + private final List usedModules; + + public TypeDefSymbol(List typeParameters, TypeSymbol symbol, List superTypes, List usedModules) { + this.typeParameters = typeParameters; + this.symbol = symbol; + this.superTypes = superTypes; + this.usedModules = usedModules; + } + + public List getTypeParameters() { + return typeParameters; + } + + public TypeSymbol getSymbol() { + return symbol; + } + + public List getSuperTypes() { + return superTypes; + } + + public List getUsedModules() { + return usedModules; + } + + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TypeDefSymbol that = (TypeDefSymbol) o; + return typeParameters.equals(that.typeParameters) && symbol.equals(that.symbol) && superTypes.equals(that.superTypes) && usedModules.equals(that.usedModules); + } + + @Override + public int hashCode() { + return Objects.hash(typeParameters, symbol, superTypes, usedModules); + } +} diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeName.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeName.java index 31f9f6dd4..fab1c7c87 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeName.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeName.java @@ -4,9 +4,14 @@ import java.util.Objects; +/** Type name inside a package (singleton list unless it is a nested class) */ public final class TypeName { private final ImmutableList path; + public TypeName(String path) { + this(ImmutableList.of(path)); + } + public TypeName(ImmutableList path) { this.path = path; } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeSymbol.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeSymbol.java index 175912bdb..c58e2bd33 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeSymbol.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/TypeSymbol.java @@ -2,6 +2,7 @@ import com.google.common.collect.ImmutableList; +import java.lang.reflect.Type; import java.util.Objects; public interface TypeSymbol { @@ -98,5 +99,11 @@ public String toString() { + /** Return type for a function that returns nothing. */ + TypeSymbol Nothing = new TypeSymbol() {}; + + /** Special type for errors */ + TypeSymbol Any = new TypeSymbol() {}; + } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/VarSymbol.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/VarSymbol.java index a10f6dd87..9ffb6a5ba 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/VarSymbol.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/symbols/VarSymbol.java @@ -1,4 +1,11 @@ package de.peeeq.wurstscript.validation.symbols; public class VarSymbol { + private final String name; + private final TypeSymbol symbol; + + public VarSymbol(String name, TypeSymbol symbol) { + this.name = name; + this.symbol = symbol; + } }