Skip to content

[WIP] Type classes #931

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 52 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
0d19d22
first steps towards supporting type classes
peq Dec 31, 2019
51ad081
wip
peq Jan 1, 2020
9086113
Merge branch 'master' into type-classes
peq Jan 3, 2020
e7ddf90
wip
peq Jan 4, 2020
fa23f1f
Revert "wip"
peq Jan 4, 2020
d3813a3
fix
peq Jan 4, 2020
7bd190a
wip
peq Jan 13, 2020
87692a9
Merge branch 'master' into type-classes
peq Jan 18, 2020
0326896
wip
peq Jan 19, 2020
625002e
wip
peq Jan 21, 2020
e679ff5
back to the design with parameters
peq Jan 23, 2020
8d8897c
add parameters for type-class-dicts
peq Jan 25, 2020
f0a2e9a
add type-class arguments
peq Jan 25, 2020
a2fe29b
singleton optimization
peq Jan 25, 2020
2f05cf0
wip
peq Jan 26, 2020
452e603
again changing design
peq Jan 27, 2020
0aa3a36
type class translation
peq Jan 29, 2020
c03c861
some real progress on type classes
peq Jan 29, 2020
b162a4f
fixed optimization
peq Jan 30, 2020
c496f81
find subclass instances
peq Jan 30, 2020
2f200e2
first dependent instances working
peq Jan 30, 2020
3aecaa2
removed debug
peq Jan 31, 2020
dc677ab
change syntax to 'implements' keyword
peq Jan 31, 2020
8ea93e7
first class with constraints
peq Feb 1, 2020
13bfc73
add missing super-visit
peq Feb 1, 2020
500c250
fixed NPE and tests
peq Feb 2, 2020
949a2ce
dependent constraints for classes
peq Feb 2, 2020
895a31f
some memory usage tweaks for travis
peq Feb 2, 2020
5e15802
increase heap size for travis
peq Feb 2, 2020
2bd0928
super-type constraint with dependency
peq Feb 4, 2020
39f8512
iterator example
peq Feb 9, 2020
a278a25
namespacing
peq Feb 9, 2020
ae31eb1
Type Check: All functions implemented correctly
peq Feb 9, 2020
02b06d6
added simple divergence check
peq Feb 9, 2020
464c9b0
basic support for derived ToIndex for object types
peq Feb 9, 2020
08dd207
support for multiple constraints
peq Feb 10, 2020
ca65678
fixed tests
peq Feb 11, 2020
9a45d20
fixed classcast exception
peq Feb 12, 2020
53250f4
default type class for classes
peq Feb 12, 2020
aae43e0
fix 464c9b0
peq Feb 12, 2020
4311d89
prefer overloads without type class constraints
peq Feb 12, 2020
9cc999d
overloading
peq Feb 12, 2020
b20a0b3
fix override check
peq Feb 13, 2020
3c09717
re-enable lua tests
peq Feb 13, 2020
1e263e0
removed any-type
peq Feb 13, 2020
ade9643
remove restriction to certain tests
peq Feb 13, 2020
040b04f
fixed bugs
peq Feb 13, 2020
4937df8
correct handling of public imports
peq Feb 13, 2020
8723ef1
fix lua: protect main
peq Feb 13, 2020
2303938
add correct submethods
peq Feb 14, 2020
1bcc0c1
one more test for subclasses
peq Feb 14, 2020
14bdfd1
fixed bug in for-loop translation (wip)
peq Feb 21, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions de.peeeq.wurstscript/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,9 @@ compileJava.dependsOn gen

test {
// set minimal heap size required to run tests:
jvmArgs = ['-Xms256m']
maxHeapSize = "1G"

useTestNG() {
suites 'src/test/resources/AllTestsSuite.xml'
}
useTestNG()
}

// delete the generated sources on clean
Expand Down
30 changes: 15 additions & 15 deletions de.peeeq.wurstscript/parserspec/jass_im.parseq
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@ ImProg(
ImFunctions functions,
ImMethods methods,
ImClasses classes,
ImTypeClassFuncs typeClassFunctions,
java.util.Map<ImVar, java.util.List<ImExpr>> globalInits)

ImVars * ImVar
ImFunctions * ImFunction
ImClasses * ImClass
ImTypeClassFuncs * ImTypeClassFunc

ImVar(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImType type, String name, boolean isBJ)
ImVar(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImType type, String name,
java.util.List<de.peeeq.wurstscript.translation.imtranslation.VarFlag> varFlags)

ImType =
ImSimpleType(String typename)
Expand All @@ -37,30 +36,28 @@ ImTypeVars * ImTypeVar

ImTypeVar(String name)

ImFunction(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace,
ImFunction(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace,
String name,
ImTypeVars typeVariables,
ImVars parameters,
ImVars parameters,
ref ImType returnType,
ImVars locals,
ImStmts body,
java.util.List<de.peeeq.wurstscript.translation.imtranslation.FunctionFlag> flags)

ImTypeClassFunc(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace,
String name,
ImTypeVars typeVariables,
ImVars parameters,
ref ImType returnType)


ImClass(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace,
String name,
ImTypeVars typeVariables,
ImVars fields,
ImVars fields,
ImMethods methods,
ImFunctions functions,
java.util.List<ImClassType> superClasses)


ImElementWithTypeVars = ImFunction | ImClass

ImMethods * ImMethod

ImMethod(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace,
Expand Down Expand Up @@ -100,10 +97,10 @@ ImExpr =
| ImGetStackTrace()
| ImCompiletimeExpr(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ImExpr expr, int executionOrderIndex)
| ImLExpr
| ImTypeVarDispatch(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImTypeClassFunc typeClassFunc, ImExprs arguments
, ref ImTypeVar typeVariable)
| ImCast(ImExpr expr, ref ImType toType)



// an expression which can be used on the left hand side of an assignment
ImLExpr =
ImVarAccess(ref ImVar var)
Expand All @@ -129,7 +126,7 @@ ImClassRelatedExprWithClass =
| ImInstanceof(ImExpr obj, ref ImClassType clazz)
| ImTypeIdOfObj(ImExpr obj, ref ImClassType clazz)
| ImTypeIdOfClass(ref ImClassType clazz)

| ImTypeClassDictValue(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImClassType clazz, ImExprs arguments)



Expand All @@ -148,7 +145,7 @@ ImConst =

ImTypeArguments * ImTypeArgument

ImTypeArgument(ref ImType type, java.util.Map<ImTypeClassFunc, io.vavr.control.Either<ImMethod, ImFunction>> typeClassBinding)
ImTypeArgument(ref ImType type)

// helper types:

Expand Down Expand Up @@ -380,3 +377,6 @@ ImLExpr.isUsedAsLValue()
returns boolean
implemented by de.peeeq.wurstscript.translation.imtranslation.LValues.isUsedAsLValue

ImVar.isBJ()
returns boolean
implemented by de.peeeq.wurstscript.translation.imtranslation.VarFlag.isBj
34 changes: 31 additions & 3 deletions de.peeeq.wurstscript/parserspec/wurstscript.parseq
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ WEntity =
| ModuleDef(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, Modifiers modifiers, Identifier nameId, TypeParamDefs typeParameters,
ClassDefs innerClasses, FuncDefs methods, GlobalVarDefs vars, ConstructorDefs constructors,
ModuleInstanciations p_moduleInstanciations, ModuleUses moduleUses, OnDestroyDef onDestroy)
| InstanceDecl(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, Modifiers modifiers, TypeParamDefs typeParameters, TypeExpr implementedInterface, FuncDefs methods)



Expand Down Expand Up @@ -117,7 +118,12 @@ TypeParamDefs * TypeParamDef

TypeParamDef(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, Modifiers modifiers, Identifier nameId, TypeParamConstraints typeParamConstraints)

TypeParamConstraints = NoTypeParamConstraints() | TypeExprList
TypeParamConstraints = NoTypeParamConstraints() | TypeParamConstraintList

TypeParamConstraintList * TypeParamConstraint

TypeParamConstraint(TypeExpr constraint)



WParameters * WParameter
Expand Down Expand Up @@ -282,6 +288,7 @@ WScope =
| WBlock
| WEntities
| ExprClosure
| InstanceDecl

PackageOrGlobal = WPackage | CompilationUnit

Expand Down Expand Up @@ -310,7 +317,7 @@ Modifier =

// ElementWithBody = FunctionImplementation | InitBlock | ConstructorDef | OnDestroyDef
//ElementWithModifier = NameDef | TypeDef | ModuleDef | ConstructorDef | GlobalVarDef | FunctionDefinition
HasModifier = NameDef | TypeDef | ModuleDef | ConstructorDef | GlobalVarDef | FunctionDefinition
HasModifier = NameDef | TypeDef | ModuleDef | ConstructorDef | GlobalVarDef | FunctionDefinition | InstanceDecl
HasTypeArgs = ExprNewObject | FunctionCall | ModuleUse | StmtCall | TypeExprSimple

AstElementWithFuncName = ExprFunctionCall | ExprMemberMethod | ExprFuncRefc
Expand All @@ -323,7 +330,7 @@ AstElementWithNameId = WPackage | NativeFunc | ModuleDef | TypeDef | ModuleInsta

AstElementWithParameters = FunctionDefinition | ExtensionFuncDef | NativeFunc | TupleDef | ConstructorDef | FuncDef

AstElementWithTypeParameters = ExtensionFuncDef | ModuleDef | ClassDef | InterfaceDef | FuncDef
AstElementWithTypeParameters = ExtensionFuncDef | ModuleDef | ClassOrInterfaceOrInstance | FuncDef

AstElementWithArgs = StmtCall | ExprFunctionCall | ExprNewObject | ExprMemberMethod

Expand All @@ -350,6 +357,8 @@ StructureDef = ClassOrModuleOrModuleInstanciation | ClassOrInterface

ClassOrInterface = ClassDef | InterfaceDef

ClassOrInterfaceOrInstance = ClassOrInterface | InstanceDecl

ClassOrModuleInstanciation = ClassDef | ModuleInstanciation
ClassOrModuleOrModuleInstanciation = ClassOrModule | ClassOrModuleInstanciation

Expand Down Expand Up @@ -506,6 +515,14 @@ Element.attrNearestScope()
returns @Nullable WScope
implemented by de.peeeq.wurstscript.attributes.AttrNearest.nearestScope

TypeParamConstraint.parentTypeParam()
returns TypeParamDef
implemented by de.peeeq.wurstscript.attributes.AttrNearest.parentTypeParam

TypeParamConstraint.attrConstraintTyp()
returns de.peeeq.wurstscript.types.WurstType
implemented by de.peeeq.wurstscript.attributes.AttrTypeExprType.constraintType

WScope.attrNextScope "returns the scope surrounding this scope"
returns @Nullable WScope
implemented by de.peeeq.wurstscript.attributes.AttrNearest.nextScope
Expand All @@ -527,6 +544,10 @@ Element.attrNearestClassOrInterface()
returns @Nullable ClassOrInterface
implemented by de.peeeq.wurstscript.attributes.AttrNearest.nearestClassOrInterface

Element.attrNearestClassOrInterfaceOrInstance()
returns @Nullable ClassOrInterfaceOrInstance
implemented by de.peeeq.wurstscript.attributes.AttrNearest.attrNearestClassOrInterfaceOrInstance

Element.attrNearestClassOrModule()
returns @Nullable ClassOrModule
implemented by de.peeeq.wurstscript.attributes.AttrNearest.nearestClassOrModule
Expand Down Expand Up @@ -893,6 +914,13 @@ WPackage.attrExportedTypeNameLinks
returns com.google.common.collect.ImmutableMultimap<String, de.peeeq.wurstscript.attributes.names.TypeLink>
implemented by de.peeeq.wurstscript.attributes.names.Exports.exportedTypeNameLinks

WPackage.attrTypeClasses
returns java.util.List<InstanceDecl>
implemented by de.peeeq.wurstscript.TypeClasses.availableTypeClasses

WPackage.attrDefinedTypeClasses
returns java.util.List<InstanceDecl>
implemented by de.peeeq.wurstscript.TypeClasses.definedTypeClasses

Element.lookupType(String name, boolean showErrors)
returns @Nullable TypeDef
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

grammar Wurst;

@header {
Expand Down Expand Up @@ -112,8 +113,16 @@ entity:
| interfaceDef
| tupleDef
| extensionFuncDef
| instanceDeclaration
;

instanceDeclaration:
modifiersWithDoc 'implements' implemented=typeExpr ('for' (params+=typeParam (',' params+=typeParam)*))?
NL (STARTBLOCK
funcDef*
ENDBLOCK)?
;

interfaceDef:
modifiersWithDoc 'interface' name=ID typeParams
('extends' extended+=typeExpr (',' extended+=typeExpr)*)?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ private void executeCompiletimeExpr(ImCompiletimeExpr cte) {
public ImVar initFor(ILconstObject obj) {


ImVar res = JassIm.ImVar(obj.getTrace(), obj.getType(), obj.getType() + "_compiletime", false);
ImVar res = JassIm.ImVar(obj.getTrace(), obj.getType(), obj.getType() + "_compiletime", Collections.emptyList());
imProg.getGlobals().add(res);
ImAlloc alloc = JassIm.ImAlloc(obj.getTrace(), obj.getType());
addCompiletimeStateInitAlloc(alloc.getTrace(), res, alloc);
Expand Down Expand Up @@ -281,7 +281,7 @@ public ImVar initFor(IlConstHandle a) {
@SuppressWarnings("unchecked")
ArrayListMultimap<HashtableProvider.KeyPair, Object> map = (ArrayListMultimap<HashtableProvider.KeyPair, Object>) obj;
ImType type = TypesHelper.imHashTable();
ImVar res = JassIm.ImVar(trace, type, type + "_compiletime", false);
ImVar res = JassIm.ImVar(trace, type, type + "_compiletime", Collections.emptyList());
imProg.getGlobals().add(res);

init = constantToExprHashtable(trace, res, a, map);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ private void resolveImport(Function<File, CompilationUnit> addCompilationUnit, S
private CompilationUnit loadLibPackage(Function<File, CompilationUnit> addCompilationUnit, String imp) {
File file = getLibs().get(imp);
if (file == null) {
gui.sendError(new CompileError(new WPos("", null, 0, 0), "Could not find lib-package " + imp + ". Are you missing your wurst.dependencies file?"));
gui.sendError(new CompileError(WPos.noSource(), "Could not find lib-package " + imp + ". Are you missing your wurst.dependencies file?"));
return Ast.CompilationUnit(new CompilationUnitInfo(errorHandler), Ast.JassToplevelDeclarations(), Ast.WPackages());
} else {
return addCompilationUnit.apply(file);
Expand Down Expand Up @@ -410,10 +410,22 @@ public JassProg transformProgToJass() {
beginPhase(2, "Eliminate generics");
new EliminateGenerics(imTranslator2, imProg2).transform();
printDebugImProg("./test-output/im " + stage++ + "_genericsEliminated.im");
if (!runArgs.isLua()) {
try {
EliminateTypeClasses.transform(imTranslator2);
} finally {
printDebugImProg("./test-output/at_crash.im");
}
}
printDebugImProg("./test-output/im " + stage++ + "_typeClassesEliminated.im");


// eliminate classes
beginPhase(2, "translate classes");

ClassesOptimizer.optimizeProg(imTranslator2);
printDebugImProg("./test-output/im " + stage++ + "_classes_optimized.im");

new EliminateClasses(imTranslator2, imProg2, !runArgs.isUncheckedDispatch()).eliminateClasses();
imTranslator2.assertProperties();
printDebugImProg("./test-output/im " + stage++ + "_classesEliminated.im");
Expand Down Expand Up @@ -543,7 +555,7 @@ private void addJassHotCodeReloadCode() {
ImFunction jhcr_reload = JassIm.ImFunction(trace, "jhcr_reload_on_escape", JassIm.ImTypeVars(), JassIm.ImVars(), JassIm.ImVoid(), JassIm.ImVars(), reloadBody, Collections.emptyList());


ImVar trig = JassIm.ImVar(trace, TypesHelper.imTrigger(), "trig", false);
ImVar trig = JassIm.ImVar(trace, TypesHelper.imTrigger(), "trig", Collections.emptyList());
mainFunc.getLocals().add(trig);
// TriggerRegisterPlayerEventEndCinematic(trig, Player(0))
stmts.add(JassIm.ImSet(trace, JassIm.ImVarAccess(trig), callExtern(trace, CallType.NORMAL, "CreateTrigger")));
Expand Down Expand Up @@ -611,6 +623,8 @@ private void printDebugImProg(String debugFile) {
} catch (IOException e) {
ErrorReporting.instance.handleSevere(e, getCompleteSourcecode());
}
// basic sanity check
getImTranslator().assertProperties(AssertProperty.rooted(getImProg()));
}

private WurstModel mergeCompilationUnits(List<CompilationUnit> compilationUnits) {
Expand Down Expand Up @@ -817,4 +831,12 @@ public LuaCompilationUnit transformProgToLua() {
LuaCompilationUnit luaCode = luaTranslator.translate();
return luaCode;
}

/**
* Clears the intermediate output programs to allow collection by garbage collector
*/
public void clear() {
imProg = null;
prog = null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ public void case_TupleDef(TupleDef tupleDef) {
add(tupleDef.getName(), SymbolKind.Class);
}

@Override
public void case_InstanceDecl(InstanceDecl instanceDecl) {
// ignore
}

@Override
public void case_FuncDef(FuncDef funcDef) {
SymbolKind kind = funcDef.attrIsDynamicClassMember() ? SymbolKind.Method : SymbolKind.Function;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,11 @@ public List<Either<String, MarkedString>> case_ExprNull(ExprNull exprNull) {
return string("The null-reference");
}

@Override
public List<Either<String, MarkedString>> case_TypeParamConstraintList(TypeParamConstraintList typeParamConstraintList) {
return string("Type parameter constraints define type classes that must be implemented for type parameters.");
}

@Override
public List<Either<String, MarkedString>> case_ClassDefs(ClassDefs classDefs) {
return string("A list of class definitions.");
Expand Down Expand Up @@ -736,6 +741,11 @@ public List<Either<String, MarkedString>> case_ExprIfElse(ExprIfElse exprIfElse)
return string("A conditional expression (condition ? ifTrue : ifFalse).");
}

@Override
public List<Either<String, MarkedString>> case_TypeParamConstraint(TypeParamConstraint t) {
return string(t.description());
}

@Override
public List<Either<String, MarkedString>> case_WurstDoc(WurstDoc wurstDoc) {
return wurstDoc.getParent().match(this);
Expand Down Expand Up @@ -766,6 +776,11 @@ public List<Either<String, MarkedString>> case_ModVararg(ModVararg modVararg) {
return string("Declares the parameter to be a array of variable length");
}

@Override
public List<Either<String, MarkedString>> case_InstanceDecl(InstanceDecl instanceDecl) {
return string("An instance declaration for the type-class " + instanceDecl.getImplementedInterface().attrTyp());
}

@Override
public List<Either<String, MarkedString>> case_TypeExprResolved(TypeExprResolved typeExprResolved) {
return typeExpr(typeExprResolved);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ public void case_TupleDef(TupleDef tupleDef) {
add(tupleDef.getName(), SymbolKind.Class);
}

@Override
public void case_InstanceDecl(InstanceDecl instanceDecl) {
// ignore
}

@Override
public void case_FuncDef(FuncDef funcDef) {
SymbolKind kind = funcDef.attrIsDynamicClassMember() ? SymbolKind.Method : SymbolKind.Function;
Expand Down
Loading