Skip to content

Commit 24c9cf8

Browse files
committed
support make string from byte slice
1 parent 466e9ba commit 24c9cf8

File tree

7 files changed

+86
-0
lines changed

7 files changed

+86
-0
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ test/example:
127127
${CELL} -d -t riscv tests/examples/helloworld.cell && ckb-debugger --bin helloworld | grep "hello world! 1"
128128
${CELL} -t riscv tests/examples/table.cell && ckb-debugger --bin table
129129
${CELL} -d -t riscv tests/examples/string.cell && ckb-debugger --bin string | grep "eq"
130+
${CELL} -d -t riscv tests/examples/string-ctor.cell && ckb-debugger --bin string-ctor | grep "s=12"
130131
${CELL} -d -t riscv tests/examples/strings.cell && ckb-debugger --bin strings | grep "aa-bb"
131132
${CELL} -d -t riscv tests/examples/make-slice.cell && ckb-debugger --bin make-slice | grep "0422"
132133
${CELL} -d -t riscv tests/examples/panic.cell && ckb-debugger --bin panic | grep "runtime panic: hah"

compiler/compiler/compiler.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,8 @@ func (c *Compiler) compileValue(node parser.Node) value.Value {
359359
return c.compileNegateBoolNode(v)
360360
case *parser.InitializeSliceNode:
361361
return c.compileInitializeSliceNode(v)
362+
case *parser.InitializeStringWithSliceNode:
363+
return c.compileInitializeStringWithSliceNode(v)
362364
case *parser.SliceArrayNode:
363365
src := c.compileValue(v.Val)
364366

compiler/compiler/strings.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package compiler
2+
3+
import (
4+
"github.com/llir/llvm/ir/constant"
5+
llvmTypes "github.com/llir/llvm/ir/types"
6+
llvmValue "github.com/llir/llvm/ir/value"
7+
8+
"github.com/cell-labs/cell-script/compiler/compiler/internal"
9+
"github.com/cell-labs/cell-script/compiler/compiler/internal/pointer"
10+
"github.com/cell-labs/cell-script/compiler/compiler/name"
11+
"github.com/cell-labs/cell-script/compiler/compiler/value"
12+
"github.com/cell-labs/cell-script/compiler/parser"
13+
)
14+
15+
func (c *Compiler) compileInitializeStringWithSliceNode(v *parser.InitializeStringWithSliceNode) value.Value {
16+
sliceValue := c.compileValue(v.Items[0])
17+
srcVal := internal.LoadIfVariable(c.contextBlock, sliceValue)
18+
srcLen := c.contextBlock.NewExtractValue(srcVal, 0)
19+
srcOff := c.contextBlock.NewExtractValue(srcVal, 2)
20+
srcArr := c.contextBlock.NewExtractValue(srcVal, 3)
21+
srcArrStartPtr := c.contextBlock.NewGetElementPtr(pointer.ElemType(srcArr), srcArr, srcOff)
22+
length := c.contextBlock.NewSub(srcLen, srcOff)
23+
// create new string
24+
strVal := c.contextBlock.NewCall(c.osFuncs.Strndup.Value.(llvmValue.Named), srcArrStartPtr, length)
25+
// construct a new string {i64, i8*}
26+
sType, ok := c.packages["global"].GetPkgType("string", true)
27+
if !ok {
28+
panic("string type not found")
29+
}
30+
alloc := c.contextBlock.NewAlloca(sType.LLVM())
31+
32+
// Save length of the string
33+
lenItem := c.contextBlock.NewGetElementPtr(pointer.ElemType(alloc), alloc, constant.NewInt(llvmTypes.I32, 0), constant.NewInt(llvmTypes.I32, 0))
34+
lenItem.SetName(name.Var("len"))
35+
if length.Type() != llvmTypes.I64 {
36+
c.contextBlock.NewStore(c.contextBlock.NewZExt(length, i64.LLVM()), lenItem)
37+
} else {
38+
c.contextBlock.NewStore(length, lenItem)
39+
}
40+
41+
// Save i8* version of string
42+
strItem := c.contextBlock.NewGetElementPtr(pointer.ElemType(alloc), alloc, constant.NewInt(llvmTypes.I32, 0), constant.NewInt(llvmTypes.I32, 1))
43+
strItem.SetName(name.Var("str"))
44+
c.contextBlock.NewStore(strVal, strItem)
45+
46+
return value.Value{
47+
Value: c.contextBlock.NewLoad(pointer.ElemType(alloc), alloc),
48+
Type: sType,
49+
IsVariable: false,
50+
}
51+
}

compiler/parser/node.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,15 @@ func (i InitializeStructNode) String() string {
427427
return fmt.Sprintf("InitializeStructNode-%s{%+v}", i.Type, i.Items)
428428
}
429429

430+
type InitializeStringWithSliceNode struct {
431+
baseNode
432+
Items []Node
433+
}
434+
435+
func (i InitializeStringWithSliceNode) String() string {
436+
return fmt.Sprintf("InitializeStringWithSliceNode-%s{%+v}", i.Items)
437+
}
438+
430439
type DeVariadicSliceNode struct {
431440
baseNode
432441
Item Node

compiler/parser/parser.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,12 @@ func (p *parser) parseOneWithOptions(withAheadParse, withArithAhead, withIdentif
390390
} else {
391391
panic("wrong argument for slice constructor")
392392
}
393+
case *SingleTypeNode:
394+
if t.TypeName == "string" {
395+
return &InitializeStringWithSliceNode{
396+
Items: items,
397+
}
398+
}
393399
default:
394400
panic("not supported")
395401
}

compiler/parser/walk.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ func Walk(v Visitor, node Node) (r Node) {
151151
for i, a := range n.Items {
152152
n.Items[i] = Walk(v, a)
153153
}
154+
case *InitializeStringWithSliceNode:
155+
for i, a := range n.Items {
156+
n.Items[i] = Walk(v, a)
157+
}
154158
case *ExternNode:
155159
for _, fn := range n.FuncNodes {
156160
Walk(v, fn)

tests/examples/string-ctor.cell

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import (
2+
"debug"
3+
)
4+
5+
func main() {
6+
b := []byte{'1','2'}
7+
s := make(string, b)
8+
debug.Printf("s=%s",s)
9+
s1 := make(string, b[0:1])
10+
debug.Printf("%s",s1)
11+
debug.Printf("s1=%s",s)
12+
return 0
13+
}

0 commit comments

Comments
 (0)