Attempt to further fix interface assignment

This commit is contained in:
Sasha Koshka 2023-12-14 21:21:07 -05:00
parent f72bf533e0
commit c4df65d189
4 changed files with 53 additions and 21 deletions

View File

@ -27,8 +27,6 @@ func (this *generator) generateAssignmentSource (
llvm.Value, llvm.Value,
error, error,
) { ) {
source, err := this.generateExpression(from)
if err != nil { return nil, err }
toBase := analyzer.ReduceToBase(to) toBase := analyzer.ReduceToBase(to)
switch toBase := toBase.(type) { switch toBase := toBase.(type) {
@ -48,6 +46,8 @@ func (this *generator) generateAssignmentSource (
// conversion from interface to interface // conversion from interface to interface
case *entity.TypeInterface: case *entity.TypeInterface:
// re-assign data // re-assign data
source, err := this.generateExpressionLoc(from)
if err != nil { return nil, err }
irFromType, err := this.generateType(fromType) irFromType, err := this.generateType(fromType)
if err != nil { return nil, err } if err != nil { return nil, err }
fromDataField := this.getInterfaceData(source, irFromType) fromDataField := this.getInterfaceData(source, irFromType)
@ -69,6 +69,8 @@ func (this *generator) generateAssignmentSource (
// conversion from pointer to interface // conversion from pointer to interface
case *entity.TypePointer: case *entity.TypePointer:
// assign data // assign data
source, err := this.generateExpression(from)
if err != nil { return nil, err }
fromData := this.blockManager.NewLoad(new(llvm.TypePointer), source) fromData := this.blockManager.NewLoad(new(llvm.TypePointer), source)
this.blockManager.NewStore(fromData, toDataField) this.blockManager.NewStore(fromData, toDataField)
@ -91,6 +93,8 @@ func (this *generator) generateAssignmentSource (
// conversion from other type to interface // conversion from other type to interface
default: default:
// assign data // assign data
source, err := this.generateExpressionLoc(from)
if err != nil { return nil, err }
this.blockManager.NewStore(source, toDataField) this.blockManager.NewStore(source, toDataField)
fromType, ok := fromType.(*entity.TypeNamed) fromType, ok := fromType.(*entity.TypeNamed)
@ -109,13 +113,19 @@ func (this *generator) generateAssignmentSource (
this.blockManager.NewStore(fromBehavior, toBehaviorField) this.blockManager.NewStore(fromBehavior, toBehaviorField)
} }
} }
return this.blockManager.NewLoad(irToType, destination), nil
// conversion from array to slice // conversion from array to slice
case *entity.TypeSlice: case *entity.TypeSlice:
switch fromBase := analyzer.ReduceToBase(from.Type()).(type) { switch fromBase := analyzer.ReduceToBase(from.Type()).(type) {
case *entity.TypeArray: case *entity.TypeArray:
source, err := this.generateExpression(from)
if err != nil { return nil, err }
return this.generateSlice(to, source, int64(fromBase.Length)) return this.generateSlice(to, source, int64(fromBase.Length))
} }
} }
source, err := this.generateExpression(from)
if err != nil { return nil, err }
return source, nil return source, nil
} }

View File

@ -58,11 +58,13 @@ func (this *generator) generateMethodCall (call *entity.MethodCall) (llvm.Value,
method, err := this.method(sourceType.Name, call.Name) method, err := this.method(sourceType.Name, call.Name)
if err != nil { return nil, err } if err != nil { return nil, err }
if method != nil {
source, err := this.generateExpressionLoc(call.Source) source, err := this.generateExpressionLoc(call.Source)
if err != nil { return nil, err } if err != nil { return nil, err }
args[0] = source args[0] = source
return this.blockManager.NewCall(method, method.Signature, args...), nil return this.blockManager.NewCall(method, method.Signature, args...), nil
} }
}
// check for methods on pointer to named type // check for methods on pointer to named type
if pointerType, ok := call.Source.Type().(*entity.TypePointer); ok { if pointerType, ok := call.Source.Type().(*entity.TypePointer); ok {
@ -70,18 +72,20 @@ func (this *generator) generateMethodCall (call *entity.MethodCall) (llvm.Value,
method, err := this.method(sourceType.Name, call.Name) method, err := this.method(sourceType.Name, call.Name)
if err != nil { return nil, err } if err != nil { return nil, err }
if method != nil {
source, err := this.generateExpression(call.Source) source, err := this.generateExpression(call.Source)
if err != nil { return nil, err } if err != nil { return nil, err }
args[0] = source args[0] = source
return this.blockManager.NewCall(method, method.Signature, args...), nil return this.blockManager.NewCall(method, method.Signature, args...), nil
} }
} }
}
// check for interface behaviors // check for interface behaviors
if sourceType := getInterface(call.Source.Type()); sourceType != nil { if sourceType := getInterface(call.Source.Type()); sourceType != nil {
irSourceType, err := this.generateType(sourceType) irSourceType, err := this.generateType(call.Source.Type())
if err != nil { return nil, err } if err != nil { return nil, err }
source, err := this.generateExpression(call.Source) source, err := this.generateExpressionLoc(call.Source)
if err != nil { return nil, err } if err != nil { return nil, err }
irBehavior := this.getInterfaceBehavior(sourceType, source, irSourceType, call.Name) irBehavior := this.getInterfaceBehavior(sourceType, source, irSourceType, call.Name)

View File

@ -85,10 +85,7 @@ func (this *generator) method (typeName string, name string) (*llvm.Function, er
errors.New(fmt.Sprintln("type", typeName, "not found")) errors.New(fmt.Sprintln("type", typeName, "not found"))
} }
method, exists := ty.Methods[name] method, exists := ty.Methods[name]
if !exists { if !exists { return nil, nil }
return nil, errors.New(fmt.Sprintln (
"method", typeName + "." + name, "not found"))
}
return this.generateMethod(method) return this.generateMethod(method)
} }
@ -99,10 +96,7 @@ func (this *generator) function (name string) (*llvm.Function, error) {
} }
} }
function, exists := this.tree.Functions[name] function, exists := this.tree.Functions[name]
if !exists { if !exists { return nil, nil }
return nil, errors.New(fmt.Sprintln (
"function", name, "not found"))
}
return this.generateFunction(function) return this.generateFunction(function)
} }

View File

@ -4,7 +4,31 @@ import "testing"
func TestInterfaceBasic (test *testing.T) { func TestInterfaceBasic (test *testing.T) {
testString (test, testString (test,
` `%Number = type i64
%Numbered = type { ptr, ptr }
define i64 @main() {
0:
%1 = alloca %Number
store i64 5, ptr %1
%2 = alloca %Numbered
%3 = getelementptr %Numbered, ptr %2, i32 0, i32 0
store ptr %1, ptr %3
%4 = getelementptr %Numbered, ptr %2, i32 0, i32 1
store ptr @Number.number, ptr %4
%6 = getelementptr { ptr, ptr }, ptr %2, i32 0, i32 1
%7 = getelementptr { ptr, ptr }, ptr %2, i32 0, i32 0
%8 = load ptr, ptr %7
%9 = call i64 %7(ptr %6)
ret i64 %9
}
define i64 @Number.number(ptr %this) {
0:
%1 = alloca ptr
store ptr %this, ptr %1
%2 = load ptr, ptr %1
%3 = load i64, ptr %2
ret i64 %3
}
`, `,
` `
Numbered: ([number]: Int) Numbered: ([number]: Int)