From 217c48f933645a6d7c61a476837e4a79ac7da855 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Fri, 20 Apr 2018 22:42:43 +0200 Subject: [PATCH] Implement interfaces on the string type --- src/examples/hello/hello.go | 3 +++ tgo.go | 23 +++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/examples/hello/hello.go b/src/examples/hello/hello.go index a47ff510..607f3922 100644 --- a/src/examples/hello/hello.go +++ b/src/examples/hello/hello.go @@ -24,6 +24,7 @@ func main() { println("thing:", thing.String()) printItf(5) printItf(byte('x')) + printItf("foo") } func strlen(s string) int { @@ -36,6 +37,8 @@ func printItf(val interface{}) { println("is int:", val) case byte: println("is byte:", val) + case string: + println("is string:", val) default: println("is ?") } diff --git a/tgo.go b/tgo.go index 5bb416ce..bff927c9 100644 --- a/tgo.go +++ b/tgo.go @@ -654,8 +654,14 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) { var itfValue llvm.Value switch typ := expr.X.Type().(type) { case *types.Basic: + itfValueType := llvm.PointerType(llvm.Int8Type(), 0) if typ.Info() & types.IsInteger != 0 { - itfValue = c.builder.CreateIntToPtr(val, llvm.PointerType(llvm.Int8Type(), 0), "") + itfValue = c.builder.CreateIntToPtr(val, itfValueType, "") + } else if typ.Kind() == types.String { + // TODO: escape analysis + itfValue = c.builder.CreateMalloc(c.stringType, "") + c.builder.CreateStore(val, itfValue) + itfValue = c.builder.CreateBitCast(itfValue, itfValueType, "") } else { return llvm.Value{}, errors.New("todo: make interface: unknown basic type") } @@ -689,7 +695,20 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) { assertedTypeNum := c.getInterfaceType(expr.AssertedType) actualTypeNum := c.builder.CreateExtractValue(itf, 0, "interface.type") valuePtr := c.builder.CreateExtractValue(itf, 1, "interface.value") - value := c.builder.CreatePtrToInt(valuePtr, assertedType, "") + var value llvm.Value + switch typ := expr.AssertedType.(type) { + case *types.Basic: + if typ.Info() & types.IsInteger != 0 { + value = c.builder.CreatePtrToInt(valuePtr, assertedType, "") + } else if typ.Kind() == types.String { + valueStringPtr := c.builder.CreateBitCast(valuePtr, llvm.PointerType(c.stringType, 0), "") + value = c.builder.CreateLoad(valueStringPtr, "") + } else { + return llvm.Value{}, errors.New("todo: typeassert: unknown basic type") + } + default: + return llvm.Value{}, errors.New("todo: typeassert: unknown type") + } commaOk := c.builder.CreateICmp(llvm.IntEQ, assertedTypeNum, actualTypeNum, "") tuple := llvm.ConstStruct([]llvm.Value{llvm.Undef(assertedType), llvm.Undef(llvm.Int1Type())}, false) // create empty tuple tuple = c.builder.CreateInsertValue(tuple, value, 0, "") // insert value