⚠️ Warning: This is a draft ⚠️

This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.

If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.

Lua


-- directions
UP, DOWN, LEFT, RIGHT = 1, 2, 4, 8
-- snusp 
snIPC, snIPL, snMPT, snDIR, snMEMORY, snSTACK, snCODE = 1, 1, 1, RIGHT, {0}, {}, {}

-- stackframe
Stackframe = {}
function Stackframe:new()
    local sf = { IPC, IPL, DIR = 0, 0, 0 }
    self.__index = self
    return setmetatable( sf, self )
end

function memStep( a )
    snMPT = snMPT + a
    if snMPT < 0 then return false end
    if snMPT > #snMEMORY then 
        table.insert( snMEMORY, 0 )
    end
    return true
end
function changeDir( d )
    if d == RIGHT then
        if snDIR == RIGHT then snDIR = UP
        elseif snDIR == LEFT then snDIR = DOWN
        elseif snDIR == DOWN then snDIR = LEFT
        else snDIR = RIGHT end
    elseif d == LEFT then
        if snDIR == RIGHT then snDIR = DOWN
        elseif snDIR == LEFT then snDIR = UP
        elseif snDIR == DOWN then snDIR = RIGHT
        else snDIR = LEFT end
    end
end
function step()
    if snDIR == RIGHT then snIPC = snIPC + 1
    elseif snDIR == LEFT then snIPC = snIPC - 1
    elseif snDIR == DOWN then snIPL = snIPL + 1
    elseif snDIR == UP then snIPL = snIPL - 1
    end
    if snIPL > #snCODE or snIPL < 1 then return false end
    if snIPC > #snCODE[snIPL] or snIPC < 1 then return false end
    return true
end
function pushFrame()
    local sf = Stackframe:new(); sf.IPC = snIPC; 
    if snDIR == RIGHT then sf.IPC = sf.IPC + 1
    elseif snDIR == LEFT then sf.IPC = sf.IPC - 1
    end
    sf.IPL = snIPL; 
    if snDIR == DOWN then sf.IPL = sf.IPL + 1
    elseif snDIR == UP then sf.IPL = sf.IPL - 1
    end
    sf.DIR = snDIR
    table.insert( snSTACK, 1, sf ) 
end
function popFrame()
    if #snSTACK < 1 then return false end
    local sf = table.remove( snSTACK, 1 )
    snIPC = sf.IPC; snIPL = sf.IPL; snDIR = sf.DIR
    sf = nil
    return true
end
function exec( c )
    local res = true
    if c == "<" then res = memStep( -1 )
    elseif c == ">" then res = memStep(  1 )
    elseif c == "+" then snMEMORY[snMPT] = snMEMORY[snMPT] + 1
    elseif c == "-" then snMEMORY[snMPT] = snMEMORY[snMPT] - 1
    elseif c == "." then io.write( string.char( snMEMORY[snMPT] ) )
    elseif c == "," then snMEMORY[snMPT] = string.byte( io.read() )
    elseif c == "!" then res = step()
    elseif c == "?" and snMEMORY[snMPT] == 0 then res = step()
    elseif c == "@" then pushFrame()
    elseif c == "#" then res = popFrame()
    elseif c == "/" then changeDir( RIGHT )
    elseif c == "\\" then  changeDir( LEFT )
    end
    return res
end
function run( filename )
    local i, lc = assert( io.open( filename, "rb" ) ), 1
    for ln in io.lines( filename ) do
        for c = 1, #ln do
            if ln:sub( c, c ) == "$" then 
                snIPL = lc; snIPC = c
            end
        end
        snCODE[#snCODE + 1] = ln
        lc = lc + 1
      end
    repeat
        if not exec( snCODE[snIPL]:sub( snIPC, snIPC ) ) then break end
    until step() == false
end
-- [[ entry point ( argument = snusp program file name ) ]]--
if arg[1] ~= nil then run( arg[1] ) end