Skip to content

Commit

Permalink
support make string from byte slice
Browse files Browse the repository at this point in the history
  • Loading branch information
douyixuan committed Aug 27, 2024
1 parent 466e9ba commit 24c9cf8
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ test/example:
${CELL} -d -t riscv tests/examples/helloworld.cell && ckb-debugger --bin helloworld | grep "hello world! 1"
${CELL} -t riscv tests/examples/table.cell && ckb-debugger --bin table
${CELL} -d -t riscv tests/examples/string.cell && ckb-debugger --bin string | grep "eq"
${CELL} -d -t riscv tests/examples/string-ctor.cell && ckb-debugger --bin string-ctor | grep "s=12"
${CELL} -d -t riscv tests/examples/strings.cell && ckb-debugger --bin strings | grep "aa-bb"
${CELL} -d -t riscv tests/examples/make-slice.cell && ckb-debugger --bin make-slice | grep "0422"
${CELL} -d -t riscv tests/examples/panic.cell && ckb-debugger --bin panic | grep "runtime panic: hah"
Expand Down
2 changes: 2 additions & 0 deletions compiler/compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,8 @@ func (c *Compiler) compileValue(node parser.Node) value.Value {
return c.compileNegateBoolNode(v)
case *parser.InitializeSliceNode:
return c.compileInitializeSliceNode(v)
case *parser.InitializeStringWithSliceNode:
return c.compileInitializeStringWithSliceNode(v)
case *parser.SliceArrayNode:
src := c.compileValue(v.Val)

Expand Down
51 changes: 51 additions & 0 deletions compiler/compiler/strings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package compiler

import (
"github.com/llir/llvm/ir/constant"
llvmTypes "github.com/llir/llvm/ir/types"
llvmValue "github.com/llir/llvm/ir/value"

"github.com/cell-labs/cell-script/compiler/compiler/internal"
"github.com/cell-labs/cell-script/compiler/compiler/internal/pointer"
"github.com/cell-labs/cell-script/compiler/compiler/name"
"github.com/cell-labs/cell-script/compiler/compiler/value"
"github.com/cell-labs/cell-script/compiler/parser"
)

func (c *Compiler) compileInitializeStringWithSliceNode(v *parser.InitializeStringWithSliceNode) value.Value {
sliceValue := c.compileValue(v.Items[0])
srcVal := internal.LoadIfVariable(c.contextBlock, sliceValue)
srcLen := c.contextBlock.NewExtractValue(srcVal, 0)
srcOff := c.contextBlock.NewExtractValue(srcVal, 2)
srcArr := c.contextBlock.NewExtractValue(srcVal, 3)
srcArrStartPtr := c.contextBlock.NewGetElementPtr(pointer.ElemType(srcArr), srcArr, srcOff)
length := c.contextBlock.NewSub(srcLen, srcOff)
// create new string
strVal := c.contextBlock.NewCall(c.osFuncs.Strndup.Value.(llvmValue.Named), srcArrStartPtr, length)
// construct a new string {i64, i8*}
sType, ok := c.packages["global"].GetPkgType("string", true)
if !ok {
panic("string type not found")
}
alloc := c.contextBlock.NewAlloca(sType.LLVM())

// Save length of the string
lenItem := c.contextBlock.NewGetElementPtr(pointer.ElemType(alloc), alloc, constant.NewInt(llvmTypes.I32, 0), constant.NewInt(llvmTypes.I32, 0))
lenItem.SetName(name.Var("len"))
if length.Type() != llvmTypes.I64 {
c.contextBlock.NewStore(c.contextBlock.NewZExt(length, i64.LLVM()), lenItem)
} else {
c.contextBlock.NewStore(length, lenItem)
}

// Save i8* version of string
strItem := c.contextBlock.NewGetElementPtr(pointer.ElemType(alloc), alloc, constant.NewInt(llvmTypes.I32, 0), constant.NewInt(llvmTypes.I32, 1))
strItem.SetName(name.Var("str"))
c.contextBlock.NewStore(strVal, strItem)

return value.Value{
Value: c.contextBlock.NewLoad(pointer.ElemType(alloc), alloc),
Type: sType,
IsVariable: false,
}
}
9 changes: 9 additions & 0 deletions compiler/parser/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,15 @@ func (i InitializeStructNode) String() string {
return fmt.Sprintf("InitializeStructNode-%s{%+v}", i.Type, i.Items)
}

type InitializeStringWithSliceNode struct {
baseNode
Items []Node
}

func (i InitializeStringWithSliceNode) String() string {
return fmt.Sprintf("InitializeStringWithSliceNode-%s{%+v}", i.Items)
}

type DeVariadicSliceNode struct {
baseNode
Item Node
Expand Down
6 changes: 6 additions & 0 deletions compiler/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,12 @@ func (p *parser) parseOneWithOptions(withAheadParse, withArithAhead, withIdentif
} else {
panic("wrong argument for slice constructor")
}
case *SingleTypeNode:
if t.TypeName == "string" {
return &InitializeStringWithSliceNode{
Items: items,
}
}
default:
panic("not supported")
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/parser/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ func Walk(v Visitor, node Node) (r Node) {
for i, a := range n.Items {
n.Items[i] = Walk(v, a)
}
case *InitializeStringWithSliceNode:
for i, a := range n.Items {
n.Items[i] = Walk(v, a)
}
case *ExternNode:
for _, fn := range n.FuncNodes {
Walk(v, fn)
Expand Down
13 changes: 13 additions & 0 deletions tests/examples/string-ctor.cell
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import (
"debug"
)

func main() {
b := []byte{'1','2'}
s := make(string, b)
debug.Printf("s=%s",s)
s1 := make(string, b[0:1])
debug.Printf("%s",s1)
debug.Printf("s1=%s",s)
return 0
}

0 comments on commit 24c9cf8

Please sign in to comment.