Skip to content

Commit

Permalink
Created InstanceGeneric Types. This now allows : Generic<T, ..>
Browse files Browse the repository at this point in the history
  • Loading branch information
tlaceby committed Apr 14, 2024
1 parent 897ec44 commit b61d84a
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 33 deletions.
18 changes: 18 additions & 0 deletions examples/test.br
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ struct Combinable<T> {
fn setData(data: T) {
self.data = data;
}

fn combine(other: T) {
self.data = self.data + other;
}
}

const c1 = Combinable <number> {
Expand All @@ -14,3 +18,17 @@ const c1 = Combinable <number> {


c1.data = 1;

let c2: Combinable<number>;
c2 = Combinable<number>{
data: 1.2,
};

c2.data = c1.data;

const c3 = Combinable<string> {
data: "Hello",
};

c3.setData("Hello ");
c3.combine("world");
7 changes: 6 additions & 1 deletion src/analysis/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ func (table *SymbolTable) debugTable(printParent bool) {
println("\nstructs:")
for typename, typevalue := range table.DefinedTypes {
if helpers.TypesMatchT[StructType](typevalue) {
println(fmt.Sprintf(" %s: ", typename))
println(fmt.Sprintf(" %s ", typename))

structVal := helpers.ExpectType[StructType](typevalue)

Expand All @@ -220,6 +220,11 @@ func (table *SymbolTable) debugTable(printParent bool) {
}
}
}

if helpers.TypesMatchT[GenericStructType](typevalue) {
structVal := helpers.ExpectType[GenericStructType](typevalue)
fmt.Printf(" %s\n", structVal.str())
}
}

println("\nsymbols:")
Expand Down
14 changes: 14 additions & 0 deletions src/analysis/helpers.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
package analysis

func createGenericListStr(structName string, generics []string) string {
str := structName + "<"

for indx, name := range generics {
str += name
if indx != len(generics)-1 {
str += ", "
}
}

str += ">"
return str
}

func typesSame(t Type, expected Type) bool {
return t.str() == expected.str()

Expand Down
9 changes: 5 additions & 4 deletions src/analysis/tc_exprs.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,26 @@ func tc_struct_instantation_expr(e ast.StructInstantiationExpr, env *SymbolTable
var expectedGenericArity = len(e.Generics)
var recievedGenericArity = len(genericStruct.Generics)
var structEnv = CreateSymbolTable(genericStruct.Closure, false, false, true, genericStruct.str())
var recievedGenericsTypeStrings = []string{}

// Verify Generics Arity
if expectedGenericArity != recievedGenericArity {
panic(fmt.Sprintf("Expected arity for generic struct instantiation of %d but recieved %d instead. \nGeneric structs must have explicit generic parameters.", expectedGenericArity, recievedGenericArity))
}

// Install Generic Types For Respective Names
generics := []Type{}
for genericIndex, recievedGenericType := range e.Generics {
genericName := genericStruct.Generics[genericIndex]
genericType := typecheck_type(recievedGenericType, structEnv)

recievedGenericsTypeStrings = append(recievedGenericsTypeStrings, genericType.str())
structEnv.DefinedTypes[genericName] = genericType
generics = append(generics, genericType)
}
var structSignature = createGenericListStr(structName, recievedGenericsTypeStrings)

genericStruct.ValidatedGenericLists = append(genericStruct.ValidatedGenericLists, generics)
structType = validate_struct_body(env, structEnv, genericStruct.Name, genericStruct.Properties, genericStruct.StaticMethods, genericStruct.InstanceMethods)
structType = validate_struct_body(env, structEnv, structSignature, genericStruct.Properties, genericStruct.StaticMethods, genericStruct.InstanceMethods)
definedScope.DefinedTypes[structName] = genericStruct
definedScope.DefinedTypes[structSignature] = structType
}

// Validate each field is instantiated which is expected in the struct
Expand Down
28 changes: 14 additions & 14 deletions src/analysis/tc_stmts.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,12 @@ func tc_struct_declaration_stmt(s ast.StructDeclarationStmt, env *SymbolTable) T

if isGeneric {
genericType := GenericStructType{
Name: s.Name,
Properties: s.Properties,
InstanceMethods: s.InstanceMethods,
StaticMethods: s.StaticMethods,
Closure: env,
Generics: s.Generics,
ValidatedGenericLists: make([][]Type, 0),
Name: s.Name,
Properties: s.Properties,
InstanceMethods: s.InstanceMethods,
StaticMethods: s.StaticMethods,
Closure: env,
Generics: s.Generics,
}

env.DefinedTypes[structName] = genericType
Expand Down Expand Up @@ -268,13 +267,13 @@ func validate_struct_body(env *SymbolTable, structEnv *SymbolTable, structName s
var returnType Type = VoidType{}

if staticNode.ReturnType != nil {
returnType = typecheck_type(staticNode.ReturnType, env)
returnType = typecheck_type(staticNode.ReturnType, structEnv)
}

params := []Type{}

for _, param := range staticNode.Parameters {
params = append(params, typecheck_type(param.Type, env))
params = append(params, typecheck_type(param.Type, structEnv))
}

staticMethods[staticNode.Name] = FnType{
Expand All @@ -289,13 +288,14 @@ func validate_struct_body(env *SymbolTable, structEnv *SymbolTable, structName s
var returnType Type = VoidType{}

if instanceNode.ReturnType != nil {
returnType = typecheck_type(instanceNode.ReturnType, env)
returnType = typecheck_type(instanceNode.ReturnType, structEnv)
}

params := []Type{}

for _, param := range instanceNode.Parameters {
params = append(params, typecheck_type(param.Type, env))
paramType := typecheck_type(param.Type, structEnv)
params = append(params, paramType)
}

fnType := FnType{
Expand All @@ -318,13 +318,13 @@ func validate_struct_body(env *SymbolTable, structEnv *SymbolTable, structName s
var returnType Type = VoidType{}

if instanceNode.ReturnType != nil {
returnType = typecheck_type(instanceNode.ReturnType, env)
returnType = typecheck_type(instanceNode.ReturnType, structEnv)
}

params := []Type{}

for _, param := range instanceNode.Parameters {
params = append(params, typecheck_type(param.Type, env))
params = append(params, typecheck_type(param.Type, structEnv))
}

fnType := FnType{
Expand Down Expand Up @@ -358,7 +358,7 @@ func validate_struct_body(env *SymbolTable, structEnv *SymbolTable, structName s
// foreach parameter populate the simulated env
for _, param := range instanceMethod.Parameters {
paramName := param.Name
paramType := typecheck_type(param.Type, methodEnv)
paramType := typecheck_type(param.Type, structEnv)

methodEnv.Symbols[paramName] = SymbolInfo{
Type: paramType,
Expand Down
53 changes: 52 additions & 1 deletion src/analysis/tc_types.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package analysis

import (
"fmt"

"github.com/tlaceby/bedrock/src/ast"
"github.com/tlaceby/bedrock/src/helpers"
)

func tc_symbol_type(t ast.SymbolType, env *SymbolTable) Type {
Expand All @@ -18,5 +21,53 @@ func tc_fn_type(t ast.FnType, env *SymbolTable) Type {
}

func tc_struct_generic_type(t ast.StructType, env *SymbolTable) Type {
panic("Unimplimented")
var genericEnv *SymbolTable
var structSignature string // StructName<T, ..>{}
var structName = t.StructName
var genStruct GenericStructType
var expectedGenericArity int
var expectedGenericNames []string
var recievedGenericArity = len(t.GenericList)
var recievedGenerics = []Type{}
var recievedGenericsTypeStrings = []string{}
var T, definedEnv = env.findNearestTypeEnv(structName)

if !IsAStructType(T) {
panic(fmt.Sprintf("Could not resolve struct with name %s.", structName))
}

if IsNormalStructType(T) {
panic(fmt.Sprintf("Struct %s is not a generic struct. No need for type parameters.", structName))
} else {
genStruct = helpers.ExpectType[GenericStructType](T)
expectedGenericArity = len(genStruct.Generics)
expectedGenericNames = genStruct.Generics
}

// Verify Arity Matches Expected
if expectedGenericArity != recievedGenericArity {
panic(fmt.Sprintf("Generic %s expected arity of %d but recieved %d instead.", structName, expectedGenericArity, recievedGenericArity))
}

// Calculate Generics Recieved
for _, recievedGeneric := range t.GenericList {
genericType := typecheck_type(recievedGeneric, env)
recievedGenerics = append(recievedGenerics, genericType)
recievedGenericsTypeStrings = append(recievedGenericsTypeStrings, genericType.str())
}

structSignature = createGenericListStr(structName, recievedGenericsTypeStrings)
genericEnv = CreateSymbolTable(env, false, false, true, structSignature)

// Install Generic Types
for indx, genericName := range expectedGenericNames {
recieved := recievedGenerics[indx]
genericEnv.DefinedTypes[genericName] = recieved
}

// Generate Valid Struct Instance Which is NOT Generic
// This can Be installed in the environment which it was defined.
structInstanceType := validate_struct_body(env, genericEnv, structSignature, genStruct.Properties, genStruct.StaticMethods, genStruct.InstanceMethods)
definedEnv.DefinedTypes[structSignature] = structInstanceType
return structInstanceType
}
14 changes: 1 addition & 13 deletions src/analysis/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,10 @@ type GenericStructType struct {
Properties []ast.StructProperty
StaticMethods []ast.FunctionDeclarationStmt
InstanceMethods []ast.FunctionDeclarationStmt

ValidatedGenericLists [][]Type // Contains all verified working subtypes for this generic
}

func (t GenericStructType) str() string {
genericList := ""

for indx, genericName := range t.Generics {
genericList += genericName

if indx != len(t.Generics)-1 {
genericList += ", "
}
}

return fmt.Sprintf("%s <%s> {}", t.Name, genericList)
return createGenericListStr(t.Name, t.Generics)
}

type ErrorType struct {
Expand Down

0 comments on commit b61d84a

Please sign in to comment.