Closed alexnask closed 8 years ago
Will eventually close #830
I will probably end up doing a pretty huge rewrite of typearg-related code.
Will split up TypeArg access/definition into their own types, with a Generic/Template enum, all index based and replace accesses with TypeArgAccesses.
Anyway, this may take some time but I'm confident it will be nice to have in the long run.
Goodie! I'm looking forward to this one!
Here is the structure I am thinking about (keep in mind it is way too early to tell if this is refined enough):
TypeArgType: enum {
Generic, Template, Unknwon
}
TypeArg: class {
index: Int
type: TypeArgType
init: func (=index, =type)
}
TypeArgDecl: class {
originalName: String // only used in codegen
typeArg: TypeArg
init: func (=originalName, =typeArg) // Unknown type triggers an internal compiler error, we should never get one
}
TypeArgInstance: class {
typeArg: TypeArg
type: Type
ref: TypeArgDecl // We get this by resolving the Node, like always
init: func (index: Int, =type) {
// We also get the typeArg type by resolving
typeArg = TypeArg new(index, TypeArgType Unknown)
}
}
TypeArgMap: class extends HashMap<String, TypeArg> {
// helper methods etc.
}
TypeArgAccess: class {
name: String
ref: TypeArgDecl // Get this by resolving
init: func (=name)
}
TypeDecls and FunctionDecls have their List of TypeArgDecls Types have their List of TypeArgInstances Addons have a TypeArgMap TypeDecls have a TypeArgMap for their super type or from type
To resolve TypeArgAccesses, we go up the trail calling resolveTypeArg (like we do with calls, accesses and types) until we get a candidate that fits.
Types and VariableAccesses can somehow (TM) be replaced by TypeArgAccesses.
Will probably start writing code and experimenting later today.
EDIT: All development will be done one my new_typeargs branch.
This seems to work well!
Will be adding a couple of tests and opening up a PR for magic-lang too soon.
Nice! :+1:
Extending template classes also works by the way (it's pretty nice since you can simulate specialization):
TCell: class template <T> {
value: T
init: func (=value)
}
extend TCell<Int> {
magic: func {
value toString() println()
}
}
extend TCell<String> {
magic: func {
value println()
}
}
cell1 := TCell<Int> new(42)
cell2 := TCell<String> new("Hello World!")
cell1 magic()
cell2 magic()
Also, mixed extensions!
Foo: class <T> template <U> {
val1: T
val2: U
init: func (=val1, =val2)
}
extend Foo<U, String> {
print: func {
"#{val1 as Pointer}: #{val2}" println()
}
}
// Works!
foo := Foo<Int, String> new(42, "Hello World!")
foo print()
// Fails, as it should
bar := Foo<Int, Int> new(0, 42)
bar print()
amazing! :+1:
This is a really huge change, there are probably some bugs but they should be mostly the kind of things that you come across if you intentionally try to do really weird things.
A rewrite of the whole TypeArg system is still probably needed at this point though.
There are a couple of known issues I will be fixing (just leaving the PR up for updates):
Other than that, it seems to be solid enough.