Created
July 31, 2015 18:40
-
-
Save anonymous/609822a64d04f20008fe to your computer and use it in GitHub Desktop.
CAPL v1.0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Custom class for errorcodes | |
class ERR | |
def self.ERR; -1 end | |
def self.OK; 0 end | |
def self.EXIT; 1 end | |
def self.UNKNOWN; 2 end | |
def self.EMPTY_STACK; 3 end | |
def self.get x | |
case x | |
when self.ERR; 'ERR' | |
when self.OK; 'OK' | |
when self.EXIT; 'EXIT' | |
when self.UNKNOWN; 'UNKNOWN' | |
when self.EMPTY_STACK; 'EMPTY_STACK' | |
end | |
end | |
end | |
# Custom class for stack | |
class Stack | |
$mystack=[] | |
# --- Main functions --- | |
# Push a new value on the stack | |
def push x | |
log "PUSH #{x}" | |
$mystack.push x | |
end | |
# Pop the top value | |
def pop | |
log "POP #{$mystack[-1]}" | |
if $mystack.length == 0 | |
puts "COULD NOT POP: EMPTY STACK" | |
return [ERR.EMPTY_STACK, "COULD NOT POP"] | |
end | |
$mystack.pop | |
end | |
# --- Custom functions --- | |
# Print the stack | |
def print | |
$mystack.each.with_index do |item, inx| | |
# \t[0] 100 | |
puts "\t[#{inx}] #{item}" | |
end | |
end | |
# Get the length from the stack | |
def length | |
return $mystack.length | |
end | |
# Reverse the array `amount` times | |
def reverse amount | |
# Temporary array | |
temp=[] | |
# Pop item from current array, and push it to the temp array | |
amount.times do | |
temp.push pop | |
end | |
# Get first item from temp array, and push it to the current stack | |
temp.each do |x| | |
push x | |
end | |
# Free temp array | |
temp=nil | |
# No need to return anything | |
end | |
end | |
# All global variables | |
$stack=Stack.new | |
$loc = { | |
x: 0, | |
y: 0 | |
} | |
$isnumber=false | |
$number=0 | |
$isstring=false | |
$string="" | |
$skip=false | |
$debug=false | |
# Output a message when it's given and when debug is on, | |
# return the debug value if no message is given | |
def log message=nil | |
return $debug if message==nil | |
puts "\t#{message}" if $debug | |
end | |
# Load a custom framework | |
def load type | |
begin | |
# FileIO; custom library to load and read files | |
if type=="FileIO" | |
# Load the file | |
require '~/Ruby Frameworks/FileIO.rb' | |
# Check if it works | |
log FileIO.check | |
else | |
throw "Type unknown" | |
end | |
# When we failed to load framework | |
rescue Exception => e | |
puts "Failed to load #{type}!" | |
raise e | |
end | |
end | |
# Parse the current character | |
def parse char | |
# If we expect a number, and the character isn't ']' | |
if $isnumber && char != ']' | |
# Check if it really is a number | |
if char=~/^[0-9]+$/ | |
# Add the new number to the global number | |
$number*=10 | |
$number+=char.ord - '0'.ord | |
# Return OK value | |
return [ERR.OK] | |
# If it isn't a number | |
else | |
puts "'#{$char}' is not a number, but is between square brackets [] !" | |
end | |
end | |
# If we expect a string, and the character isn't '"' | |
if $isstring && char != '"' | |
# Add the character to the current string | |
$string+=char | |
# Return OK value | |
return [ERR.OK] | |
end | |
# If the character is a null character (what ?!) or a space | |
if char==0 || char==' ' | |
# If we have to skip ( After ? or ! ) | |
elsif $skip | |
log "SKIP" | |
$skip=false | |
# Return OK value | |
return [ERR.OK] | |
# Number | |
elsif char=='[' | |
$isnumber=true | |
elsif char==']' | |
$isnumber=false | |
$stack.push $number | |
$number=0 | |
# Check for single hexadecimal number | |
elsif char=~/[0-9a-f]/ | |
x=char.to_i 16 | |
$stack.push x | |
# String | |
elsif char=='"' | |
# If we don't expect a string ... | |
if ! $isstring | |
# ... we do now | |
$isstring=true | |
# ... but if we do ... | |
else | |
# ... we don't now | |
$isstring=false | |
# And add the global string in ASCII to the stack | |
$string.split('').each do |c| | |
$stack.push c.ord | |
end | |
# Reset global string | |
$string="" | |
end | |
# Output | |
# Output as number | |
elsif char==',' | |
log "NUMBER OUT" | |
print $stack.pop | |
log "" | |
# Output as ASCII | |
elsif char=='.' | |
log "CHAR OUT" | |
print $stack.pop.chr | |
puts if log | |
# Output the stack | |
elsif char=='P' | |
log "PRINT" | |
$stack.print | |
# Manipulation | |
# Reverse `x` items | |
elsif char=='~' | |
log "REVERSE #{x=$stack.pop}" | |
$stack.reverse x | |
# Copy top value | |
elsif char==':' | |
log "COPY" | |
x=$stack.pop | |
$stack.push x | |
$stack.push x | |
# Add, subtract, multiplicate, devide and modulus | |
elsif char=~/[\+\-\*\/\%]/ | |
log "EXPR #{char}" | |
y=$stack.pop | |
x=$stack.pop | |
# Eval is safe here | |
z=eval("#{x}#{char}#{y}") | |
$stack.push z | |
# Get length | |
elsif char=='#' | |
log "LENGTH" | |
x=$stack.length | |
$stack.push x | |
# Go back to the start of the line | |
elsif char=='<' | |
log "HOME" | |
$loc[:x]=-1 | |
# Go `x` lines down | |
elsif char=='v' | |
log "DOWN" | |
x=$stack.pop | |
$loc[:x]=-1 | |
$loc[:y]+=x | |
# Go `x` lines up | |
elsif char=='^' | |
log "UP" | |
x=$stack.pop | |
$loc[:x]=-1 | |
$loc[:y]-=x | |
# Contitional. Go 1 to the right if `x` is not 0, or 2 to the right if it is | |
elsif char=='?' | |
log "COND" | |
x=$stack.pop | |
if x==0 | |
$skip=true | |
end | |
# Skip the following character | |
elsif char=='!' | |
log "SKIP" | |
$skip=true | |
# Delete top value | |
elsif char=='x' | |
log "DELETE" | |
$stack.pop | |
# Exit file | |
elsif char==';' | |
return [ERR.EXIT] | |
# If we have NO idea what we have to do, just throw an error | |
else | |
return [ERR.UNKNOWN, char] | |
end | |
return [ERR.OK] | |
end | |
# Explode an array | |
def explode pre | |
# New array | |
post=[] | |
# Split each string from `pre` into its characters | |
pre.each.with_index do |item, inx| | |
post[inx] = item.split '' | |
end | |
# New array | |
post | |
end | |
# Get the character at the current position | |
def get | |
$content [ $loc[:y] ] [ $loc[:x] ] | |
end | |
def main args | |
# No arguments enables debug mode | |
if args.count == 0 | |
$debug=true | |
log "Debug enabled!" | |
end | |
# Setting filename | |
filename=args[0] || "debug.cpl" | |
log "Filename: #{filename}" | |
# Loading FileIO to load files | |
load "FileIO" | |
# Loading FileIO for current file | |
fio=FileIO.new "#{filename}" | |
# Convert 2D array to 3D array | |
# ['abc', 'def'] => [['a','b','c'], ['d','e','f']] | |
$content=explode fio.getContent | |
# Logging content if debug mode enabled | |
if log | |
puts "Content:" | |
$content.each do |line| | |
# Two tabs | |
print "\t\t" | |
# Outputting each line | |
line.each do |char| | |
print char | |
end | |
# Newline | |
puts | |
end | |
# Newline | |
puts | |
end | |
# While we don't have to exit | |
while x[0] != ERR.EXIT | |
# Log the character | |
log "'#{get}'" | |
# Default errorcode | |
x=ERR.ERR | |
begin | |
# Parsing current character | |
x=parse get | |
# When error happens | |
rescue Exception => e | |
# Print location and character | |
puts "(#{$loc[:x]},#{$loc[:y]}) '#{get}'" | |
# Print default stacktrace | |
raise e | |
end | |
# If it didn't run correctly | |
if x[0] != ERR.OK | |
# Output location, character, errorcode and errormessage | |
puts "(#{$loc[:x]},#{$loc[:y]}) '#{get}' #{ERR.get x[0]}: '#{x[1]}'" | |
end | |
# Next character | |
$loc[:x]+=1 | |
end | |
end | |
# Start with arguments | |
main ARGV |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment