Textile/brainfuck

From Esolang
Jump to navigation Jump to search
GET_PTR: { #get the memory address the pointer points to
push $FF,$FE
read
push $FF,$FF
read
}

GET_PTR_VAL: {
[GET_PTR]
read
}

POP: {
push
mul
add
}

DUPE_PTR: {
    #store pc lo
push $FF,$FB
write
    #store pc hi
add*2
[POP]
push $FF,$FA
write
    #restore lo
push 1
add
read
    #dupe hi
push $FF,$FA
read
    #dupe lo
push $FF,$FB
read
}

#-------------------------------------------------

MAIN: {
jump GET_INPUT_POS
}

#--------------------------------

GET_INPUT_POS: { #get the first byte where input is
    #is \0 or ";" then set input pos
input
push
equal INC_INPUT_POS
push ";"
add
equal INC_INPUT_POS
    #neither; increment read byte
add
[POP]
    #increment lo byte
push 1
add
    #byte overflow
push
equal INPUT_POS_OVERFLOW
    #loop
add
jump GET_INPUT_POS
}

INPUT_POS_OVERFLOW: {
push 1
add*3
push
jump GET_INPUT_POS
}

###############################

INC_INPUT_POS: {
add
[POP]
    #increment
push 1
add
    #overflow :skull:
push
equal INPUT_SET_OVERFLOW
add
jump SET_INPUT_POS
}

INPUT_SET_OVERFLOW: {
push 1
add*3
push
jump SET_INPUT_POS
}

SET_INPUT_POS: {
    #set lo byte
push $FF,$FD
write
    #pop
add*2
[POP]
    #set hi byte
push $FF,$FC
write
    #pop
add*2
[POP]
jump CHECK_INPUT #enter main program loop
}

#----------------------------------------------

CHECK_INPUT: { #compare input to characters
input
push "+" 
equal INC
push 2
add      # "-"
equal DEC
push 15
add      # "<"
equal LEFT
push 2
add      # ">"
equal RIGHT
push 16
sub      # "."
equal OUT
push 2
sub      # ","
equal INPUT 
push 47
add      # "["
equal LOOP_OPEN
push 2
add      # "]"
equal LOOP_CLOSED
    #end of program check
push
mul
equal EXIT
push ";"
add
equal EXIT
    #no match, jump to increment
add
[POP]
jump PC_INC
}

#---------------------------

INC: { #push memory address at pointer, increment
[GET_PTR_VAL]
push 1
add
jump INC_DEC
}

DEC: { #push memory address at pointer, decrement
[GET_PTR_VAL]
push 1
sub
jump INC_DEC
}

INC_DEC: { 
[GET_PTR]
write
add*4
[POP]
jump PC_INC
}

#--------------------------------------------------

RIGHT: {
    #increment the pointer
[GET_PTR]
push 1
add
    #address overflow
push
equal PTR_OVERFLOW
    #check for $FFFA
push $FA
add
equal BYPASS_RIGHT_LO
[POP]
jump LEFT_RIGHT
}

PTR_OVERFLOW: {
push 1         
add*3          
push           
jump LEFT_RIGHT
}

BYPASS_RIGHT_LO: {
    #get to hi byte
add
[POP]
    #check FF
push $FF
equal BYPASS_RIGHT_HI
    #if it isn't FF
[POP]
push $FA
jmp LEFT_RIGHT
}

BYPASS_RIGHT_HI: { #ptr is FFFA, set to 0000
add
[POP]
push*2
jmp LEFT_RIGHT
}

###############

LEFT: {
    #decrement pointer
[GET_PTR]
push 1
sub
    #address underflow
push $FF
equal PTR_UNDERFLOW
push 1
add*2
jump LEFT_RIGHT
}

PTR_UNDERFLOW: {
    #get to hi ptr byte and decrement
add
[POP]
push 1
sub
push $FF
    #if we're on $FFFF
equal BYPASS_LEFT
jump LEFT_RIGHT
}

BYPASS_LEFT: { #set PTR to $FFF9
push 6
sub
jump LEFT_RIGHT
}

###############

LEFT_RIGHT: {
   #set $FFFF to top stack
push $FF,$FF
write
   #pop 3
add*2
[POP]
   #set $FFFE to 2nd top stack
push $FF,$FE
write
add*4
[POP]
jump PC_INC
}

#---------------------------------------

OUT: {
[GET_PTR_VAL]
out
add
[POP]
jump PC_INC
}

#---------------------------------------

INPUT: {
    #push address in memory starting on $FFFC
push $FF,$FC
read
push $FF,$FD
read
    #push input
input
    #store to pointer 
[GET_PTR]
write
    #increment input pos
push $FF,$FC
read
push $FF,$FD
read
push 1
add
    #more overflow
push
equal INPUT_OVERFLOW
add
jump FINISH_INPUT
}

INPUT_OVERFLOW: {
push 1
add*3
push
jump FINISH_INPUT
}

FINISH_INPUT: {
    #write to input pos bytes
    #set lo byte
push $FF,$FD
write
    #pop
add*2
[POP]
    #set hi byte
push $FF,$FC
write
    #pop
add*9
[POP]
jump PC_INC
}

#----------------------------------------

LOOP_OPEN: {
    #compare ptr to 0
[GET_PTR_VAL]
push
equal JMP_BRACE
    #pop from stack to get to PC values
add*3
[POP]
[DUPE_PTR]
    #loop over
jump PC_INC
}

################

JMP_BRACE: {
    #pop 4
add*3
[POP]
    #write 1 to $FFFB
push 1,$FF,$FB
write
add*2
[POP]
jump MATCH_BRACE
}

MATCH_BRACE: {
    #increment PC
push 1
add
    #OVERFLOW
push
equal MATCH_OVERFLOW
add
jump MATCH_CHECK
}

MATCH_OVERFLOW: {
push 1
add*3
push
jump MATCH_CHECK
}

MATCH_CHECK: {
    #input and check for either brackets or end
input
push "["
equal MATCH_INC
push 2
add  #"]"
equal MATCH_DEC
    #the brackets could be uneven
push
mul  #"\0"
equal EXIT
push ";"
add  #";"
equal EXIT
    #none match, loop over
add
[POP]
jump MATCH_BRACE
}

MATCH_INC: {
    #increment $FFFB
push 1,$FF,$FB
read
add
push $FF,$FB
write
    #pop and loop
add*4
[POP]
jump MATCH_BRACE
}

MATCH_DEC: {
    #decrement $FFFB
push $FF,$FB
read
push 1
sub
    #if FFFB == 0 then exit this loop
push
equal END_MATCH
    #if FFFB != 0
add
push $FF,$FB
write
    #pop and loop
add*4
[POP]
jump MATCH_BRACE
}

END_MATCH: {
add*3
[POP]
jump PC_INC
}

#----------------------------------------

LOOP_CLOSED: {
[GET_PTR_VAL]
    #compare to 0
push
equal EXIT_LOOP
    #not 0, loop over
add*5
[POP]
[DUPE_PTR]
jump PC_INC
}

EXIT_LOOP: {
    #pop 4
add*3
[POP]
    #store ptr
push $FF,$FB
write
add*2
[POP]
push $FF,$FA
write
    #pop from loop stack
add*4
[POP]
    #restore ptr
push $FF,$FA
read
push $FF,$FB
read
jump PC_INC
}

#----------------------------------------

PC_INC: { #stack should be on pc_lo
    #inc
push 1
add
    #pc overflow
push
equal PC_OVERFLOW
add
jump CHECK_INPUT
}

PC_OVERFLOW: {
    #pop 2, adding 1 to PC_hi
push 1
add*3
push #restore PC_lo
jump CHECK_INPUT
}

EXIT: {
debug
}

#memory map
#0000 - FFF9 : brainfuck memory
#FFFA : temp byte hi
#FFFB : temp byte lo
#FFFC : input pos hi byte
#FFFD : input pos lo byte
#FFFE : ptr hi byte
#FFFF : ptr lo byte

#interpreter specs:
#cell storage type: unsigned 8-bit
#loop depth: unlimited
#max program length: 2^16
#cells: 2^16 - 6 (65530)