/* ARM assembly Raspberry PI  */
/*  program substring.s   */

/* Constantes    */
.equ STDOUT, 1                           @ Linux output console
.equ EXIT,   1                           @ Linux syscall
.equ WRITE,  4                           @ Linux syscall

.equ BUFFERSIZE,          100

/* Initialized data */
.data
szMessString:            .asciz "Result : "
szString1:               .asciz "abcdefghijklmnopqrstuvwxyz"
szStringStart:           .asciz "abcdefg"
szCarriageReturn:        .asciz "\n"

/* UnInitialized data */
.bss
szSubString:             .skip 500             @ buffer result

/*  code section */
.text
.global main
main:

    ldr r0,iAdrszString1                        @ address input string
    ldr r1,iAdrszSubString                      @ address output string
    mov r2,#22                                  @ location
    mov r3,#4                                   @ length
    bl subStringNbChar                          @ starting from n characters in and of m length
    ldr r0,iAdrszMessString                     @ display message
    bl affichageMess
    ldr r0,iAdrszSubString                      @ display substring result
    bl affichageMess
    ldr r0,iAdrszCarriageReturn                 @ display line return
    bl affichageMess
    @
    ldr r0,iAdrszString1
    ldr r1,iAdrszSubString
    mov r2,#15                                  @ location
    bl subStringEnd                             @starting from n characters in, up to the end of the string
    ldr r0,iAdrszMessString                     @ display message
    bl affichageMess
    ldr r0,iAdrszSubString
    bl affichageMess
    ldr r0,iAdrszCarriageReturn                 @ display line return
    bl affichageMess
    @
    ldr r0,iAdrszString1
    ldr r1,iAdrszSubString
    bl subStringMinus                           @ whole string minus last character
    ldr r0,iAdrszMessString                     @ display message
    bl affichageMess
    ldr r0,iAdrszSubString
    bl affichageMess
    ldr r0,iAdrszCarriageReturn                 @ display line return
    bl affichageMess
    @
    ldr r0,iAdrszString1
    ldr r1,iAdrszSubString
    mov r2,#'c'                                 @ start character
    mov r3,#5                                   @ length
    bl subStringStChar                          @starting from a known character within the string and of m length
    cmp r0,#-1                                  @ error ?
    beq 2f
    ldr r0,iAdrszMessString                     @ display message
    bl affichageMess
    ldr r0,iAdrszSubString
    bl affichageMess
    ldr r0,iAdrszCarriageReturn                 @ display line return
    bl affichageMess
    @
2:
    ldr r0,iAdrszString1
    ldr r1,iAdrszSubString
    ldr r2,iAdrszStringStart                    @ sub string to start
    mov r3,#10                                  @ length
    bl subStringStString                        @ starting from a known substring within the string and of m length
    cmp r0,#-1                                  @ error ?
    beq 3f
    ldr r0,iAdrszMessString                     @ display message
    bl affichageMess
    ldr r0,iAdrszSubString
    bl affichageMess
    ldr r0,iAdrszCarriageReturn                 @ display line return
    bl affichageMess
3:
100:                                            @ standard end of the program
    mov r0, #0                                  @ return code
    mov r7, #EXIT                               @ request to exit program
    svc 0                                       @ perform system call
iAdrszMessString:         .int szMessString
iAdrszString1:            .int szString1
iAdrszSubString:            .int szSubString
iAdrszStringStart:            .int szStringStart
iAdrszCarriageReturn:     .int szCarriageReturn
/******************************************************************/
/*     sub strings  index start  number of characters             */
/******************************************************************/
/* r0 contains the address of the input string */
/* r1 contains the address of the output string */
/* r2 contains the start index                  */
/* r3 contains numbers of characters to extract */
/* r0 returns number of characters or -1 if error */
subStringNbChar:
    push {r1-r5,lr}                             @ save  registers
    mov r4,#0                                   @ counter byte output string
1:
    ldrb r5,[r0,r2]                             @ load byte string input
    cmp r5,#0                                   @ zero final ?
    beq 2f
    strb r5,[r1,r4]                             @ store byte output string
    add r2,#1                                   @ increment counter
    add r4,#1
    cmp r4,r3                                   @ end ?
    blt 1b                                      @ no -> loop
2:
    mov r5,#0
    strb r5,[r1,r4]                             @ load byte string 2
    mov r0,r4
100:
    pop {r1-r5,lr}                              @ restaur registers
    bx lr                                       @ return
/******************************************************************/
/*     sub strings  index start at end of string             */
/******************************************************************/
/* r0 contains the address of the input string */
/* r1 contains the address of the output string */
/* r2 contains the start index                  */
/* r0 returns number of characters or -1 if error */
subStringEnd:
    push {r1-r5,lr}                             @ save registers
    mov r4,#0                                   @ counter byte output string
1:
    ldrb r5,[r0,r2]                             @ load byte string 1
    cmp r5,#0                                   @ zero final ?
    beq 2f
    strb r5,[r1,r4]
    add r2,#1
    add r4,#1
    b 1b                                        @ loop
2:
    mov r5,#0
    strb r5,[r1,r4]                             @ load byte string 2
    mov r0,r4
100:
    pop {r1-r5,lr}                              @ restaur registers
    bx lr
/******************************************************************/
/*      whole string minus last character                        */
/******************************************************************/
/* r0 contains the address of the input string */
/* r1 contains the address of the output string */
/* r0 returns number of characters or -1 if error */
subStringMinus:
    push {r1-r5,lr}                             @ save  registers
    mov r2,#0                                   @ counter byte input string
    mov r4,#0                                   @ counter byte output string
1:
    ldrb r5,[r0,r2]                             @ load byte string
    cmp r5,#0                                   @ zero final ?
    beq 2f
    strb r5,[r1,r4]
    add r2,#1
    add r4,#1
    b 1b                                        @  loop
2:
    sub r4,#1
    mov r5,#0
    strb r5,[r1,r4]                             @ load byte string 2
    mov r0,r4
100:
    pop {r1-r5,lr}                              @ restaur registers
    bx lr
/******************************************************************/
/*   starting from a known character within the string and of m length  */
/******************************************************************/
/* r0 contains the address of the input string */
/* r1 contains the address of the output string */
/* r2 contains the character    */
/* r3 contains the length
/* r0 returns number of characters or -1 if error */
subStringStChar:
    push {r1-r5,lr}                             @ save  registers
    mov r6,#0                                   @ counter byte input string
    mov r4,#0                                   @ counter byte output string

1:
    ldrb r5,[r0,r6]                             @ load byte string
    cmp r5,#0                                   @ zero final ?
    streqb r5,[r1,r4]
    moveq r0,#-1
    beq 100f
    cmp r5,r2
    beq 2f
    add r6,#1
    b 1b                                        @  loop
2:
    strb r5,[r1,r4]
    add r6,#1
    add r4,#1
    cmp r4,r3
    bge 3f
    ldrb r5,[r0,r6]                             @ load byte string
    cmp r5,#0
    bne 2b
3:
    mov r5,#0
    strb r5,[r1,r4]                             @ load byte string 2
    mov r0,r4
100:
    pop {r1-r5,lr}                              @ restaur registers
    bx lr

/******************************************************************/
/*   starting from a known substring within the string and of m length  */
/******************************************************************/
/* r0 contains the address of the input string */
/* r1 contains the address of the output string */
/* r2 contains the address of string to start    */
/* r3 contains the length
/* r0 returns number of characters or -1 if error */
subStringStString:
    push {r1-r8,lr}                             @ save  registers
    mov r7,r0                                   @ save address
    mov r8,r1                                   @ counter byte string
    mov r1,r2
    bl searchSubString
    cmp r0,#-1
    beq 100f
    mov r6,r0                                   @ counter byte input string
    mov r4,#0
1:
    ldrb r5,[r7,r6]                             @ load byte string
    strb r5,[r8,r4]
    cmp r5,#0                                   @ zero final ?
    moveq r0,r4
    beq 100f
    add r4,#1
    cmp r4,r3
    addlt r6,#1
    blt 1b                                      @  loop
    mov r5,#0
    strb r5,[r8,r4]
    mov r0,r4
100:
    pop {r1-r8,lr}                              @ restaur registers
    bx lr

/******************************************************************/
/*   search a substring in the string                            */
/******************************************************************/
/* r0 contains the address of the input string */
/* r1 contains the address of substring */
/* r0 returns index of substring in string or -1 if not found */
searchSubString:
    push {r1-r6,lr}                       @ save registers
    mov r2,#0                             @ counter byte input string
    mov r3,#0                             @ counter byte string
    mov r6,#-1                            @ index found
    ldrb r4,[r1,r3]
1:
    ldrb r5,[r0,r2]                       @ load byte string
    cmp r5,#0                             @ zero final ?
    moveq r0,#-1                          @ yes returns error
    beq 100f
    cmp r5,r4                             @ compare character
    beq 2f
    mov r6,#-1                            @ no equals - > raz index
    mov r3,#0                             @ and raz counter byte
    add r2,#1                             @ and increment counter byte
    b 1b                                  @ and loop
2:                                        @ characters equals
    cmp r6,#-1                            @ first characters equals ?
    moveq r6,r2                           @ yes -> index begin in r6
    add r3,#1                             @ increment counter substring
    ldrb r4,[r1,r3]                       @ and load next byte
    cmp r4,#0                             @ zero final ?
    beq 3f                                @ yes -> end search
    add r2,#1                             @ else increment counter string
    b 1b                                  @ and loop
3:
    mov r0,r6
100:
    pop {r1-r6,lr}                        @ restaur registers
    bx lr

/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}                       @ save  registers
    mov r2,#0                                   @ counter length */
1:                                              @ loop length calculation
    ldrb r1,[r0,r2]                             @ read octet start position + index
    cmp r1,#0                                   @ if 0 its over
    addne r2,r2,#1                              @ else add 1 in the length
    bne 1b                                      @ and loop
                                                @ so here r2 contains the length of the message
    mov r1,r0                                   @ address message in r1
    mov r0,#STDOUT                              @ code to write to the standard output Linux
    mov r7, #WRITE                              @ code call system "write"
    svc #0                                      @ call system
    pop {r0,r1,r2,r7,lr}                        @ restaur registers
    bx lr                                       @ return


% Subleq program interpreter                                                 %
begin

    % executes the program specified in scode, stops when the instruction    %
    % pointer becomes negative                                               %
    procedure runSubleq ( integer array scode( * )
                        ; integer value codeLength
                        ) ;
    begin
        integer maxMemory;
        maxMemory := 3 * 1024;
        begin
            integer array memory ( 0 :: maxMemory - 1 );
            integer       ip, a, b, c;
            for i := 0 until maxMemory - 1 do memory( i ) := 0;
            % load the program into memory                                   %
            for i := 0 until codeLength do memory( i ) := scode( i );

            % start at instruction 0                                         %
            ip := 0;
            % execute the instructions until ip is < 0                       %
            while ip >= 0 do begin
                % get three words at ip and advance ip past them             %
                a  := memory( ip     );
                b  := memory( ip + 1 );
                c  := memory( ip + 2 );
                ip := ip + 3;
                % execute according to a, b and c                            %
                if       a = -1 then begin
                    % input a character to b                                 %
                    string(1) input;
                    read( input );
                    memory( b ) := decode( input )
                    end
                else if b = -1 then begin
                    % output character from a                                %
                    writeon( code( memory( a ) ) )
                    end
                else begin
                    % subtract and branch if le 0                            %
                    memory( b ) := memory( b ) - memory( a );
                    if memory( b ) <= 0 then ip := c
                end
            end % while-do %
        end
    end % runSubleq % ;

    % test the interpreter with the hello-world program specified in the task %
    begin
        integer array code ( 0 :: 31 );
        integer       codePos;
        codePos := 0;
        for i :=  15,  17,  -1,  17,  -1,  -1
               ,  16,   1,  -1,  16,   3,  -1
               ,  15,  15,   0,   0,  -1,  72
               , 101, 108, 108, 111,  44,  32
               , 119, 111, 114, 108, 100,  33
               ,  10,   0
        do begin
            code( codePos ) := i;
            codePos := codePos + 1;
        end;
        runSubleq( code, 31 )
    end

end.


#!/usr/local/bin/apl -s --
⎕IO←0                       ⍝ Index origin 0 is more intuitive with 'pointers'
∇Subleq;fn;text;M;A;B;C;X
        →(5≠⍴⎕ARG)/usage    ⍝ There should be one (additional) argument
        fn←⊃⎕ARG[4]         ⍝ This argument should be the file name
        →(''≢0⍴text←⎕FIO[26]fn)/filerr ⍝ Load the file
        text[(text∊⎕TC)/⍳⍴text]←' '    ⍝ Control characters to spaces
        text[(text='-')/⍳⍴text]←'¯'    ⍝ Negative numbers get high minus
        M←⍎text             ⍝ The memory starts with the numbers in the text
        pc←0                ⍝ Program counter starts at PC

instr:  (A B C)←3↑pc↓M        ⍝ Read instruction
        M←'(1+A⌈B⌈C⌈⍴M)↑M'⎕EA'M⊣M[A,B,C]' ⍝ Extend the array if necessary
        pc←pc+3               ⍝ PC is incremented by 3
        →(A=¯1)/in            ⍝ If A=-1, read input
        →(B=¯1)/out           ⍝ If B=-1, write output
        →(0<M[B]←M[B]-M[A])/instr   ⍝ Do SUBLEQ instruction
        pc←C                  ⍝ Set PC if necessary
        →(C≥0)×instr          ⍝ Next instruction if C≥0

in:     X←(M[B]←1⎕FIO[41]1)⎕FIO[42]1 ⋄ →instr
out:    X←M[A]⎕FIO[42]1 ⋄ →instr

usage:  'subleq.apl <file> - Run the SUBLEQ program in <file>' ⋄ →0
filerr: 'Error loading: ',fn ⋄ →0
∇

Subleq
)OFF


	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
	@@@	ARM SUBLEQ for Linux			@@@
	@@@	Word size is 32 bits. The program is	@@@
	@@@	given 8 MB (2 Mwords) to run in.	@@@
	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.text
.global	_start
	@@@ Linux syscalls
.equ	exit,	1
.equ	read,	3
.equ	write,	4
.equ	open,	5
_start:	pop	{r6}		@ Retrieve amount of arguments
	cmp	r6,#2		@ There should be exactly 2 (incl program)
	ldrne	r1,=usage	@ Otherwise, print usage and stop
	bne 	die
	pop	{r0,r1}		@ Retrieve filename
	mov	r0,r1
	mov	r1,#0		@ Try to open the file in read mode
	mov	r2,#0
	mov	r7,#open
	swi	#0
	movs	r5,r0		@ File handle in R5
	ldrmi	r1,=efile	@ If the file can't be opened, error
	bmi	die
	ldr	r8,=prog	@ R8 = pointer into program
	mov	r6,#0		@ At the beginning, there is no data
rdnum:	bl	fchar		@ Skip past whitespace
	cmp	r0,#32
	bls 	rdnum
	mov	r9,#0		@ R9 = current number being read
	subs	r10,r0,#'-	@ R10 is zero if number is negative
	bleq	fchar		@ And get next character
1:	sub	r0,r0,#'0	@ Subtract ASCII 0
	cmp	r0,#9
	ldrhi	r1,=echar
	bhi	die		@ Invalid digit = error
	mov	r1,#10
	mla	r0,r9,r1,r0	@ Multiply accumulator by 10 and add digit
	mov	r9,r0
	bl	fchar		@ Get next character
	cmp 	r0,#32		@ If it isn't whitespace...
	bhi	1b		@ ...then it's the next digit
	tst	r10,r10		@ If the number should be negative,
	rsbeq	r9,r9,#0	@ ...then negate it
	str	r9,[r8],#4	@ Store the number
	b	rdnum		@ And get the next number.
setup:	ldr	r0,=prog	@ Zero out the rest of program memory
	sub	r0,r8,r0	@ Zero to 8-word (32-byte) boundary
	orr	r0,r0,#31	@ Find address of last byte within
	add	r0,r0,r8	@ current 31-byte block
	mov	r1,#0		@ R1 = zero to write
1:	str	r1,[r8],#4	@ Write zeroes,
	cmp	r0,r8		@ until boundary reached.
	blo	1b
	mov	r0,#0		@ 8 words of zeroes in r0-r7
	umull	r2,r3,r0,r1	@ A trick to produce 2 zero words in one
	umull	r4,r5,r0,r1	@ go: 0*0 = 0, long multiplication
	umull	r6,r7,r0,r1	@ results in 2 words.
	ldr	r9,=mem_end
2:	stmia	r8!,{r0-r7}	@ Write 8 zero words at a time
	cmp	r8,r9		@ Are we at mem_end yet?
	blo	2b		@ If not, keep going
	ldr	r8,=prog	@ R8 = IP, starts at beginning
	ldr	r6,=prog	@ R6 = base address for memory
	mov	r12,#0xFFFF	@ 0x1FFFFF = address mask
	movt	r12,#0x1F
instr:	ldmia	r8!,{r9-r11}	@ R9, R10, R11 = A, B, C
	cmp	r9,#-1		@ If A=-1, get character
	beq	rchar
	cmp	r10,#-1		@ Otherwise, if B=-1, write character
	beq	wchar
	and	r9,r9,r12	@ Keep addresses within 2 Mwords
	and	r10,r10,r12
	ldr	r0,[r6,r9,lsl #2]	@ Grab [A] and [B]
	ldr	r1,[r6,r10,lsl #2]
	subs	r1,r1,r0		@ Subtract
	str	r1,[r6,r10,lsl #2]	@ Store back in [B]
	cmpmi	r0,r0		@ Set zero flag if negative
	bne	instr		@ If result is positive, next instruction
	lsls	r8,r11,#2	@ Otherwise, C becomes the new IP
	add	r8,r8,r6
	bpl	instr		@ If result is positive, keep going
	mov	r0,#0		@ Otherwise, we exit
	mov	r7,#exit
	swi	#0
	@@@ 	Read character into [B]
rchar:	mov	r0,#0		@ STDIN
	and	r10,r10,r12	@ Address of B
	add	r10,r6,r10,lsl #2	@ Kept in R10 out of harm's way
	mov	r1,r10
	mov	r2,#1		@ Read one character
	mov	r7,#read
	swi	#0
	cmp	r0,#1		@ We should have received 1 byte
	movne	r1,#-1		@ If not, write -1
	ldreqb	r1,[r10]	@ Otherwise, blank out the top 3 bytes
	str	r1,[r10]
	b	instr
	@@@	Write character in [A]
wchar:	mov	r0,#1		@ STDIN
	and	r1,r9,r12	@ Address of [A]
	add	r1,r6,r1,lsl #2
	mov	r2,#1		@ Write one character
	mov	r7,#write
	swi	#0
	b	instr
	@@@	Read character from file into R0. Tries to read more
	@@@	if the buffer is empty (as given by R6). Buffer in R11.
fchar:	tst	r6,r6		@ Any bytes in the buffer?
	ldrneb	r0,[r11],#1	@ If so, return next character from buffer
	subne	r6,r6,#1
	bxne	lr
	mov	r12,lr		@ Save link register
	mov	r0,r5		@ If not, read from file into buffer
	ldr	r1,=fbuf
	mov	r2,#0x400000
	mov	r7,#read
	swi	#0
	movs	r6,r0		@ Amount of bytes in r6
	beq	setup		@ If no more bytes, start the program
	ldr	r11,=fbuf	@ Otherwise, R11 = start of buffer
	mov	lr,r12
	b	fchar
	@@@	Write a zero-terminated string, in [r1], to stdout.
print:	push	{lr}
	mov	r2,r1
1:	ldrb	r0,[r2],#1	@ Get character and advance pointer
	tst	r0,r0		@ Zero yet?
	bne	1b		@ If not, keep scanning
	sub	r2,r2,r1	@ If so, calculate length
	mov	r0,#1		@ STDOUT
	mov	r7,#write	@ Write to STDOUT
	swi	#0
	pop	{pc}
	@@@	Print error message in [r1], then end.
die:	bl	print
	mov	r0,#255
	mov	r7,#exit
	swi	#0
usage:	.asciz	"Usage: subleq <filename>\n"
efile:	.asciz	"Cannot open file\n"
echar:	.asciz	"Invalid number in file\n"
	@@@ Memory
.bss
.align	4
prog:	.space	0x400000	@ Lower half of program memory
fbuf:	.space	0x400000	@ File buffer and top half of program memory
mem_end	=	.


# syntax: GAWK -f SUBLEQ.AWK SUBLEQ.TXT
# converted from Java
BEGIN {
    instruction_pointer = 0
}
{   printf("%s\n",$0)
    for (i=1; i<=NF; i++) {
      if ($i == "*") {
        ncomments++
        break
      }
      mem[instruction_pointer++] = $i
    }
}
END {
    if (instruction_pointer == 0) {
      print("error: nothing to run")
      exit(1)
    }
    printf("input: %d records, %d instructions, %d comments\n\n",NR,instruction_pointer,ncomments)
    instruction_pointer = 0
    do {
      a = mem[instruction_pointer]
      b = mem[instruction_pointer+1]
      if (a == -1) {
        getline <"con"
        mem[b] = $1
      }
      else if (b == -1) {
        printf("%c",mem[a])
      }
      else {
        mem[b] -= mem[a]
        if (mem[b] < 1) {
          instruction_pointer = mem[instruction_pointer+2]
          continue
        }
      }
      instruction_pointer += 3
    } while (instruction_pointer >= 0)
    exit(0)
}


str: "abcdefgh"
n: 2
m: 3

; starting from n=2 characters in and m=3 in length
print slice str n-1 n+m-2

; starting from n characters in, up to the end of the string
print slice str n-1 (size str)-1

; whole string minus last character
print slice str 0 (size str)-2

; starting from a known character char="d"
; within the string and of m length
print slice str index str "d" m+(index str "d")-1

; starting from a known substring chars="cd"
; within the string and of m length
print slice str index str "cd" m+(index str "cd")-1


String := "abcdefghijklmnopqrstuvwxyz"
; also: String = abcdefghijklmnopqrstuvwxyz
n := 12
m := 5

; starting from n characters in and of m length;
subString := SubStr(String, n, m)
; alternative:  StringMid, subString, String, n, m
MsgBox % subString

; starting from n characters in, up to the end of the string;
subString := SubStr(String, n)
; alternative:  StringMid, subString, String, n
MsgBox % subString

; whole string minus last character;
StringTrimRight, subString, String, 1
; alternatives: subString := SubStr(String, 1, StrLen(String) - 1)
;               StringMid, subString, String, 1, StrLen(String) - 1
MsgBox % subString

; starting from a known character within the string and of m length;
findChar := "q"
subString := SubStr(String, InStr(String, findChar), m)
; alternatives: RegExMatch(String, findChar . ".{" . m - 1 . "}", subString)
;               StringMid, subString, String, InStr(String, findChar), m
MsgBox % subString

; starting from a known character within the string and of m length;
findString := "pq"
subString := SubStr(String, InStr(String, findString), m)
; alternatives: RegExMatch(String, findString . ".{" . m - StrLen(findString) . "}", subString)
;               StringMid, subString, String, InStr(String, findString), m
MsgBox % subString


10 DEFINT A-Z: DIM M(8192)
20 INPUT "Filename";F$
30 OPEN "I",1,F$
40 GOTO 70
50 INPUT #1,M(I)
60 I=I+1
70 IF EOF(1) THEN CLOSE(1) ELSE GOTO 50
80 I=0
90 A=M(I): B=M(I+1): C=M(I+2): I=I+3
100 IF A=-1 GOTO 150 ELSE IF B=-1 GOTO 190
120 M(B) = M(B) - M(A)
130 IF M(B)<=0 THEN I=C
140 IF I>=0 GOTO 90 ELSE END
150 A$ = INPUT$(1): PRINT A$;
160 C = ASC(A$): IF C=13 THEN C=10
170 M(B) = C
180 GOTO 90
190 IF M(A)=10 THEN PRINT ELSE PRINT(CHR$(M(A) AND 255));
200 GOTO 90


REM >subleq
DIM memory%(255)
counter% = 0
INPUT "SUBLEQ> " program$
WHILE INSTR(program$, " ")
    memory%(counter%) = VAL(LEFT$(program$, INSTR(program$, " ") - 1))
    program$ = MID$(program$, INSTR(program$, " ") + 1)
    counter% += 1
ENDWHILE
memory%(counter%) = VAL(program$)
counter% = 0
REPEAT
    a% = memory%(counter%)
    b% = memory%(counter% + 1)
    c% = memory%(counter% + 2)
    counter% += 3
    IF a% = -1 THEN
        INPUT "SUBLEQ> " character$
        memory%(b%) = ASC(character$)
    ELSE
        IF b% = -1 THEN
            PRINT CHR$(memory%(a%));
        ELSE
            memory%(b%) = memory%(b%) - memory%(a%)
            IF memory%(b%) <= 0 THEN counter% = c%
        ENDIF
    ENDIF
UNTIL counter% < 0


BEGIN {
	str = "abcdefghijklmnopqrstuvwxyz"
	n = 12
	m = 5

	print substr(str, n, m)
	print substr(str, n)
	print substr(str, 1, length(str) - 1)
	print substr(str, index(str, "q"), m)
	print substr(str, index(str, "pq"), m)
}


Lbl SUB1
0→{r₁+r₂+r₃}
r₁+r₂
Return

Lbl SUB2
r₁+r₂
Return

Lbl SUB3
0→{r₁+length(r₁)-1}
r₁
Return

Lbl SUB4
inData(r₂,r₁)-1→I
0→{r₁+I+r₃}
r₁+I
Return


DIM baseString AS STRING, subString AS STRING, findString AS STRING
DIM m AS INTEGER, n AS INTEGER

baseString = "abcdefghijklmnopqrstuvwxyz"
n = 12
m = 5

' starting from n characters in and of m length;
subString = MID$(baseString, n, m)
PRINT subString

' starting from n characters in, up to the end of the string;
subString = MID$(baseString, n)
PRINT subString

' whole string minus last character;
subString = LEFT$(baseString, LEN(baseString) - 1)
PRINT subString

' starting from a known character within the string and of m length;
subString = MID$(baseString, INSTR(baseString, "b"), m)
PRINT subString

' starting from a known substring within the string and of m length.
findString = "pq"
subString = MID$(baseString, INSTR(baseString, findString), m)
PRINT subString


get "libhdr"

// Read a string
let reads(v) be
$(  let ch = ?
    v%0 := 0
    ch := rdch()
    until ch = '*N' do
    $(  v%0 := v%0 + 1
        v%(v%0) := ch
        ch := rdch()
    $)
$)

// Try to read a number, fail on EOF
// (Alas, the included READN just returns 0 and that's a valid number)
let readnum(n) = valof
$(  let neg, ch = false, ?
    !n := 0
    $(  ch := rdch()
        if ch = endstreamch then resultis false
    $) repeatuntil ch = '-' | '0' <= ch <= '9'
    if ch = '-' then
    $(  neg := true
        ch := rdch()
    $)
    while '0' <= ch <= '9' do
    $(  !n := !n * 10 + ch - '0'
        ch := rdch()
    $)
    if neg then !n := -!n
    resultis true
$)

// Read SUBLEQ code
let readfile(file, v) = valof
$(  let i, oldin = 0, input()
    selectinput(file)
    while readnum(v+i) do i := i + 1
    endread()
    selectinput(oldin)
    resultis i
$)

// Run SUBLEQ code
let run(v) be
$(  let ip = 0
    until ip < 0 do
    $(  let a, b, c = v!ip, v!(ip+1), v!(ip+2)
        ip := ip + 3
        test a=-1
            then v!b := rdch()
        else test b=-1
            then wrch(v!a)
        else
        $(  v!b := v!b - v!a
            if v!b <= 0 then ip := c
        $)
    $)
$)

let start() be
$(  let filename = vec 64
    let file = ?

    writes("Filename? ")
    reads(filename)
    file := findinput(filename)
    test file = 0 then
        writes("Cannot open file.*N")
    else
    $(  let top = maxvec()
        let mem = getvec(top)
        let progtop = readfile(file, mem)
        for i = progtop to top do mem!i := 0
        run(mem)
        freevec(mem)
    $)
$)


# Helpers
_while_ ← {𝔽⍟𝔾∘𝔽_𝕣_𝔾∘𝔽⍟𝔾𝕩}
ToNum ← {neg ← '-'=⊑𝕩 ⋄ (¯1⋆neg)×10⊸×⊸+˜´·⌽-⟜'0'neg↓𝕩}

Subleq ← {
  𝕊 memory:
  {
    𝕊 ip‿mem:
    {
      ¯1‿b‿·: ⟨ip+3, (@-˜•[email protected])⌾(b⊸⊑) mem⟩;
      a‿¯1‿·: •Out @+a⊑mem, ⟨ip+3, mem⟩;
      a‿b‿c : d ← b-○(⊑⟜mem)a, ⟨(0<d)⊑⟨c, ip+3⟩, d⌾(b⊸⊑) mem⟩
    } mem⊏˜ip+↕3
  }  _while_ {𝕊 ip‿mem: ip≥0} 0‿memory
}

Subleq ToNum¨•args


#include <stdlib.h>
#include <stdio.h>

void
subleq(int *code)
{
	int ip = 0, a, b, c, nextIP;
	char ch;
	while(0 <= ip) {
		nextIP = ip + 3;
		a = code[ip];
		b = code[ip + 1];
		c = code[ip + 2];
		if(a == -1) {
			scanf("%c", &ch);
			code[b] = (int)ch;
		} else if(b == -1) {
			printf("%c", (char)code[a]);
		} else {
			code[b] -= code[a];
			if(code[b] <= 0)
				nextIP = c;
		}
		ip = nextIP;
	}
}

void
processFile(char *fileName)
{
	int *dataSet, i, num;
	FILE *fp = fopen(fileName, "r");
	fscanf(fp, "%d", &num);
	dataSet = (int *)malloc(num * sizeof(int));
	for(i = 0; i < num; i++)
		fscanf(fp, "%d", &dataSet[i]);
	fclose(fp);
	subleq(dataSet);
}

int
main(int argC, char *argV[])
{
	if(argC != 2)
		printf("Usage : %s <subleq code file>\n", argV[0]);
	else
		processFile(argV[1]);
	return 0;
}


   5↑3↓"Marshmallow"
"shmal"
   3↓"Marshmallow"
"shmallow"
   ¯1↓"Marshmallow"
"Marshmallo"
   (⊑∘/'m'⊸=)⊸↓"Marshmallow"
"mallow"
   (⊑∘/"sh"⊸⍷)⊸↓"Marshmallow"
"shmallow"


( (basestring = "The five boxing wizards jump quickly")
& (n = 10)
& (m = 5)

  { starting from n characters in and of m length: }
& @(!basestring:? [(!n+-1) ?substring [(!n+!m+-1) ?)
& out$!substring

  { starting from n characters in, up to the end of the string: }
& @(!basestring:? [(!n+-1) ?substring)
& out$!substring

  { whole string minus last character: }
& @(!basestring:?substring [-2 ?)
& out$!substring

  { starting from a known character within the string and of m length: }
& (char = "w")
& @(!basestring:? ([?p !char ?: ?substring [(!p+!m) ?))
& out$!substring

  { starting from a known substring within the string and of m length: }
& (find = "iz")
& @(!basestring:? ([?p !find ?: ?substring [(!p+!m) ?))
& out$!substring
&
)


blsq ) "RosettaCode"5.+
"Roset"
blsq ) "RosettaCode"5.+2.-
"set"
blsq ) "RosettaCode""set"ss
2
blsq ) "RosettaCode"J"set"ss.-
"settaCode"
blsq ) "RosettaCode"~]
"RosettaCod"
blsq ) "RosettaCode"[-
"osettaCode"


using System;

namespace Subleq {
    class Program {
        static void Main(string[] args) {
            int[] mem = {
                15, 17, -1, 17, -1, -1, 16, 1, -1, 16,
                3, -1, 15, 15, 0, 0, -1, 72, 101, 108,
                108, 111, 44, 32, 119, 111, 114, 108, 100, 33,
                10, 0,
            };

            int instructionPointer = 0;

            do {
                int a = mem[instructionPointer];
                int b = mem[instructionPointer + 1];

                if (a == -1) {
                    mem[b] = Console.Read();
                }
                else if (b == -1) {
                    Console.Write((char)mem[a]);
                }
                else {
                    mem[b] -= mem[a];
                    if (mem[b] < 1) {
                        instructionPointer = mem[instructionPointer + 2];
                        continue;
                    }
                }

                instructionPointer += 3;
            } while (instructionPointer >= 0);
        }
    }
}


#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>

class subleq {
public:
    void load_and_run( std::string file ) {
        std::ifstream f( file.c_str(), std::ios_base::in );
        std::istream_iterator<int> i_v, i_f( f );
        std::copy( i_f, i_v, std::back_inserter( memory ) );
        f.close();
        run();
    }

private:
    void run() {
        int pc = 0, next, a, b, c;
        char z;
        do {
            next = pc + 3;
            a = memory[pc]; b = memory[pc + 1]; c = memory[pc + 2];
            if( a == -1 ) {
                std::cin >> z; memory[b] = static_cast<int>( z );
            } else if( b == -1 ) {
                std::cout << static_cast<char>( memory[a] );
            } else {
                memory[b] -= memory[a];
                if( memory[b] <= 0 ) next = c;
            }
            pc = next;
        } while( pc >= 0 );
    }

    std::vector<int> memory;
};

int main( int argc, char* argv[] ) {
    subleq s;
    if( argc > 1 ) {
        s.load_and_run( argv[1] );
    } else {
        std::cout << "usage: subleq <filename>\n";
    }
    return 0;
}


/*
 * RosettaCode: Substring, C89
 *
 * In this task display a substring: starting from n characters in and of m
 * length; starting from n characters in, up to the end of the string; whole
 * string minus last character; starting from a known character within the
 * string and of m length; starting from a known substring within the string
 * and of m length.
 *
 * This example program DOES NOT make substrings. The program simply displays
 * certain parts of the input string.
 *
 */
#define _CRT_SECURE_NO_WARNINGS /* MSVS compilers need this */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
 * Put no more than m characters from string to standard output.
 *
 * It is worth noting that printf("%*s",width,string) does not limit the number
 * of characters to be printed.
 *
 * @param string null terminated string
 * @param m      number of characters to display
 */
void putm(char* string, size_t m)
{
    while(*string && m--)
        putchar(*string++);
}

int main(void)
{

    char string[] =
        "Programs for other encodings (such as 8-bit ASCII, or EUC-JP)."

    int n = 3;
    int m = 4;
    char knownCharacter = '(';
    char knownSubstring[] = "encodings";

    putm(string+n-1, m );                       putchar('\n');
    puts(string+n+1);                           putchar('\n');
    putm(string, strlen(string)-1);             putchar('\n');
    putm(strchr(string, knownCharacter), m );   putchar('\n');
    putm(strstr(string, knownSubstring), m );   putchar('\n');

    return EXIT_SUCCESS;
}


#include <iostream>
#include <string>

int main()
{
  std::string s = "0123456789";

  int const n = 3;
  int const m = 4;
  char const c = '2';
  std::string const sub = "456";

  std::cout << s.substr(n, m)<< "\n";
  std::cout << s.substr(n) << "\n";
  std::cout << s.substr(0, s.size()-1) << "\n";
  std::cout << s.substr(s.find(c), m) << "\n";
  std::cout << s.substr(s.find(sub), m) << "\n";
}


% Read numbers from a stream
read_nums = iter (s: stream) yields (int)
    while true do
        c: char := stream$getc(s)
        while c~='-' & ~(c>='0' & c<='9') do
            c := stream$getc(s)
        end
        acc: int := 0
        neg: bool
        if c='-' then
            neg := true
            c := stream$getc(s)
        else
            neg := false
        end
        while c>='0' & c<='9' do
            acc := acc*10 + char$c2i(c) - char$c2i('0')
            c := stream$getc(s)
            except when end_of_file: break end
        end
        if neg then acc := -acc end
        yield(acc)
    end except when end_of_file: end
end read_nums

% Auto-resizing array
mem = cluster is new, load, fetch, store
    rep = array[int]

    new = proc () returns (cvt)
        return(rep$predict(0,2**9))
    end new

    fill_to = proc (a: rep, lim: int)
        while rep$high(a) < lim do rep$addh(a,0) end
    end fill_to

    fetch = proc (a: cvt, n: int) returns (int) signals (bounds)
        fill_to(a,n)
        return(a[n]) resignal bounds
    end fetch

    store = proc (a: cvt, n: int, v: int) signals (bounds)
        fill_to(a,n)
        a[n] := v resignal bounds
    end store

    load = proc (a: cvt, s: stream)
        i: int := 0
        for n: int in read_nums(s) do
            up(a)[i] := n
            i := i + 1
        end
    end load
end mem

% Run a Subleq program
subleq = proc (m: mem, si, so: stream)
    ip: int := 0
    while ip >= 0 do
        a: int := m[ip]
        b: int := m[ip+1]
        c: int := m[ip+2]
        ip := ip + 3
        if a=-1 then m[b] := char$c2i(stream$getc(si))
        elseif b=-1 then stream$putc(so,char$i2c(m[a] // 256))
        else
            m[b] := m[b] - m[a]
            if m[b] <= 0 then ip := c end
        end
    end
end subleq

start_up = proc ()
    pi: stream := stream$primary_input()
    po: stream := stream$primary_output()

    args: sequence[string] := get_argv()
    if sequence[string]$size(args) ~= 1 then
        stream$putl(stream$error_output(), "Usage: subleq file_name")
        return
    end

    fname: file_name := file_name$parse(sequence[string]$bottom(args))
    file: stream := stream$open(fname, "read")
    m: mem := mem$new()
    mem$load(m, file)
    stream$close(file)
    subleq(m, pi, po)
end start_up


identification division.
program-id. subleq-program.
data division.
working-storage section.
01  subleq-source-code.
    05 source-string                      pic x(2000).
01  subleq-virtual-machine.
    05 memory-table.
        10 memory                         pic s9999
            occurs 500 times.
    05 a                                  pic s9999.
    05 b                                  pic s9999.
    05 c                                  pic s9999.
    05 instruction-pointer                pic s9999.
    05 input-output-character             pic x.
01  working-variables.
    05 loop-counter                       pic 9999.
    05 instruction-counter                pic 9999.
    05 string-pointer                     pic 9999.
    05 adjusted-index-a                   pic 9999.
    05 adjusted-index-b                   pic 9999.
    05 output-character-code              pic 9999.
procedure division.
read-source-paragraph.
    accept source-string from console.
    display 'READING SUBLEQ PROGRAM... ' with no advancing.
    move 1 to string-pointer.
    move 0 to instruction-counter.
    perform split-source-paragraph varying loop-counter from 1 by 1
        until loop-counter is greater than 500
        or string-pointer is greater than 2000.
    display instruction-counter with no advancing.
    display ' WORDS READ.'.
execute-paragraph.
    move 1 to instruction-pointer.
    move 0 to instruction-counter.
    display 'BEGINNING RUN... '.
    display ''.
    perform execute-instruction-paragraph
        until instruction-pointer is negative.
    display ''.
    display 'HALTED AFTER ' instruction-counter ' INSTRUCTIONS.'.
    stop run.
execute-instruction-paragraph.
    add 1 to instruction-counter.
    move memory(instruction-pointer) to a.
    add 1 to instruction-pointer.
    move memory(instruction-pointer) to b.
    add 1 to instruction-pointer.
    move memory(instruction-pointer) to c.
    add 1 to instruction-pointer.
    if a is equal to -1 then perform input-paragraph.
    if b is equal to -1 then perform output-paragraph.
    if a is not equal to -1 and b is not equal to -1
        then perform subtraction-paragraph.
split-source-paragraph.
    unstring source-string delimited by all spaces
        into memory(loop-counter)
        with pointer string-pointer.
    add 1 to instruction-counter.
input-paragraph.
    display '> ' with no advancing.
    accept input-output-character from console.
    add 1 to b giving adjusted-index-b.
    move function ord(input-output-character)
        to memory(adjusted-index-b).
    subtract 1 from memory(adjusted-index-b).
output-paragraph.
    add 1 to a giving adjusted-index-a.
    add 1 to memory(adjusted-index-a) giving output-character-code.
    move function char(output-character-code)
        to input-output-character.
    display input-output-character with no advancing.
subtraction-paragraph.
    add 1 to c.
    add 1 to a giving adjusted-index-a.
    add 1 to b giving adjusted-index-b.
    subtract memory(adjusted-index-a) from memory(adjusted-index-b).
    if memory(adjusted-index-b) is equal to zero
        or memory(adjusted-index-b) is negative
        then move c to instruction-pointer.


using System;
namespace SubString
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "0123456789";
            const int n = 3;
            const int m = 2;
            const char c = '3';
            const string z = "345";

            // A: starting from n characters in and of m length;
            Console.WriteLine(s.Substring(n, m));
            // B: starting from n characters in, up to the end of the string;
            Console.WriteLine(s.Substring(n, s.Length - n));
            // C: whole string minus the last character;
            Console.WriteLine(s.Substring(0, s.Length - 1));
            // D: starting from a known character within the string and of m length;
            Console.WriteLine(s.Substring(s.IndexOf(c), m));
            // E: starting from a known substring within the string and of m length.
            Console.WriteLine(s.Substring(s.IndexOf(z), m));
        }
    }
}


(def string "alphabet")
(def n 2)
(def m 4)
(def len (count string))

;starting from n characters in and of m length;
(println
 (subs string n (+ n m)))              ;phab
;starting from n characters in, up to the end of the string;
(println
 (subs string n))                      ;phabet
;whole string minus last character;
(println
 (subs string 0 (dec len)))            ;alphabe
;starting from a known character within the string and of m length;
(let [pos (.indexOf string (int \l))]
  (println
   (subs string pos (+ pos m))))     ;lpha
;starting from a known substring within the string and of m length.
(let [pos (.indexOf string "ph")]
  (println
   (subs string pos (+ pos m))))      ;phab


(defun run (memory)
  (loop for pc = 0 then next-pc
        until (minusp pc)
        for a = (aref memory pc)
        for b = (aref memory (+ pc 1))
        for c = (aref memory (+ pc 2))
        for next-pc = (cond ((minusp a)
                             (setf (aref memory b) (char-code (read-char)))
                             (+ pc 3))
                            ((minusp b)
                             (write-char (code-char (aref memory a)))
                             (+ pc 3))
                            ((plusp (setf (aref memory b)
                                          (- (aref memory b) (aref memory a))))
                             (+ pc 3))
                            (t c))))

(defun main ()
  (let ((memory (vector 15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72
                        101 108 108 111 44 32 119 111 114 108 100 33 10 0)))
    (run memory)))


import std.stdio;

void main() {
    int[] mem = [
         15,  17,  -1,  17,  -1,  -1,  16,   1,
         -1,  16,   3,  -1,  15,  15,   0,   0,
         -1,  72, 101, 108, 108, 111,  44,  32,
        119, 111, 114, 108, 100,  33,  10,   0
    ];

    int instructionPointer = 0;

    do {
        int a = mem[instructionPointer];
        int b = mem[instructionPointer + 1];

        if (a == -1) {
            int input;
            readf!" %d"(input);
            mem[b] = input;
        } else if (b == -1) {
            write(cast(char) mem[a]);
        } else {
            mem[b] -= mem[a];
            if (mem[b] < 1) {
                instructionPointer = mem[instructionPointer + 2];
                continue;
            }
        }

        instructionPointer += 3;
    } while (instructionPointer >= 0);
}


       identification division.
       program-id. substring.

       environment division.
       configuration section.
       repository.
           function all intrinsic.

       data division.
       working-storage section.
       01 original.
          05 value "this is a string".
       01 starting  pic 99 value 3.
       01 width     pic 99 value 8.
       01 pos       pic 99.
       01 ender     pic 99.
       01 looking   pic 99.
       01 indicator pic x.
          88 found  value high-value when set to false is low-value.
       01 look-for  pic x(8).

       procedure division.
       substring-main.

       display "Original |" original "|, n = " starting " m = " width
       display original(starting : width)
       display original(starting :)
       display original(1 : length(original) - 1)

       move "a" to look-for
       move 1 to looking
       perform find-position
       if found
           display original(pos : width)
       end-if

       move "is a st" to look-for
       move length(trim(look-for)) to looking
       perform find-position
       if found
           display original(pos : width)
       end-if
       goback.

       find-position.
       set found to false
       compute ender = length(original) - looking
       perform varying pos from 1 by 1 until pos > ender
           if original(pos : looking) equal look-for then
               set found to true
               exit perform
           end-if
       end-perform
       .

       end program substring.


program SubleqTest;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

var
  mem: array of Integer;
  instructionPointer: Integer;
  a, b: Integer;

begin
  mem := [15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1, 72,
    101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 10, 0];
  instructionPointer := 0;

  repeat
    a := mem[instructionPointer];
    b := mem[instructionPointer + 1];

    if a = -1 then
    begin
      read(mem[b]);
    end
    else if b = -1 then
    begin
      write(ansichar(mem[a]));
    end
    else
    begin
      mem[b] := mem[b] - mem[a];
      if (mem[b] < 1) then
      begin
        instructionPointer := mem[instructionPointer + 2];
        Continue;
      end;
    end;
    inc(instructionPointer, 3);
  until (instructionPointer >= length(mem)) or (instructionPointer < 0);
  readln;
end.


\util.g

proc nonrec rdch() byte:
    char c;
    if read(c) then
        pretend(c, byte)
    else
        case ioerror()
            incase CH_MISSING: readln(); 10
            default: 0
        esac
    fi
corp

proc nonrec wrch(byte b) void:
    if b=10
        then writeln()
        else write(pretend(b, char))
    fi
corp

proc nonrec main() void:
    [16384] int mem;
    file() srcfile;
    channel input text srcch;
    *char fname;
    int a, b, c, i;
    byte iob;

    BlockFill(pretend(&mem[0], *byte), sizeof(byte), 0);

    fname := GetPar();
    if fname = nil then
        writeln("usage: SUBLEQ filename");
        exit(1);
    fi;

    if not open(srcch, srcfile, fname) then
        writeln("Cannot open input file");
        exit(1)
    fi;

    i := 0;
    while read(srcch; mem[i]) do i := i + 1 od;
    close(srcch);

    i := 0;
    while i>=0 do
        a := mem[i];
        b := mem[i+1];
        c := mem[i+2];
        i := i + 3;

        if a=-1 then mem[b] := rdch()
        elif b=-1 then wrch(mem[a])
        else
            mem[b] := mem[b] - mem[a];
            if mem[b] <= 0 then i := c fi
        fi
    od
corp


<cfoutput>
	<cfset str = "abcdefg">
	<cfset n = 2>
	<cfset m = 3>

	<!--- Note: In CF index starts at 1 rather than 0
	starting from n characters in and of m length --->
	#mid( str, n, m )#
	<!--- starting from n characters in, up to the end of the string --->
	<cfset countFromRight = Len( str ) - n + 1>
	#right( str, countFromRight )#
	<!--- whole string minus last character --->
	<cfset allButLast = Len( str ) - 1>
	#left( str, allButLast )#
	<!--- starting from a known character within the string and of m length --->
	<cfset startingIndex = find( "b", str )>
	#mid( str, startingIndex, m )#
	<!--- starting from a known substring within the string and of m length --->
	<cfset startingIndexSubString = find( "bc", str )>
	#mid( str, startingIndexSubString, m )#

</cfoutput>


(let ((string "0123456789")
      (n 2)
      (m 3)
      (start #\5)
      (substring "34"))
  (list (subseq string n (+ n m))
        (subseq string n)
        (subseq string 0 (1- (length string)))
        (let ((pos (position start string)))
          (subseq string pos (+ pos m)))
        (let ((pos (search substring string)))
          (subseq string pos (+ pos m)))))


create M 32 cells allot

: enter refill drop parse-word evaluate ; : M[] cells M + ;
: init M 32 cells bounds ?do i ! 1 cells +loop ;
: b-a+! dup dup cell+ @ M[] swap @ M[] @ negate over +! ;
: c b-a+! @ 1- 0< if 2 cells + @ else swap 3 + then nip ;
: b? dup cell+ @ 0< if @ M[] @ emit 3 + else c then ;
: a? dup @ 0< if cell+ @ M[] enter swap ! 3 + else b? then ;
: subleq cr 0 begin dup 1+ 0> while dup M[] a? repeat drop ;

0 10 33 100 108 114 111 119 32 44 111 108 108 101 72
-1 0 0 15 15 -1 3 16 -1 1 16 -1 -1 17 -1 17 15

init subleq


      PROGRAM SUBLEQ0	!Simulates a One-Instruction computer, with Subtract and Branch if <= 0.
      INTEGER LOTS,LOAD		!Document some bounds.
      PARAMETER (LOTS = 36, LOAD = 31)	!Sufficient for the example.
      INTEGER IAR, MEM(0:LOTS)		!The basic storage of a computer. IAR could be in memory too.
      INTEGER ABC(3),A,B,C		!A hardware register. Could use INTEGER*1 for everything...
      EQUIVALENCE (ABC(1),A),(ABC(2),B),(ABC(3),C)	!It has components.
      INTEGER INITIAL(0:LOAD)		!There is no sign of a bootstrap loader sequence!
      DATA INITIAL/15,17,-1,17,-1,-1,16,1,-1,16,3,-1,15,15,0,0,-1,	!These are operations, it so happens.
     1          72,101,108,108,111,44,32,119,111,114,108,100,33,10,0/	!And these happen to be ASCII character code numbers.
Core memory initialisation.
      MEM = -66			!Accessing uninitialised memory is improper. This might cause hiccoughs..
      MEM(0:LOAD) = INITIAL	!No bootstrap!
      IAR = 0			!The Instruction Address Register starts at the start.
Commence execution of the current instruction.
  100 ABC = MEM(IAR:IAR + 2)	!Load the three-word instruction.
      IAR = IAR + 3		!Advance IAR accordingly.
      IF (A .EQ. -1) THEN	!Decode the instruction as per the design.
        WRITE (6,102)			!Supply a prompt, otherwise, obscurity results.
  102   FORMAT (" A number:",$)		!But, that will make a mess of the layout.
        READ (5,*) MEM(B)		!The specified action is to read as a number.
      ELSE IF (B .EQ. -1) THEN	!This is for output.
        WRITE (6,103) CHAR(MEM(A))	!As specified, interpret a number as a character.
  103   FORMAT (A1,$)			!The $, obviously, states: do not end the line and start the next.
      ELSE			!And this is a two-part action.
        MEM(B) = MEM(B) - MEM(A)	!Perform arithmetic.
        IF (MEM(B).LE.0) IAR = C	!And based on the result, maybe a GO TO.
      END IF			!So much for decoding.
      IF (IAR.GE.0) GO TO 100	!Keep at it.
      END	!That was simple.


MODULE Substrings;
IMPORT StdLog,Strings;

PROCEDURE Do*;
CONST
	aStr = "abcdefghijklmnopqrstuvwxyz";
VAR
	str: ARRAY 128 OF CHAR;
	pos: INTEGER;
BEGIN
	Strings.Extract(aStr,3,10,str);
	StdLog.String("from 3, 10 characters:> ");StdLog.String(str);StdLog.Ln;
	Strings.Extract(aStr,3,LEN(aStr) - 3,str);
	StdLog.String("from 3, until the end:> ");StdLog.String(str);StdLog.Ln;
	Strings.Extract(aStr,0,LEN(aStr) - 1,str);
	StdLog.String("whole string but last:> ");StdLog.String(str);StdLog.Ln;
	Strings.Find(aStr,'d',0,pos);
	Strings.Extract(aStr,pos + 1,10,str);
	StdLog.String("from 'd', 10 characters:> ");StdLog.String(str);StdLog.Ln;
	Strings.Find(aStr,"de",0,pos);
	Strings.Extract(aStr,pos + LEN("de"),10,str);
	StdLog.String("from 'de', 10 characters:> ");StdLog.String(str);StdLog.Ln;
END Do;

END Substrings.


def substring_demo(string, n, m, known_character, known_substring)
    n -= 1

    puts string[n...n+m]

    puts string[n...]

    puts string.rchop

    known_character_index = string.index(known_character).not_nil!
    puts string[known_character_index...known_character_index+m]

    known_substring_index = string.index(known_substring).not_nil!
    puts string[known_substring_index...known_substring_index+m]
end

substring_demo("crystalline", 3, 5, 't', "st")


Dim As Integer memoria(255), contador = 0
Dim As String codigo, caracter

Input "SUBLEQ> ", codigo

While Instr(codigo, " ")
    memoria(contador) = Val(Left(codigo, Instr(codigo, " ") - 1))
    codigo = Mid(codigo, Instr(codigo, " ") + 1)
    contador += 1
Wend

memoria(contador) = Val(codigo)
contador = 0
Do
    Dim As Integer a = memoria(contador)
    Dim As Integer b = memoria(contador + 1)
    Dim As Integer c = memoria(contador + 2)
    contador += 3
    If a = -1 Then
        Input "SUBLEQ> ", caracter
        memoria(b) = Asc(caracter)
    Else
        If b = -1 Then
            Print Chr(memoria(a));
        Else
            memoria(b) -= memoria(a)
            If memoria(b) <= 0 Then contador = c
        End If
    End If
Loop Until contador < 0
Sleep


package main

import (
	"io"
	"log"
	"os"
)

func main() {
	var mem = []int{
		15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1,
		//'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\n',
		72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 10,
		0,
	}
	for ip := 0; ip >= 0; {
		switch {
		case mem[ip] == -1:
			mem[mem[ip+1]] = readbyte()
		case mem[ip+1] == -1:
			writebyte(mem[mem[ip]])
		default:
			b := mem[ip+1]
			v := mem[b] - mem[mem[ip]]
			mem[b] = v
			if v <= 0 {
				ip = mem[ip+2]
				continue
			}
		}
		ip += 3
	}
}

func readbyte() int {
	var b [1]byte
	if _, err := io.ReadFull(os.Stdin, b[:]); err != nil {
		log.Fatalln("read:", err)
	}
	return int(b[0])
}

func writebyte(b int) {
	if _, err := os.Stdout.Write([]byte{byte(b)}); err != nil {
		log.Fatalln("write:", err)
	}
}


import std.stdio, std.string;

void main() {
    const s = "the quick brown fox jumps over the lazy dog";
    enum n = 5, m = 3;

    writeln(s[n .. n + m]);

    writeln(s[n .. $]);

    writeln(s[0 .. $ - 1]);

    const i = s.indexOf("q");
    writeln(s[i .. i + m]);

    const j = s.indexOf("qu");
    writeln(s[j .. j + m]);
}


;starting from n characters in and of m length;
SUB_STR = STR(n:m)

;starting from n characters in, up to the end of the string;
SUB_STR = STR(n,$LEN(STR))

;whole string minus last character;
SUB_STR = STR(1,%TRIM(STR)-1)

;starting from a known character f within the string and of m length;
;starting from a known substring f within the string and of m length.
SUB_STR = STR(%INSTR(1,STR,f):m)


program ShowSubstring;

{$APPTYPE CONSOLE}

uses SysUtils;

const
  s = '0123456789';
  n = 3;
  m = 4;
  c = '2';
  sub = '456';
begin
  Writeln(Copy(s, n, m));             // starting from n characters in and of m length;
  Writeln(Copy(s, n, Length(s)));     // starting from n characters in, up to the end of the string;
  Writeln(Copy(s, 1, Length(s) - 1)); // whole string minus last character;
  Writeln(Copy(s, Pos(c, s), m));     // starting from a known character within the string and of m length;
  Writeln(Copy(s, Pos(sub, s), m));   // starting from a known substring within the string and of m length.
end.


{-# LANGUAGE FlexibleContexts #-}
import Control.Monad.State
import Data.Char (chr, ord)
import Data.IntMap

subleq = loop 0
    where
      loop ip =
          when (ip >= 0) $
          do m0 <- gets (! ip)
             m1 <- gets (! (ip + 1))
             if m0 < 0
                then do modify . insert m1 ch . ord =<< liftIO getChar
                        loop (ip + 3)
                else if m1 < 0
                        then do liftIO . putChar . chr =<< gets (! m0)
                                loop (ip + 3)
                        else do v <- (-) <$> gets (! m1) <*> gets (! m0)
                                modify $ insert m1 v
                                if v <= 0
                                   then loop =<< gets (! (ip + 2))
                                   else loop (ip + 3)

main = evalStateT subleq helloWorld
    where
      helloWorld =
          fromList $
          zip [0..]
              [15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33, 10, 0]


readchar=:3 :0
  if.0=#INBUF do. INBUF=:LF,~1!:1]1 end.
  r=.3 u:{.INBUF
  INBUF=:}.INBUF
  r
)

writechar=:3 :0
  OUTBUF=:OUTBUF,u:y
)

subleq=:3 :0
  INBUF=:OUTBUF=:''
  p=.0
  whilst.0<:p do.
    'A B C'=. (p+0 1 2){y
    p=.p+3
    if._1=A do. y=. (readchar'') B} y
    elseif._1=B do. writechar A{y
    elseif. 1   do.
      t=. (B{y)-A{y
      y=. t B}y
      if. 0>:t do.p=.C end.
    end.
  end.
  OUTBUF
)


let s = "0123456789"
let n = 3
let m = 2
let c = '3'
let z = "345"

// A: starting from n characters in and of m length;
print(s.Substring(n, m))
// B: starting from n characters in, up to the end of the string;
print(s[n..])
// C: whole string minus the last character;
print(s[..-1])
// D: starting from a known character within the string and of m length;
print(s.Substring(s.IndexOf(c),m))
// E: starting from a known substring within the string and of m length.
print(s.Substring(s.IndexOf(z),m))


def string := "aardvarks"
def n := 4
def m := 4
println(string(n, n + m))
println(string(n))
println(string(0, string.size() - 1))
println({string(def i := string.indexOf1('d'), i + m)})
println({string(def i := string.startOf("ard"), i + m)})


(defn main [& args]
  (let [filename  (get args 1)
        fh        (file/open filename)
        program   (file/read fh :all)
        memory    (eval-string (string "@[" program "]"))
        size      (length memory)]

    (var pc 0)

    (while (<= 0 pc size)
      (let [a (get memory pc)
            b (get memory (inc pc))
            c (get memory (+ pc 2))]
      (set pc (+ pc 3))
      (cond
        (< a 0) (put memory b (first (file/read stdin 1)))
        (< b 0) (file/write stdout (buffer/push-byte @"" (get memory a)))
        true
          (do
            (put memory b (- (get memory b) (get memory a)))
            (if (<= (get memory b) 0)
               (set pc c))))))))


import java.util.Scanner;

public class Subleq {

    public static void main(String[] args) {
        int[] mem = {15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0,
            -1, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 10, 0};

        Scanner input = new Scanner(System.in);
        int instructionPointer = 0;

        do {
            int a = mem[instructionPointer];
            int b = mem[instructionPointer + 1];

            if (a == -1) {
                mem[b] = input.nextInt();

            } else if (b == -1) {
                System.out.printf("%c", (char) mem[a]);

            } else {

                mem[b] -= mem[a];
                if (mem[b] < 1) {
                    instructionPointer = mem[instructionPointer + 2];
                    continue;
                }
            }

            instructionPointer += 3;

        } while (instructionPointer >= 0);
    }
}


/* In this task display a substring:

1.       starting from n characters in and of m length;
2.       starting from n characters in, up to the end of the string;
3.       whole string minus last character;
4.       starting from a known character within the string and of m length;
5.       starting from a known substring within the string and of m length.
*/

IMPORT STD; //imports a standard string library

TheString := 'abcdefghij';
CharIn    := 3; //n
StrLength := 4; //m
KnownChar := 'f';
KnownSub  := 'def';
FindKnownChar := STD.Str.Find(TheString, KnownChar,1);
FindKnownSub  := STD.Str.Find(TheString, KnownSub,1);

OUTPUT(TheString[Charin..CharIn+StrLength-1]); //task1
OUTPUT(TheString[Charin..]);                   //task2
OUTPUT(TheString[1..LENGTH(TheString)-1]);     //task3
OUTPUT(TheString[FindKnownChar..FindKnownChar+StrLength-1]);//task4
OUTPUT(TheString[FindKnownSub..FindKnownSub+StrLength-1]);  //task5

/* OUTPUTS:
   defg
   cdefghij
   abcdefghi
   fghi
   defg
*/


#import <Foundation/Foundation.h>

int main()
  autoreleasepool
    str := 'abcdefgh'
    n := 2
    m := 3
    Log( '%@', str[0 .. str.length-1] )                     // abcdefgh
    Log( '%@', str[n .. m]            )                     // cd
    Log( '%@', str[n .. str.length-1] )                     // cdefgh
    Log( '%@', str.substringFromIndex: n                  ) // cdefgh
    Log( '%@', str[(str.rangeOfString:'b').location .. m] ) // bcd
  return 0


import extensions;

public program()
{
    var s := "0123456789";
    var n := 3;
    var m := 2;
    var c := $51;
    var z := "345";

    console.writeLine(s.Substring(n, m));
    console.writeLine(s.Substring(n, s.Length - n));
    console.writeLine(s.Substring(0, s.Length - 1));
    console.writeLine(s.Substring(s.indexOf(0, c), m));
    console.writeLine(s.Substring(s.indexOf(0, z), m))
}


# If your jq has while/2 then the following definition can be omitted:
def while(cond; update):
  def _while: if cond then ., (update | _while) else empty end;
  _while;

# subleq(a) runs the program, a, an array of integers.
# Input: the data
# When the subleq OSIC is about to emit a NUL character, it stops instead.
def subleq(a):
  . as $input
  # state: [i, indexIntoInput, a, output]
  | [0, 0, a]
  | while( .[0] >= 0 and .[3] != 0 ;
           .[0] as $i
           | .[1] as $ix
           | .[2] as $a
           | if $a[$i] == -1 then
                if $input and $ix < ($input|length)
                then [$i+3, $ix + 1, ($a[$a[$i + 1]] = $input[$ix]), null]
                else [-1]
                end
              elif $a[$i + 1] == -1 then [$i+3, $ix, $a, $a[$a[$i]]]
              else
                [$i, $ix, ($a | .[.[$i + 1]] -= .[.[$i]]), null]
                | .[2] as $a
                | if $a[$a[$i+1]] <= 0 then .[0] = $a[$i + 2] else . end
                | .[0] += 3
              end )
  | .[3] | select(.) | [.] | implode;

subleq([15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15,  0, 0, -1,
        72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 10, 0])


module Subleq

using OffsetArrays

function interpret(allwords::AbstractVector{Int})
    words = OffsetArray(allwords, -1)
    buf = IOBuffer()
    ip = 0
    while true
        a, b, c = words[ip:ip+2]
        ip += 3
        if a < 0
            print("Enter a character: ")
            words[b] = parse(Int, readline(stdin))
        elseif b < 0
            print(buf, Char(words[a]))
        else
            words[b] -= words[a]
            if words[b] ≤ 0
                ip = c
            end
            ip < 0 && break
        end
    end
    return String(take!(buf))
end

interpret(src::AbstractString) = interpret(parse.(Int, split(src)))

end  # module Subleq


// version 1.1.2

fun subleq(program: String) {
    val words = program.split(' ').map { it.toInt() }.toTypedArray()
    val sb = StringBuilder()
    var ip = 0
    while (true) {
        val a = words[ip]
        val b = words[ip + 1]
        var c = words[ip + 2]
        ip += 3
        if (a < 0) {
            print("Enter a character : ")
            words[b] = readLine()!![0].toInt()
        }
        else if (b < 0) {
            sb.append(words[a].toChar())
        }
        else {
            words[b] -= words[a]
            if (words[b] <= 0) ip = c
            if (ip < 0) break
        }
    }
    print(sb)
}

fun main(args: Array<String>) {
    val program = "15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0"
    subleq(program)
}


s = "abcdefgh"
String.slice(s, 2, 3)           #=> "cde"
String.slice(s, 1..3)           #=> "bcd"
String.slice(s, -3, 2)          #=> "fg"
String.slice(s, 3..-1)          #=> "defgh"

# UTF-8
s = "αβγδεζηθ"
String.slice(s, 2, 3)           #=> "γδε"
String.slice(s, 1..3)           #=> "βγδ"
String.slice(s, -3, 2)          #=> "ζη"
String.slice(s, 3..-1)          #=> "δεζηθ"


1> N = 3.
2> M = 5.
3> string:sub_string( "abcdefghijklm", N ).
"cdefghijklm"
4> string:sub_string( "abcdefghijklm", N, N + M - 1 ).
"cdefg"
6> string:sub_string( "abcdefghijklm", 1, string:len("abcdefghijklm") - 1 ).
"abcdefghijkl"
7> Start_character = string:chr( "abcdefghijklm", $e ).
8> string:sub_string( "abcdefghijklm", Start_character, Start_character + M - 1 ).
"efghi"
9> Start_string = string:str( "abcdefghijklm", "efg" ).
10> string:sub_string( "abcdefghijklm", Start_string, Start_string + M - 1 ).
"efghi"


sequence baseString, subString, findString
integer findChar
integer m, n

baseString = "abcdefghijklmnopqrstuvwxyz"

-- starting from n characters in and of m length;
n = 12
m = 5
subString = baseString[n..n+m-1]
puts(1, subString )
puts(1,'\n')

-- starting from n characters in, up to the end of the string;
n = 12
subString = baseString[n..$]
puts(1, subString )
puts(1,'\n')

-- whole string minus last character;
subString = baseString[1..$-1]
puts(1, subString )
puts(1,'\n')

-- starting from a known character within the string and of m length;
findChar = 'o'
m = 5
n = find(findChar,baseString)
subString = baseString[n..n+m-1]
puts(1, subString )
puts(1,'\n')

-- starting from a known substring within the string and of m length.
findString = "pq"
m = 5
n = match(findString,baseString)
subString = baseString[n..n+m-1]
puts(1, subString )
puts(1,'\n')


make "memory (array 32 0)

to load_subleq
  local "i make "i 0
  local "line
  make "line readlist
  while [or (not empty? :line) (not list? :line)] [
    foreach :line [
        setitem :i :memory ?
        make "i sum :i 1
    ]
    make "line readlist
  ]
end

to run_subleq
  make "ip 0
  while [greaterequal? :ip 0] [
    local "a make "a item :ip :memory
    make "ip sum :ip 1
    local "b make "b item :ip :memory
    make "ip sum :ip 1
    local "c make "c item :ip :memory
    make "ip sum :ip 1
    cond [
     [[less? :a 0]  setitem :b :memory ascii readchar ]
     [[less? :b 0]  type char item :a :memory ]
     [else
        local "av make "av item :a :memory
        local "bv make "bv item :b :memory
        local "diff make "diff difference :bv :av
        setitem :b :memory :diff
        if [lessequal? :diff 0] [make "ip :c]]]
    ]
end

load_subleq
run_subleq
bye


function subleq (prog)
    local mem, p, A, B, C = {}, 0
    for word in prog:gmatch("%S+") do
        mem[p] = tonumber(word)
        p = p + 1
    end
    p = 0
    repeat
        A, B, C = mem[p], mem[p + 1], mem[p + 2]
        if A == -1 then
            mem[B] = io.read()
        elseif B == -1 then
            io.write(string.char(mem[A]))
        else
            mem[B] = mem[B] - mem[A]
            if mem[B] <= 0 then p = C end
        end
        p = p + 3
    until not mem[mem[p]]
end

subleq("15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0")


ClearAll[memory, MemoryGet, MemorySet, MemorySubtract]
memory = {15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0,
   0, -1, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33,
    10, 0};
MemoryGet[addr_] := memory[[addr + 1]]
MemorySet[addr_, value_] := memory[[addr + 1]] = value
MemorySubtract[addr1_, addr2_] := MemorySet[addr1, MemoryGet[addr1] - MemoryGet[addr2]]
p = 0;
While[p >= 0,
 a = MemoryGet[p];
 b = MemoryGet[p + 1];
 c = MemoryGet[p + 2];
 If[b == -1,
  Print[FromCharacterCode[MemoryGet[a]]]
  ,
  MemorySubtract[b, a];
  If[MemoryGet[b] < 1,
   p = MemoryGet[p + 2];
   Continue[]
   ]
  ];
 p += 3;
 ]


[<EntryPoint>]
let main args =
    let s = "一二三四五六七八九十"
    let n, m  = 3, 2
    let c = '六'
    let z = "六七八"

    printfn "%s" (s.Substring(n, m))
    printfn "%s" (s.Substring(n))
    printfn "%s" (s.Substring(0, s.Length - 1))
    printfn "%s" (s.Substring(s.IndexOf(c), m))
    printfn "%s" (s.Substring(s.IndexOf(z), m))
    0


USING: math sequences kernel ;

! starting from n characters in and of m length
: subseq* ( from length seq -- newseq ) [ over + ] dip subseq ;

! starting from n characters in, up to the end of the string
: dummy ( seq n -- tailseq ) tail ;

! whole string minus last character
: dummy1 ( seq -- headseq ) but-last ;

USING: fry sequences kernel ;
! helper word
: subseq-from-* ( subseq len seq quot -- seq ) [ nip ] prepose 2keep subseq* ; inline

! starting from a known character within the string and of m length;
: subseq-from-char ( char len seq -- seq ) [ index ] subseq-from-* ;

! starting from a known substring within the string and of m length.
: subseq-from-seq ( subseq len seq -- seq ) [ start ] subseq-from-* ;


memory = []
step = 3
currentAddress = 0
out = ""

process = function(address)
    A = memory[address].val
    B = memory[address + 1].val
    C = memory[address + 2].val
    nextAddress = address + step

    if A == -1 then
        memory[B] = input
    else if B == -1 then
        globals.out = globals.out + char(memory[A].val)
    else
        memory[B] = str(memory[B].val - memory[A].val)
        if memory[B] < 1 then nextAddress = C
    end if
    return nextAddress
end function

print
memory = input("Enter SUBLEQ program").split

print
print "Running Program"
print "-------------------"
processing = currentAddress < memory.len
while processing
    currentAddress = process(currentAddress)
    if currentAddress >= memory.len or currentAddress == -1 then
        processing = false
    end if
end while

print out
print "-------------------"
print "Execution Complete"


MODULE Subleq;
FROM Terminal IMPORT Write,WriteString,WriteLn,ReadChar;

TYPE MEMORY = ARRAY[0..31] OF INTEGER;
VAR
    mem : MEMORY;
    ip,a,b : INTEGER;
    ch : CHAR;
BEGIN
    mem := MEMORY{
         15,  17,  -1,  17,  -1,  -1,  16,   1,
         -1,  16,   3,  -1,  15,  15,   0,   0,
         -1,  72, 101, 108, 108, 111,  44,  32,
        119, 111, 114, 108, 100,  33,  10,   0
    };

    ip := 0;
    REPEAT
        a := mem[ip];
        b := mem[ip+1];

        IF a = -1 THEN
            ch := ReadChar();
            mem[b] := ORD(ch);
        ELSIF b = -1 THEN
            Write(CHR(mem[a]));
        ELSE
            DEC(mem[b],mem[a]);
            IF mem[b] < 1 THEN
                ip := mem[ip+2];
                CONTINUE
            END
        END;

        INC(ip,3)
    UNTIL ip < 0;
    WriteLn;

    ReadChar
END Subleq.


/* created by Aykayayciti Earl Lamont Montgomery
April 9th, 2018 */
s = "FalconPL is not just a multi-paradign language but also fun"
n = 12
m = 5

> "starting from n characters in and of m length: ", s[n:n+m]
> "starting from n characters in, up to the end of the string: ", s[n:]
> "whole string minus last character: ", s[0:len(s)-1]
new_n = s.find("j", 0)
> "starting from a known character within the string and of m length: ", s[new_n:new_n+m]
new_n = s.find("mu", 0)
> "starting from a known character within the string and of m length: ", s[new_n:new_n+m]


2 constant Pos
3 constant Len
: Str ( -- c-addr u )  s" abcdefgh" ;

Str Pos /string drop Len type    \ cde
Str Pos /string type             \ cdefgh
Str 1- type                      \ abcdefg
Str char d scan drop Len type    \ def
Str s" de" search 2drop Len type \ def


program test_substring

  character (*), parameter :: string = 'The quick brown fox jumps over the lazy dog.'
  character (*), parameter :: substring = 'brown'
  character    , parameter :: c = 'q'
  integer      , parameter :: n = 5
  integer      , parameter :: m = 15
  integer                  :: i

! Display the substring starting from n characters in and of length m.
  write (*, '(a)') string (n : n + m - 1)
! Display the substring starting from n characters in, up to the end of the string.
  write (*, '(a)') string (n :)
! Display the whole string minus the last character.
  i = len (string) - 1
  write (*, '(a)') string (: i)
! Display the substring starting from a known character and of length m.
  i = index (string, c)
  write (*, '(a)') string (i : i + m - 1)
! Display the substring starting from a known substring and of length m.
  i = index (string, substring)
  write (*, '(a)') string (i : i + m - 1)

end program test_substring


import streams

type
  Interpreter = object
    mem: seq[int]
    ip: int
    input, output: Stream

proc load(prog: openArray[int]; inp, outp: Stream): Interpreter =
  Interpreter(mem: prog, input: inp, output: outp)

proc run(i: var Interpreter) =
  while i.ip >= 0:
    let A = i.mem[i.ip]
    let B = i.mem[i.ip+1]
    let C = i.mem[i.ip+2]
    i.ip += 3
    if A == -1:
      i.mem[B] = ord(i.input.readChar)
    elif B == -1:
      i.output.write(chr(i.mem[A]))
    else:
      i.mem[B] -= i.mem[A]
      if i.mem[B] <= 0:
        i.ip = C

let test = @[15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1,
             72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 10, 0]
var intr = load(test, newFileStream(stdin), newFileStream(stdout))

try:
  intr.run()
except IndexDefect:
  echo "ip: ", intr.ip
  echo "mem: ", intr.mem


use System.IO;

class Sublet {
  function : Main(args : String[]) ~ Nil {
    mem := [
      15, 17, -1, 17, -1, -1, 16, 1, -1, 16,
      3, -1, 15, 15, 0, 0, -1, 72, 101, 108,
      108, 111, 44, 32, 119, 111, 114, 108, 100, 33,
      10, 0];

    instructionPointer := 0;

    do {
      a := mem[instructionPointer];
      b := mem[instructionPointer + 1];

      if (a = -1) {
        mem[b] := Console->ReadString()->Get(0);
        instructionPointer += 3;
      }
      else if (b = -1) {
        value := mem[a]->As(Char);
        value->Print();
        instructionPointer += 3;
      }
      else {
        mem[b] -= mem[a];
        if (mem[b] < 1) {
          instructionPointer := mem[instructionPointer + 2];
        }
        else {
          instructionPointer += 3;
        };
      };
    }
    while (instructionPointer >= 0);
  }
}


s[n..n+m]
s[n..high(nativeUInt)]
s[1..length(s)-1]
s[pos(c, s)..pos(c, s)+m]
s[pos(p, s)..pos(p, s)+m]


' FB 1.05.0 Win64

Dim s As String = "123456789"
Dim As Integer n = 3, m = 4
Print Mid(s, n, m)
Print Mid(s, n)
Print Left(s, Len(s) - 1)
'start from "5" say
Print Mid(s, Instr(s, "5"), m)
' start from "12" say
Print Mid(s, Instr(s, "12"), m)
Sleep


test = "🐱abcdefg😾"
n = 3
m = 2
println[substrLen[test, n, m]]
println[right[test, -m]]
println[left[test, -1]]
pos = indexOf["c"]
if pos != -1
    println[substrLen[test, pos, m]]
pos = indexOf[test, "cd"]
if pos != -1
    println[substrLen[test, pos, m]]


: subleq(program)
| ip a b c newb |
   program asListBuffer ->program
   0 ->ip
   while( ip 0 >= ) [
      ip 1+ dup program at ->a 1+ dup program at ->b 1+ program at ->c
      ip 3 + ->ip
      a -1 = ifTrue: [ b System.In >> nip program put continue ]
      b -1 = ifTrue: [ System.Out a 1+ program at <<c drop continue ]
      b 1+ program at a 1+ program at - ->newb
      program put(b 1+, newb)
      newb 0 <= ifTrue: [ c ->ip ]
      ] ;

[15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 10, 0 ]
subleq


/*REXX program simulates execution of a  One-Instruction Set Computer (OISC). */
Signal on Halt                         /*enable user to halt the simulation.  */
cell.=0                                /*zero-out all of real memory locations*/
ip=0                                   /*initialize ip  (instruction pointer).*/
Parse Arg memory                       /*get optional low memory vals from CL.*/
memory=space(memory)                   /*elide superfluous blanks from string.*/

If memory==''  Then Do
  memory='15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1' /* common start     */
  If 3=='f3'x  Then                    /* EBCDIC                              */
    memory=memory '200 133 147 147 150 107 64 166 150 153 147 132  90  21 0'
  else /* ASCII      H   e   l   l   o   , bla  w   o   r   l   d   ! l/f */
    memory=memory ' 72 101 108 108 111  44 32 119 111 114 108 100  33  10 0'
  End

Do i=0 For words(memory)               /* copy memory to cells                */
  cell.i=word(memory,i+1)
  End

Do Until ip<0                          /* [?]  neg addresses are treated as -1*/
  a=cell(ip)
  b=cell(ip+1)
  c=cell(ip+2)                         /*get values for  A,  B,  and  C.      */
  ip=ip+3                              /*advance the ip (instruction pointer).*/
  Select                               /*choose an instruction state.         */
    When a<0 Then cell.b=charin()            /* read a character from term.   */
    When b<0 Then call charout ,d2c(cell.a)  /* write "    "      to    "     */
    Otherwise Do
      cell.b=cell.b-cell.a             /* put difference ---? loc  B.         */
      If cell.b<=0  Then ip=c          /* if ¬positive, set ip to  C.         */
      End
    End
  End
Exit
cell: Parse arg _
      Return cell._                    /*return the contents of "memory" loc _*/
halt: Say 'REXX program halted by user.'
      Exit 1


PROGRAM OISC;

CONST
	MAXADDRESS = 1255;

TYPE
	MEMORY = PACKED ARRAY [0 .. MAXADDRESS] OF INTEGER;

VAR
	MEM : MEMORY;
	FILENAME : STRING;

PROCEDURE LOADTEXT (FILENAME : STRING; VAR MEM : MEMORY);
	VAR
		NUMBERS : TEXT;
		ADDRESS : INTEGER;
	BEGIN
		ASSIGN (NUMBERS, FILENAME);
		ADDRESS := 0;
		RESET (NUMBERS);
		WHILE (ADDRESS <= MAXADDRESS) AND NOT EOF (NUMBERS) DO BEGIN
			READ (NUMBERS, MEM [ADDRESS]);
			ADDRESS := ADDRESS + 1
		END;
		CLOSE (NUMBERS);
		FOR ADDRESS := ADDRESS TO MAXADDRESS DO
			MEM [ADDRESS] := 0
	END;

PROCEDURE SUBLEQ (VAR MEM : MEMORY);
	VAR
		ADDRESS, A, B, C : INTEGER;
		IO : CHAR;
	BEGIN
		ADDRESS := 0;
		WHILE ADDRESS >= 0 DO BEGIN
			A := MEM [ADDRESS];
			B := MEM [ADDRESS + 1];
			C := MEM [ADDRESS + 2];
			ADDRESS := ADDRESS + 3;
			IF A = -1 THEN BEGIN
				READ (IO);
				MEM [B] := ORD (IO)
			END
			ELSE IF B = -1 THEN BEGIN
				IO := CHR (MEM [A]);
				WRITE (IO)
			END
			ELSE BEGIN
				MEM [B] := MEM [B] - MEM [A];
				IF MEM [B] <= 0 THEN ADDRESS := C
			END
		END
	END;

BEGIN
	WRITE ('Filename>');
	READLN (FILENAME);
	LOADTEXT (FILENAME, MEM);
	SUBLEQ (MEM);
END.


Public Sub Main()
Dim sString As String = "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG"

Print Mid(sString, 11, 5)                     'Starting from n characters in and of m length
Print Mid(sString, 17)                        'Starting from n characters in, up to the end of the string
Print Left(sString, -1)                       'Whole string minus last character
Print Mid(sString, InStr(sString, "B"), 9)    'Starting from a known character within the string and of m length
Print Mid(sString, InStr(sString, "OVER"), 8) 'Starting from a known substring within the string and of m length

End


LETTERS;
# "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
LETTERS{[5 .. 10]};
# "EFGHIJ"


#!/usr/bin/env perl
use strict;
use warnings;
my $file = shift;
my @memory = ();
open (my $fh, $file);
while (<$fh>) {
  chomp;
  push @memory, split;
}
close($fh);
my $ip = 0;
while ($ip >= 0 && $ip < @memory) {
  my ($a, $b, $c) = @memory[$ip,$ip+1,$ip+2];
 $ip += 3;
 if ($a < 0) {
    $memory[$b] = ord(getc);
 } elsif ($b < 0) {
    print chr($memory[$a]);
 } else {
    if (($memory[$b] -= $memory[$a]) <= 0) {
     $ip = $c;
   }
 }
}


package main

import (
    "fmt"
    "strings"
)

func main() {
    s := "ABCDEFGH"
    n, m := 2, 3
    // for reference
    fmt.Println("Index: ", "01234567")
    fmt.Println("String:", s)
    // starting from n characters in and of m length
    fmt.Printf("Start %d, length %d:    %s\n", n, m, s[n : n+m])
    // starting from n characters in, up to the end of the string
    fmt.Printf("Start %d, to end:      %s\n", n, s[n:])
    // whole string minus last character
    fmt.Printf("All but last:         %s\n", s[:len(s)-1])
    // starting from a known character within the string and of m length
    dx := strings.IndexByte(s, 'D')
    fmt.Printf("Start 'D', length %d:  %s\n", m, s[dx : dx+m])
    // starting from a known substring within the string and of m length
    sx := strings.Index(s, "DE")
    fmt.Printf(`Start "DE", length %d: %s`+"\n", m, s[sx : sx+m])
}


def str = 'abcdefgh'
def n = 2
def m = 3
// #1
println str[n..n+m-1]
/* or */
println str[n..<(n+m)]
// #2
println str[n..-1]
// #3
println str[0..-2]
// #4
def index1 = str.indexOf('d')
println str[index1..index1+m-1]
/* or */
println str[index1..<(index1+m)]
// #5
def index2 = str.indexOf('de')
println str[index2..index2+m-1]
/* or */
println str[index2..<(index2+m)]


function Invoke-Subleq ([int[]]$Program)
{
    [int]$ip, [string]$output = $null

    try
    {
        while ($ip -ge 0)
        {
            if ($Program[$ip] -eq -1)
            {
                $Program[$Program[$ip + 1]] = [int](Read-Host -Prompt SUBLEQ)[0]
            }
            elseif ($Program[$ip + 1] -eq -1)
            {
                $output += "$([char]$Program[$Program[$ip]])"
            }
            else
            {
                $Program[$Program[$ip + 1]] -= $Program[$Program[$ip]]

                if ($Program[$Program[$ip + 1]] -le 0)
                {
                    $ip = $Program[$ip + 2]
                    continue
                }
            }

            $ip += 3
        }

        return $output
    }
    catch [IndexOutOfRangeException],[Exception]
    {
        Write-Host "$($Error[0].Exception.Message)" -ForegroundColor Red
    }
}


DataSection
  StartData:
  Data.i 15,17,-1,17,-1,-1,16,1,-1,16,3,-1,15,15,0,0,-1,72,101,108,108,111,44,32,119,111,114,108,100,33,10,0
  StopData:
EndDataSection

If OpenConsole("Subleq")=0 : End 1 : EndIf
Dim code.i((?StopData-?StartData)/SizeOf(Integer)-1)
CopyMemory(?StartData,@code(0),?StopData-?StartData)
Define.i ip=0,a,b,c,nip
While 0<=ip
  nip=ip+3  :  a=code(ip)  :   b=code(ip+1)  :  c=code(ip+2)
  If a=-1       :    code(b)=Asc(Input())
  ElseIf b=-1   :    Print(Chr(code(a)))
  Else          :    code(b)-code(a)  :    If code(b)<=0   :   nip=c   :   EndIf
  EndIf
  ip=nip
Wend
Input()


CHARACTER :: string = 'ABCDEFGHIJK', known = 'B',  substring = 'CDE'
REAL, PARAMETER :: n = 5,  m = 8

WRITE(Messagebox) string(n : n + m - 1), "| substring starting from n, length m"
WRITE(Messagebox) string(n :), "| substring starting from n, to  end of string"
WRITE(Messagebox) string(1: LEN(string)-1), "| whole string minus last character"

pos_known = INDEX(string, known)
WRITE(Messagebox) string(pos_known : pos_known+m-1), "| substring starting from pos_known, length m"

pos_substring = INDEX(string, substring)
WRITE(Messagebox) string(pos_substring : pos_substring+m-1), "| substring starting from pos_substring, length m"


mem <- c(15, 17, -1, 17, -1, -1, 16, 1,
         -1, 16, 3, -1, 15, 15, 0, 0,
         -1, 72, 101, 108, 108, 111, 44,
         32, 119, 111, 114, 108, 100,
         33, 10, 0)

getFromMemory <- function(addr) { mem[[addr + 1]] } # because first element in mem is mem[[1]]
setMemory <- function(addr, value) { mem[[addr + 1]] <<- value }
subMemory <- function(x, y) { setMemory(x, getFromMemory(x) - getFromMemory(y)) }

instructionPointer <- 0
while (instructionPointer >= 0) {
  a <- getFromMemory(instructionPointer)
  b <- getFromMemory(instructionPointer + 1)
  c <- getFromMemory(instructionPointer + 2)
  if (b == -1) {
    cat(rawToChar(as.raw(getFromMemory(a))))
  } else {
    subMemory(b, a)
    if (getFromMemory(b) < 1) {
      instructionPointer <- getFromMemory(instructionPointer + 2)
      next
    }
  }
  instructionPointer <- instructionPointer + 3
}


procedure main(arglist)
write("Usage: substring  <string> <first position> <second position> <single character> <substring>")
s := \arglist[1] | "aardvarks"
n := \arglist[2] | 5
m := \arglist[3] | 4
c := \arglist[4] | "d"
ss := \arglist[5] | "ard"

write( s[n+:m] )
write( s[n:0] )
write( s[1:-1] )
write( s[find(c,s)+:m] )
write( s[find(ss,s)+:m] )
end


   5{.3}.'Marshmallow'
shmal
   3}.'Marshmallow'
shmallow
   }.'Marshmallow'
arshmallow
   }:'Marshmallow'
Marshmallo
   5{.(}.~ i.&'m')'Marshmallow'
mallo
   5{.(}.~ [email protected]~&'sh')'Marshmallow'
shmal


#lang racket

(define (subleq v)
  (define (mem n)
    (vector-ref v n))
  (define (mem-set! n x)
    (vector-set! v n x))
  (let loop ([ip 0])
    (when (>= ip 0)
      (define m0 (mem ip))
      (define m1 (mem (add1 ip)))
      (cond
        [(< m0 0) (mem-set! m1 (read-byte))
                  (loop (+ ip 3))]
        [(< m1 0) (write-byte (mem m0))
                  (loop (+ ip 3))]
        [else (define v (- (mem m1) (mem m0)))
              (mem-set! m1 v)
              (if (<= v 0)
                 (loop (mem (+ ip 2)))
                 (loop (+ ip 3)))]))))

(define Hello (vector 15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1
                    ; H    e    l    l    o    ,  <sp> w    o    r    l    d    !   \n
                      72   101  108  108  111  44  32  119  111  114  108  100  33  10
                      0))

(subleq Hello)


my @hello-world =
|<15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1>,
|"Hello, world!\n\0".comb.map(*.ord);

sub run-subleq(@memory) {
  my $ip = 0;
  while $ip >= 0 && $ip < @memory {
    my ($a, $b, $c) = @memory[$ip..*];
    $ip += 3;
    if $a < 0 {
      @memory[$b] = getc.ord;
    } elsif $b < 0 {
      print @memory[$a].chr;
    } else {
      if (@memory[$b] -= @memory[$a]) <= 0 {
        $ip = $c;
      }
    }
  }
}

run-subleq @hello-world;


/*REXX program  simulates  the  execution  of a   One─Instruction Set Computer  (OISC). */
signal on halt                                   /*enable user to  halt  the simulation.*/
parse arg $                                      /*get optional low memory vals from CL.*/
$$= '15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1'  /*common stuff for EBCDIC & ASCII.*/
    /*EBCDIC "then" choice [↓]       H   e   l   l   o  , BLANK w   o   r   l   d  !  LF*/
if $='' then if 6=="f6"x  then $=$$ 200 133 147 147 150 107 64 166 150 153 147 132 90 21 0
                          else $=$$  72 101 108 108 111  44 32 119 111 114 108 100 33 10 0
                        /* [↑]  ASCII   (the "else" choice).                Line Feed≡LF*/
@.= 0                                            /*zero all memory & instruction pointer*/
         do j=0  for words($);  @.j=word($,j+1)  /*assign memory.  OISC is zero─indexed.*/
         end   /*j*/                             /*obtain A, B, C memory values──►────┐ */
    do #=0  by 3 until #<0;     a= @(#-3);    b= @(#-2);     c= @(#-1)   /* ◄─────────┘ */
        select                                   /*choose an instruction state.         */
        when a<0  then @.b= charin()             /*  read a character from the terminal.*/
        when b<0  then call charout , d2c(@.a)   /* write "     "      to   "     "     */
        otherwise      @.b= @.b - @.a            /*put difference  ────►  location  B.  */
                    if @.b<=0  then #= c         /*Not positive?   Then set  #  to  C.  */
        end   /*select*/                         /* [↑]  choose one of two states.      */
    end       /*#*/                              /*leave the DO loop if  #  is negative.*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
@:     parse arg @z;    return @.@z              /*return  a  memory location (cell @Z).*/
halt:  say 'The One─Instruction Set Computer simulation pgm was halted by user.';   exit 1


public static String Substring(String str, int n, int m){
    return str.substring(n, n+m);
}
public static String Substring(String str, int n){
    return str.substring(n);
}
public static String Substring(String str){
    return str.substring(0, str.length()-1);
}
public static String Substring(String str, char c, int m){
    return str.substring(str.indexOf(c), str.indexOf(c)+m+1);
}
public static String Substring(String str, String sub, int m){
    return str.substring(str.indexOf(sub), str.indexOf(sub)+m+1);
}


var str = "abcdefgh";

var n = 2;
var m = 3;

//  *  starting from n characters in and of m length;
str.substr(n, m);  // => "cde"

//  * starting from n characters in, up to the end of the string;
str.substr(n);  // => "cdefgh"
str.substring(n);  // => "cdefgh"

//  * whole string minus last character;
str.substring(0, str.length - 1);  // => "abcdefg"

//  * starting from a known character within the string and of m length;
str.substr(str.indexOf('b'), m);  // => "bcd"

//  * starting from a known substring within the string and of m length.
str.substr(str.indexOf('bc'), m);  // => "bcd"


class Computer
  def initialize program
    @memory = program.map &:to_i
    @instruction_pointer = 0
  end

  def step
    return nil if @instruction_pointer < 0

    a, b, c = @memory[@instruction_pointer .. @instruction_pointer + 2]
    @instruction_pointer += 3

    if a == -1
      b = readchar
    elsif b == -1
      writechar @memory[a]
    else
      difference = @memory[b] -= @memory[a]
      @instruction_pointer = c if difference <= 0
    end

    @instruction_pointer
  end

  def run
    current_pointer = @instruction_pointer
    current_pointer = step while current_pointer >= 0
  end

  private

  def readchar
    gets[0].ord
  end

  def writechar code_point
    print code_point.chr
  end
end

subleq = Computer.new ARGV

subleq.run


import java.util.Scanner

object Subleq extends App {
  val mem = Array(15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1,
    'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', 10, 0)
  val input = new Scanner(System.in)
  var instructionPointer = 0

  do {
    val (a, b) = (mem(instructionPointer), mem(instructionPointer + 1))
    if (a == -1) mem(b) = input.nextInt
    else if (b == -1) print(f"${mem(a)}%c")
    else {
      mem(b) -= mem(a)
      if (mem(b) < 1) instructionPointer = mem(instructionPointer + 2) - 3
    }
    instructionPointer += 3
  } while (instructionPointer >= 0)
}


def s: "一二三四五六七八九十";


#!/usr/local/bin/jsish -u %s

var str = "abcdefgh";

var n = 2;
var m = 3;

// In jsish, semi-colon first character lines are echoed with result
;str;
;n;
;m;

//  *  starting from n characters in and of m length;
;str.substr(n, m);

//  * starting from n characters in, up to the end of the string;
;str.substr(n);
;str.substring(n);

//  * whole string minus last character;
;str.substring(0, str.length - 1);

//  * starting from a known character within the string and of m length;
;str.substr(str.indexOf('b'), m);

//  * starting from a known substring within the string and of m length.
;str.substr(str.indexOf('bc'), m);

/* Functional */
var res = (function () {
    'use strict';

    //  take :: Int -> Text -> Text
    function take(n, s) {
        return s.substr(0, n);
    }

    //  drop :: Int -> Text -> Text
    function drop(n, s) {
        return s.substr(n);
    }

    // init :: Text -> Text
    function init(s) {
        var n = s.length;
        return (n > 0 ? s.substr(0, n - 1) : undefined);
    }

    // breakOn :: Text -> Text -> (Text, Text)
    function breakOn(strPattern, s) {
        var i = s.indexOf(strPattern);
        return i === -1 ? [strPattern, ''] : [s.substr(0, i), s.substr(i)];
    }

    var str = 'abcdefgh';

    return JSON.stringify({

        'from 4 in, of 3 length': (function (n, m) {
            return take(m, drop(n, str));
        })(4, 3),

        'from 3 in, up to end' : (function (n) {
            return drop(n, str);
        })(3),

        'all but last' : init(str),

        'from matching b, of length 3' : (function (pattern, s, n) {
            return take(n, breakOn(pattern, s)[1]);
        })('b', str, 3),

        'from matching bc, of length 4':(function (pattern, s, n) {
            return take(n, breakOn(pattern, s)[1]);
        })('bc', str, 4)

    }, true);

})();
;res;


var memory = ARGV.map{.to_i};
var ip = 0;

while (ip.ge(0) && ip.lt(memory.len)) {
    var (a, b, c) = memory[ip, ip+1, ip+2];
    ip += 3;
    if (a < 0) {
        memory[b] = STDIN.getc.ord;
    }
    elsif (b < 0) {
        print memory[a].chr;
    }
    elsif ((memory[b] -= memory[a]) <= 0) {
        ip = c
    }
}


func subleq(_ inst: inout [Int]) {
  var i = 0

  while i >= 0 {
    if inst[i] == -1 {
      inst[inst[i + 1]] = Int(readLine(strippingNewline: true)!.unicodeScalars.first!.value)
    } else if inst[i + 1] == -1 {
      print(String(UnicodeScalar(inst[inst[i]])!), terminator: "")
    } else {
      inst[inst[i + 1]] -= inst[inst[i]]

      if inst[inst[i + 1]] <= 0 {
        i = inst[i + 2]
        continue
      }
    }

    i += 3
  }
}

var prog = [
  15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15,
  0, 0, -1, 72, 101, 108, 108, 111, 44, 32, 119, 111,
  114, 108, 100, 33, 10, 0
]

subleq(&prog)


namespace import ::tcl::mathop::-

proc subleq {pgm} {
    set ip 0
    while {$ip >= 0} {
        lassign [lrange $pgm $ip $ip+2] a b c
        incr ip 3
        if {$a == -1} {
            scan [read stdin 1] %C char
            lset pgm $b $char
        } elseif {$b == -1} {
            set char [format %c [lindex $pgm $a]]
            puts -nonewline $char
        } else {
            lset pgm $b [set res [- [lindex $pgm $b] [lindex $pgm $a]]]
            if {$res <= 0} {
                set ip $c
            }
        }
    }
}

fconfigure stdout -buffering none
subleq {15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0}


julia> s = "abcdefg"
"abcdefg"

julia> n = 3
3

julia> s[n:end]
"cdefg"

julia> m=2
2

julia> s[n:n+m]
"cde"

julia> s[1:end-1]
"abcdef"

julia> s[search(s,'c')]
'c'

julia> s[search(s,'c'):search(s,'c')+m]
"cde"


// version 1.0.6

fun main(args: Array<String>) {
    val s = "0123456789"
    val n = 3
    val m = 4
    val c = '5'
    val z = "12"
    var i: Int
    println(s.substring(n, n + m))
    println(s.substring(n))
    println(s.dropLast(1))
    i = s.indexOf(c)
    println(s.substring(i, i + m))
    i = s.indexOf(z)
    println(s.substring(i, i + m))
}


#!/bin/ksh

# Display a substring:
#	- starting from  n  characters in and of  m  length;
#	- starting from  n  characters in, up to the end of the string;
#	- whole string minus the last character;
#	- starting from a known character within the string and of  m  length;
#	- starting from a known substring within the string and of  m  length.

#	# Variables:
#

str='solve this task according to the task description,'
integer n=6 m=14
ch='v'
substr='acc'

#	# Functions:
#
#	# Function _length(str, start, length) - return substr from start,
#	# length chars long (length=-1 = end-of-str)
#
function _length {
	typeset _str ; _str="$1"
	typeset _st ; integer _st=$2
	typeset _ln ; integer _ln=$3

	(( _ln == -1 )) && 	echo "${_str:${_st}}"

	echo "${_str:${_st}:${_ln}}"
}

 ######
# main #
 ######
print -- "--String (Length: ${#str} chars):"
print "${str}\n"

print -- "--From char ${n} and ${m} chars in length:"
_length "${str}" ${n} ${m}
echo

print -- "--From char ${n} to the end:"
_length "${str}" ${n} -1

print -- "--Last character removed:"	# Strings in ksh are zero based
_length "${str}" 0 $(( ${#str}-1 ))
echo

print -- "-From char:'${ch}' and ${m} chars in length:"
foo=${str%${ch}*}
_length "${str}" ${#foo} ${m}
echo

print -- "-From substr:'${substr}' and ${m} chars in length:"
foo=${str%${substr}*}
_length "${str}" ${#foo} ${m}
echo


GoSub _Initialize                      ' Initialize memory

i = 0                                  ' Reset instruction pointer

Do While i > -1                        ' While IP is not negative
  A = @(i)                             ' Fill the registers with
  B = @(i+1)                           ' opcodes and operands
  C = @(i+2)

  i = i + 3                            ' Increment instruction counter
                                       ' A<0 = Input, B<0 = Output
  If B < 0 Then Print CHR(@(A)); : Continue
  If A < 0 Then Input "Enter: ";@(B) : Continue
  @(B) = @(B) - @(A) : If @(B) < 1 Then i = C
Loop                                   ' Change memory contents
                                       ' And optionally the IP
End
                                       ' Corresponds to assembler language:
_Initialize                            ' start:
  @(0) = 15                            '   zero, message, -1
  @(1) = 17
  @(2) = -1
  @(3) = 17                            '   message, -1, -1
  @(4) = -1
  @(5) = -1
  @(6) = 16                            '   neg1, start+1, -1
  @(7) = 1
  @(8) = -1
  @(9) = 16                            '   neg1, start+3, -1
  @(10) = 3
  @(11) = -1
  @(12) = 15                           '   zero, zero, start
  @(13) = 15
  @(14) = 0
  @(15) = 0                            ' zero: 0
  @(16) = -1                           ' neg1: -1
  @(17) = 72                           ' message: "Hello, world!\n\0"
  @(18) = 101
  @(19) = 108
  @(20) = 108
  @(21) = 111
  @(22) = 44
  @(23) = 32
  @(24) = 119
  @(25) = 111
  @(26) = 114
  @(27) = 108
  @(28) = 100
  @(29) = 33                           ' Works only with ASCII
  @(30) = 10                           ' Replace with =ORD(c) when required
  @(31) = 0
Return


import "io" for Stdin, Stdout

var subleq = Fn.new { |program|
    var words = program.split(" ").map { |w| Num.fromString(w) }.toList
    var sb = ""
    var ip = 0
    while (true) {
        var a = words[ip]
        var b = words[ip+1]
        var c = words[ip+2]
        ip = ip + 3
        if (a < 0) {
            System.write("Enter a character : ")
            Stdout.flush()
            words[b] = Num.fromString(Stdin.readLine()[0])
        } else if (b < 0) {
            sb = sb + String.fromByte(words[a])
        } else {
            words[b] = words[b] - words[a]
            if (words[b] <= 0) ip = c
            if (ip < 0) break
        }
    }
    System.write(sb)
}

var program = "15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0"
subleq.call(program)


{S.slice 1 2 hello brave new world}
-> brave new
{W.slice 4 11 www.rosetta.org}
-> rosetta


: cr "\n". ; [] '__A set : dip swap __A swap 1 compress append '__A set execute __A
    -1 extract nip ; : nip swap drop ; : tuck swap over ; : -rot rot rot ; : 0= 0 == ; : 1+ 1 + ;
: 2dip swap 'dip dip ; : 2drop drop drop ; : |a,b> over - iota + ; : bi* 'dip dip execute ; : [email protected] dup bi* ;
: comb "" split ; : concat "" join ; : empty? length 0= ; : tail over lensize |a,b> subscript ;
: lensize length nip ; : while do 'dup dip 'execute 2dip rot if dup 2dip else break then loop 2drop ;

: <substr>  comb -rot over + |a,b> subscript concat ;
: str-tail  tail concat ;
: str-index
    : 2streq  2dup over lensize iota subscript eq '* reduce ;
    swap 'comb [email protected] length -rot 0 -rot
    "2dup 'lensize [email protected] <="
    "2streq if 0 reshape else '1+ 2dip 0 extract drop then"
    while empty? if 2drop tuck == if drop -1 then else 4 ndrop -1 then ;

'abcdefgh 'str set 2 'n set 3 'm set
n m str <substr>
str comb n str-tail
str "d" str-index m str <substr>
str "de" str-index m str <substr>


fcn subleq(a,a1,a2,etc){ a=vm.arglist.copy();
   i:=0;
   while(i>=0){ A,B,C:=a[i,3];
      if(A==-1) a[B]=ask("::").toInt(); // or File.stdin.read(1)[0] // int
      else if(B==-1) print(a[A].toChar());
      else if( (a[B]-=a[A]) <=0) { i=C; continue; }
      i+=3;
   }
}


 10 DIM m(512)
 20 INPUT p$
 30 LET word=1
 40 LET char=1
 50 IF char<LEN p$ THEN GO TO 80
 60 LET m(word)=VAL p$
 70 GO TO 150
 80 IF p$(char)=" " THEN GO TO 110
 90 LET char=char+1
100 GO TO 50
110 LET m(word)=VAL p$( TO char-1)
120 LET p$=p$(char+1 TO )
130 LET word=word+1
140 GO TO 40
150 LET ptr=0
160 LET a=m(ptr+1)
170 LET b=m(ptr+2)
180 LET c=m(ptr+3)
190 LET ptr=ptr+3
200 IF a=-1 THEN GO TO 260
210 IF b=-1 THEN GO TO 290
220 LET m(b+1)=m(b+1)-m(a+1)
230 IF m(b+1)<=0 THEN LET ptr=c
240 IF ptr<0 THEN STOP
250 GO TO 160
260 INPUT c$
270 LET m(b+1)=CODE c$
280 GO TO 160
290 IF m(a+1)=10 THEN PRINT : GO TO 160
300 PRINT CHR$ m(a+1);
310 GO TO 160