Skip to content

Commit f84a9b0

Browse files
authored
Merge pull request #54 from tanyanliang110/main
Add slice syntax
2 parents 21f3924 + 13cc016 commit f84a9b0

File tree

9 files changed

+1347
-378
lines changed

9 files changed

+1347
-378
lines changed

pkg/ast/ast.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const (
4343
TypeAssignmentExpr
4444

4545
TypeCallExpr
46+
TypeSliceExpr
4647

4748
// stmt.
4849
TypeBlockStmt
@@ -91,6 +92,8 @@ func (t NodeType) String() string {
9192
return "AssignmentExpr"
9293
case TypeCallExpr:
9394
return "CallExpr"
95+
case TypeSliceExpr:
96+
return "SliceExpr"
9497
case TypeBlockStmt:
9598
return "BlockStmt"
9699
case TypeIfelseStmt:
@@ -203,6 +206,9 @@ func (n *Node) AssignmentExpr() *AssignmentExpr {
203206
func (n *Node) CallExpr() *CallExpr {
204207
return n.elem.(*CallExpr)
205208
}
209+
func (n *Node) SliceExpr() *SliceExpr {
210+
return n.elem.(*SliceExpr)
211+
}
206212
func (n *Node) BlockStmt() *BlockStmt {
207213
return n.elem.(*BlockStmt)
208214
}
@@ -345,6 +351,12 @@ func WrapCallExpr(node *CallExpr) *Node {
345351
}
346352
}
347353

354+
func WrapSliceExpr(node *SliceExpr) *Node {
355+
return &Node{
356+
NodeType: TypeSliceExpr,
357+
elem: node,
358+
}
359+
}
348360
func WrapIfelseStmt(node *IfelseStmt) *Node {
349361
return &Node{
350362
NodeType: TypeIfelseStmt,
@@ -433,6 +445,8 @@ func NodeStartPos(node *Node) token.LnColPos {
433445
case TypeCallExpr:
434446
return node.CallExpr().NamePos
435447

448+
case TypeSliceExpr:
449+
return node.SliceExpr().LBracket
436450
case TypeBlockStmt:
437451
return node.BlockStmt().LBracePos
438452

pkg/ast/expr.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,38 @@ func (e *CallExpr) String() string {
315315
return fmt.Sprintf("%s(%s)", strings.ToLower(e.Name), strings.Join(arr, ", "))
316316
}
317317

318+
type SliceExpr struct {
319+
Obj *Node
320+
Start *Node
321+
End *Node
322+
Step *Node
323+
Colon2 *Node
324+
LBracket token.LnColPos
325+
RBracket token.LnColPos
326+
}
327+
328+
func (e *SliceExpr) IsExpr() bool {
329+
return true
330+
}
331+
332+
func (e *SliceExpr) String() string {
333+
startStr := ""
334+
if e.Start != nil {
335+
startStr = e.Start.String()
336+
}
337+
endStr := ""
338+
if e.End != nil {
339+
endStr = e.End.String()
340+
}
341+
stepStr := ""
342+
if e.Step != nil {
343+
stepStr = ":" + e.Step.String()
344+
} else if e.Colon2 != nil {
345+
stepStr = ":"
346+
}
347+
return fmt.Sprintf("%s[%s:%s%s]", e.Obj.String(), startStr, endStr, stepStr)
348+
}
349+
318350
type AssignmentExpr struct {
319351
LHS, RHS *Node
320352
Op Op

pkg/engine/runtime/checkstmt.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ func RunStmtCheck(ctx *Task, ctxCheck *ContextCheck, node *ast.Node) *errchain.P
7171

7272
case ast.TypeCallExpr:
7373
return RunCallExprCheck(ctx, ctxCheck, node.CallExpr())
74+
case ast.TypeSliceExpr:
75+
return RunSliceExprCheck(ctx, ctxCheck, node.SliceExpr())
7476

7577
case ast.TypeIfelseStmt:
7678
return RunIfElseStmtCheck(ctx, ctxCheck, node.IfelseStmt())
@@ -191,6 +193,30 @@ func RunCallExprCheck(ctx *Task, ctxCheck *ContextCheck, expr *ast.CallExpr) *er
191193
return funcCheck(ctx, expr)
192194
}
193195

196+
func RunSliceExprCheck(ctx *Task, ctxCheck *ContextCheck, expr *ast.SliceExpr) *errchain.PlError {
197+
if err := RunStmtCheck(ctx, ctxCheck, expr.Obj); err != nil {
198+
return err
199+
}
200+
201+
if expr.Start != nil {
202+
if err := RunStmtCheck(ctx, ctxCheck, expr.Start); err != nil {
203+
return err
204+
}
205+
}
206+
207+
if expr.End != nil {
208+
if err := RunStmtCheck(ctx, ctxCheck, expr.End); err != nil {
209+
return err
210+
}
211+
}
212+
if expr.End != nil {
213+
if err := RunStmtCheck(ctx, ctxCheck, expr.Step); err != nil {
214+
return err
215+
}
216+
}
217+
return nil
218+
}
219+
194220
func RunAssignmentExprCheck(ctx *Task, ctxCheck *ContextCheck, expr *ast.AssignmentExpr) *errchain.PlError {
195221
if err := RunStmtCheck(ctx, ctxCheck, expr.RHS); err != nil {
196222
return err

pkg/engine/runtime/runtime.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,8 @@ func RunStmt(ctx *Task, node *ast.Node) (any, ast.DType, *errchain.PlError) {
381381
return RunAssignmentExpr(ctx, node.AssignmentExpr())
382382
case ast.TypeCallExpr:
383383
return RunCallExpr(ctx, node.CallExpr())
384+
case ast.TypeSliceExpr:
385+
return RunSliceExpr(ctx, node.SliceExpr())
384386
case ast.TypeInExpr:
385387
return RunInExpr(ctx, node.InExpr())
386388
case ast.TypeListLiteral:
@@ -1006,7 +1008,133 @@ func RunCallExpr(ctx *Task, expr *ast.CallExpr) (any, ast.DType, *errchain.PlErr
10061008
}
10071009
return nil, ast.Void, nil
10081010
}
1011+
func RunSliceExpr(ctx *Task, expr *ast.SliceExpr) (any, ast.DType, *errchain.PlError) {
1012+
obj, objT, err := RunStmt(ctx, expr.Obj)
1013+
if err != nil {
1014+
return nil, ast.Invalid, err
1015+
}
1016+
var start, end, step any
1017+
var startT, endT, stepT ast.DType
1018+
if expr.Start != nil {
1019+
start, startT, err = RunStmt(ctx, expr.Start)
1020+
if err != nil {
1021+
return nil, ast.Invalid, err
1022+
}
1023+
}
1024+
if expr.End != nil {
1025+
end, endT, err = RunStmt(ctx, expr.End)
1026+
if err != nil {
1027+
return nil, ast.Invalid, err
1028+
}
1029+
}
1030+
if expr.Step != nil {
1031+
step, stepT, err = RunStmt(ctx, expr.Step)
1032+
if err != nil {
1033+
return nil, ast.Invalid, err
1034+
}
1035+
}
1036+
var startInt, endInt, stepInt int
1037+
var length int
1038+
switch objT { //nolint:exhaustive
1039+
case ast.String:
1040+
length = len(obj.(string))
1041+
case ast.List, ast.DType(ast.TypeSliceExpr):
1042+
length = len(obj.([]any))
1043+
default:
1044+
return nil, ast.Invalid, NewRunError(ctx, "invalid obj type", expr.Obj.StartPos())
1045+
}
10091046

1047+
if step != nil {
1048+
if stepT != ast.Int {
1049+
return nil, ast.Invalid, NewRunError(ctx, "invalid step type", expr.Step.StartPos())
1050+
}
1051+
stepInt = cast.ToInt(step)
1052+
if stepInt == 0 {
1053+
return nil, ast.Invalid, NewRunError(ctx, "step must be non-zero", expr.Step.StartPos())
1054+
}
1055+
} else {
1056+
stepInt = 1
1057+
}
1058+
1059+
if start != nil {
1060+
if startT != ast.Int {
1061+
return nil, ast.Invalid, NewRunError(ctx, "invalid start type", expr.Start.StartPos())
1062+
}
1063+
startInt = cast.ToInt(start)
1064+
if startInt < 0 {
1065+
startInt = length + startInt
1066+
}
1067+
} else if stepInt > 0 {
1068+
startInt = 0
1069+
} else {
1070+
startInt = length - 1
1071+
}
1072+
1073+
if end != nil {
1074+
if endT != ast.Int {
1075+
return nil, ast.Invalid, NewRunError(ctx, "invalid end type", expr.End.StartPos())
1076+
}
1077+
endInt = cast.ToInt(end)
1078+
if endInt < 0 {
1079+
endInt = length + endInt
1080+
}
1081+
} else if stepInt > 0 {
1082+
endInt = length
1083+
} else {
1084+
endInt = -1
1085+
}
1086+
1087+
switch objT {
1088+
case ast.String:
1089+
str := obj.(string)
1090+
if stepInt > 0 {
1091+
result := ""
1092+
if startInt < 0 {
1093+
startInt = 0
1094+
}
1095+
for i := startInt; i < endInt && i < length; i += stepInt {
1096+
result += string(str[i])
1097+
}
1098+
return result, ast.String, nil
1099+
} else {
1100+
result := ""
1101+
if startInt > length-1 {
1102+
startInt = length - 1
1103+
}
1104+
for i := startInt; i > endInt && i >= 0; i += stepInt {
1105+
result += string(str[i])
1106+
}
1107+
return result, ast.String, nil
1108+
}
1109+
default:
1110+
list := obj.([]any)
1111+
if stepInt > 0 {
1112+
if startInt < 0 {
1113+
startInt = 0
1114+
}
1115+
if endInt > length {
1116+
endInt = length
1117+
}
1118+
result := make([]any, 0, (endInt-startInt+stepInt-1)/stepInt)
1119+
for i := startInt; i < endInt; i += stepInt {
1120+
result = append(result, list[i])
1121+
}
1122+
return result, ast.List, nil
1123+
} else {
1124+
if startInt > length-1 {
1125+
startInt = length - 1
1126+
}
1127+
if endInt < 0 {
1128+
endInt = -1
1129+
}
1130+
result := make([]any, 0, (startInt-endInt-stepInt-1)/(-stepInt))
1131+
for i := startInt; i > endInt; i += stepInt {
1132+
result = append(result, list[i])
1133+
}
1134+
return result, ast.List, nil
1135+
}
1136+
}
1137+
}
10101138
func typePromotion(l ast.DType, r ast.DType) ast.DType {
10111139
if l == ast.Float || r == ast.Float {
10121140
return ast.Float

0 commit comments

Comments
 (0)