@@ -525,6 +525,15 @@ template takeAddress(reg, source) =
525
525
reg.nodeAddr = addr source
526
526
GC_ref source
527
527
528
+ proc takeCharAddress (c: PCtx , src: PNode , index: BiggestInt , pc: int ): TFullReg =
529
+ let typ = newType (tyPtr, nextTypeId c.idgen, c.module.owner)
530
+ typ.add getSysType (c.graph, c.debug[pc], tyChar)
531
+ var node = newNodeIT (nkIntLit, c.debug[pc], typ) # xxx nkPtrLit
532
+ node.intVal = cast [int ](src.strVal[index].addr )
533
+ node.flags.incl nfIsPtr
534
+ TFullReg (kind: rkNode, node: node)
535
+
536
+
528
537
proc rawExecute (c: PCtx , start: int , tos: PStackFrame ): TFullReg =
529
538
var pc = start
530
539
var tos = tos
@@ -658,14 +667,73 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
658
667
else :
659
668
ensureKind (rkNode)
660
669
regs[ra].node = nb
670
+ of opcSlice:
671
+ # A bodge, but this takes in `toOpenArray(rb, rc, rc)` and emits
672
+ # nkTupleConstr(x, y, z) into the `regs[ra]`. These can later be used for calculating the slice we have taken.
673
+ decodeBC (rkNode)
674
+ let
675
+ collection = regs[ra].node
676
+ leftInd = regs[rb].intVal
677
+ rightInd = regs[rc].intVal
678
+
679
+ proc rangeCheck (left, right: BiggestInt , safeLen: BiggestInt ) =
680
+ if left < 0 :
681
+ stackTrace (c, tos, pc, formatErrorIndexBound (left, safeLen))
682
+
683
+ if right > safeLen:
684
+ stackTrace (c, tos, pc, formatErrorIndexBound (right, safeLen))
685
+
686
+ case collection.kind
687
+ of nkTupleConstr: # slice of a slice
688
+ let safeLen = collection[2 ].intVal - collection[1 ].intVal
689
+ rangeCheck (leftInd, rightInd, safeLen)
690
+ let
691
+ leftInd = leftInd + collection[1 ].intVal # Slice is from the start of the old
692
+ rightInd = rightInd + collection[1 ].intVal
693
+
694
+ regs[ra].node = newTree (
695
+ nkTupleConstr,
696
+ collection[0 ],
697
+ newIntNode (nkIntLit, BiggestInt leftInd),
698
+ newIntNode (nkIntLit, BiggestInt rightInd)
699
+ )
700
+
701
+ else :
702
+ let safeLen = safeArrLen (collection) - 1
703
+ rangeCheck (leftInd, rightInd, safeLen)
704
+ regs[ra].node = newTree (
705
+ nkTupleConstr,
706
+ collection,
707
+ newIntNode (nkIntLit, BiggestInt leftInd),
708
+ newIntNode (nkIntLit, BiggestInt rightInd)
709
+ )
710
+
711
+
661
712
of opcLdArr:
662
713
# a = b[c]
663
714
decodeBC (rkNode)
664
715
if regs[rc].intVal > high (int ):
665
716
stackTrace (c, tos, pc, formatErrorIndexBound (regs[rc].intVal, high (int )))
666
717
let idx = regs[rc].intVal.int
667
718
let src = regs[rb].node
668
- if src.kind in {nkStrLit.. nkTripleStrLit}:
719
+ case src.kind
720
+ of nkTupleConstr: # refer to `of opcSlice`
721
+ let
722
+ left = src[1 ].intVal
723
+ right = src[2 ].intVal
724
+ realIndex = left + idx
725
+ if idx in 0 .. (right - left):
726
+ case src[0 ].kind
727
+ of nkStrKinds:
728
+ regs[ra].node = newIntNode (nkCharLit, ord src[0 ].strVal[int realIndex])
729
+ of nkBracket:
730
+ regs[ra].node = src[0 ][int realIndex]
731
+ else :
732
+ stackTrace (c, tos, pc, " opcLdArr internal error" )
733
+ else :
734
+ stackTrace (c, tos, pc, formatErrorIndexBound (idx, int right))
735
+
736
+ of nkStrLit.. nkTripleStrLit:
669
737
if idx < % src.strVal.len:
670
738
regs[ra].node = newNodeI (nkCharLit, c.debug[pc])
671
739
regs[ra].node.intVal = src.strVal[idx].ord
@@ -682,10 +750,27 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
682
750
stackTrace (c, tos, pc, formatErrorIndexBound (regs[rc].intVal, high (int )))
683
751
let idx = regs[rc].intVal.int
684
752
let src = if regs[rb].kind == rkNode: regs[rb].node else : regs[rb].nodeAddr[]
685
- if src.kind notin {nkEmpty.. nkTripleStrLit} and idx < % src.len:
686
- takeAddress regs[ra], src.sons[idx]
753
+ case src.kind
754
+ of nkTupleConstr:
755
+ let
756
+ left = src[1 ].intVal
757
+ right = src[2 ].intVal
758
+ realIndex = left + idx
759
+ if idx in 0 .. (right - left): # Refer to `opcSlice`
760
+ case src[0 ].kind
761
+ of nkStrKinds:
762
+ regs[ra] = takeCharAddress (c, src[0 ], realIndex, pc)
763
+ of nkBracket:
764
+ takeAddress regs[ra], src.sons[0 ].sons[realIndex]
765
+ else :
766
+ stackTrace (c, tos, pc, " opcLdArrAddr internal error" )
767
+ else :
768
+ stackTrace (c, tos, pc, formatErrorIndexBound (idx, int right))
687
769
else :
688
- stackTrace (c, tos, pc, formatErrorIndexBound (idx, src.safeLen- 1 ))
770
+ if src.kind notin {nkEmpty.. nkTripleStrLit} and idx < % src.len:
771
+ takeAddress regs[ra], src.sons[idx]
772
+ else :
773
+ stackTrace (c, tos, pc, formatErrorIndexBound (idx, src.safeLen- 1 ))
689
774
of opcLdStrIdx:
690
775
decodeBC (rkInt)
691
776
let idx = regs[rc].intVal.int
@@ -702,21 +787,32 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
702
787
let idx = regs[rc].intVal.int
703
788
let s = regs[rb].node.strVal.addr # or `byaddr`
704
789
if idx < % s[].len:
705
- # `makePtrType` not accessible from vm.nim
706
- let typ = newType (tyPtr, nextTypeId c.idgen, c.module.owner)
707
- typ.add getSysType (c.graph, c.debug[pc], tyChar)
708
- let node = newNodeIT (nkIntLit, c.debug[pc], typ) # xxx nkPtrLit
709
- node.intVal = cast [int ](s[][idx].addr )
710
- node.flags.incl nfIsPtr
711
- regs[ra].node = node
790
+ regs[ra] = takeCharAddress (c, regs[rb].node, idx, pc)
712
791
else :
713
792
stackTrace (c, tos, pc, formatErrorIndexBound (idx, s[].len- 1 ))
714
793
of opcWrArr:
715
794
# a[b] = c
716
795
decodeBC (rkNode)
717
796
let idx = regs[rb].intVal.int
718
797
let arr = regs[ra].node
719
- if arr.kind in {nkStrLit.. nkTripleStrLit}:
798
+ case arr.kind
799
+ of nkTupleConstr: # refer to `opcSlice`
800
+ let
801
+ src = arr[0 ]
802
+ left = arr[1 ].intVal
803
+ right = arr[2 ].intVal
804
+ realIndex = left + idx
805
+ if idx in 0 .. (right - left):
806
+ case src.kind
807
+ of nkStrKinds:
808
+ src.strVal[int (realIndex)] = char (regs[rc].intVal)
809
+ of nkBracket:
810
+ src[int (realIndex)] = regs[rc].node
811
+ else :
812
+ stackTrace (c, tos, pc, " opcWrArr internal error" )
813
+ else :
814
+ stackTrace (c, tos, pc, formatErrorIndexBound (idx, int right))
815
+ of {nkStrLit.. nkTripleStrLit}:
720
816
if idx < % arr.strVal.len:
721
817
arr.strVal[idx] = chr (regs[rc].intVal)
722
818
else :
@@ -874,14 +970,21 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
874
970
of opcLenSeq:
875
971
decodeBImm (rkInt)
876
972
# assert regs[rb].kind == nkBracket
877
- let high = (imm and 1 ) # discard flags
973
+ let
974
+ high = (imm and 1 ) # discard flags
975
+ node = regs[rb].node
878
976
if (imm and nimNodeFlag) != 0 :
879
977
# used by mNLen (NimNode.len)
880
978
regs[ra].intVal = regs[rb].node.safeLen - high
881
979
else :
882
- # safeArrLen also return string node len
883
- # used when string is passed as openArray in VM
884
- regs[ra].intVal = regs[rb].node.safeArrLen - high
980
+ case node.kind
981
+ of nkTupleConstr: # refer to `of opcSlice`
982
+ regs[ra].intVal = node[2 ].intVal - node[1 ].intVal + 1 - high
983
+ else :
984
+ # safeArrLen also return string node len
985
+ # used when string is passed as openArray in VM
986
+ regs[ra].intVal = node.safeArrLen - high
987
+
885
988
of opcLenStr:
886
989
decodeBImm (rkInt)
887
990
assert regs[rb].kind == rkNode
0 commit comments