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

View File

@ -58,10 +58,12 @@ func (this *generator) generateMethodCall (call *entity.MethodCall) (llvm.Value,
method, err := this.method(sourceType.Name, call.Name)
if err != nil { return nil, err }
source, err := this.generateExpressionLoc(call.Source)
if err != nil { return nil, err }
args[0] = source
return this.blockManager.NewCall(method, method.Signature, args...), nil
if method != nil {
source, err := this.generateExpressionLoc(call.Source)
if err != nil { return nil, err }
args[0] = source
return this.blockManager.NewCall(method, method.Signature, args...), nil
}
}
// check for methods on pointer to named type
@ -70,18 +72,20 @@ func (this *generator) generateMethodCall (call *entity.MethodCall) (llvm.Value,
method, err := this.method(sourceType.Name, call.Name)
if err != nil { return nil, err }
source, err := this.generateExpression(call.Source)
if err != nil { return nil, err }
args[0] = source
return this.blockManager.NewCall(method, method.Signature, args...), nil
if method != nil {
source, err := this.generateExpression(call.Source)
if err != nil { return nil, err }
args[0] = source
return this.blockManager.NewCall(method, method.Signature, args...), nil
}
}
}
// check for interface behaviors
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 }
source, err := this.generateExpression(call.Source)
source, err := this.generateExpressionLoc(call.Source)
if err != nil { return nil, err }
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"))
}
method, exists := ty.Methods[name]
if !exists {
return nil, errors.New(fmt.Sprintln (
"method", typeName + "." + name, "not found"))
}
if !exists { return nil, nil }
return this.generateMethod(method)
}
@ -99,10 +96,7 @@ func (this *generator) function (name string) (*llvm.Function, error) {
}
}
function, exists := this.tree.Functions[name]
if !exists {
return nil, errors.New(fmt.Sprintln (
"function", name, "not found"))
}
if !exists { return nil, nil }
return this.generateFunction(function)
}

View File

@ -4,7 +4,31 @@ import "testing"
func TestInterfaceBasic (test *testing.T) {
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)