Skip to content

Instantly share code, notes, and snippets.

@jbilcke
Created November 7, 2011 15:56
Show Gist options
  • Save jbilcke/1345341 to your computer and use it in GitHub Desktop.
Save jbilcke/1345341 to your computer and use it in GitHub Desktop.
Push.coffee
#/*****************************************************************************
# * *
# * PushScript *
# * Copyright (C) 2008-2010 Jonathan Klein *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU General Public License as published by *
# * the Free Software Foundation; either version 2 of the License, or *
# * (at your option) any later version. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU General Public License for more details. *
# * *
# * You should have received a copy of the GNU General Public License *
# * along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
# *****************************************************************************/
#
# Push types
#
# slight modification to built-in types to lets us compare them like program
pushFloat = (inValue) ->
@_value = inValue
@toString = ->
decimal = /\./
unless decimal.test(@_value)
@_value + ".0"
else
@_value
@equals = (inOther) ->
isPushFloat(inOther) and @_value == inOther._value
pushInt = (inValue) ->
@_value = inValue
@toString = ->
@_value
@equals = (inOther) ->
isPushInt(inOther) and @_value == inOther._value
pushInstruction = (inStack, inFunction) ->
@_function = inFunction
@_stack = inStack
@call = (inInterpreter) ->
@_function inInterpreter, @_stack
pushDefine = (inStack, inValue) ->
@_value = inValue
@_stack = inStack
@call = (inInterpreter) ->
@_stack.push @_value
isPushProgram = (inObject) ->
typeof (inObject) == "object" and inObject["_isPushProgram"] == true
isPushFloat = (inObject) ->
typeof (inObject) == "object" and inObject.constructor == pushFloat
isPushInt = (inObject) ->
typeof (inObject) == "object" and inObject.constructor == pushInt
isPushInstruction = (inObject) ->
typeof (inObject) == "object" and inObject.constructor == pushInstruction
isPushDefine = (inObject) ->
typeof (inObject) == "object" and inObject.constructor == pushDefine
pushInstructionRandomBool = (inInterpreter, inStack) ->
inStack.push Math.random() > 0.5
pushInstructionRandomNumber = (inInterpreter, inStack) ->
inStack.push Math.random() * 10
pushInstructionRandomName = (inInterpreter, inStack) ->
inStack.push "n" + inInterpreter._nameCounter++
pushInstructionRandomBoundName = (inInterpreter, inStack) ->
pushInstructionAnd = (inInterpreter, inStack) ->
if inStack.length > 1
o1 = inStack.pop()
o2 = inStack.pop()
inInterpreter.boolStack.push o2 and o1
pushInstructionOr = (inInterpreter, inStack) ->
if inStack.length > 1
o1 = inStack.pop()
o2 = inStack.pop()
inInterpreter.boolStack.push o2 or o1
pushInstructionNot = (inInterpreter, inStack) ->
inInterpreter.boolStack.push not inStack.pop() if inStack.length > 0
pushInstructionFromInteger = (inInterpreter, inStack) ->
inStack.push inInterpreter.intStack.pop() if inStack.length > 0
pushInstructionFromFloat = (inInterpreter, inStack) ->
inStack.push inInterpreter.floatStack.pop() if inStack.length > 0
pushInstructionFromBoolean = (inInterpreter, inStack) ->
if inStack.length > 0
num = 0
num = 1 if inInterpreter.boolStack.pop() == true
inStack.push num
pushInstructionQuote = (inInterpreter, inStack) ->
inStack.push inInterpreter.execStack.pop() if inInterpreter.execStack.length > 0
pushInstructionCar = (inInterpreter, inStack) ->
if inStack.length > 0
top = inStack.pop()
if isPushProgram(top)
inStack.push top.shift()
else
inStack.push top
pushInstructionCdr = (inInterpreter, inStack) ->
if inStack.length > 0
top = inStack.pop()
if isPushProgram(top)
top.shift()
inStack.push top
else
inStack.push new Array()
pushInstructionNth = (inInterpreter, inStack) ->
if inStack.length > 0 and inInterpreter.intStack.length > 0
top = inStack.pop()
index = inInterpreter.intStack.pop()
if isPushProgram(top)
index %= top.length
inStack.push top[(top.length - 1) - index]
else
inStack.push top
pushInstructionContains = (inInterpreter, inStack) ->
if inStack.length > 1
program = inStack.pop()
sub = inStack.pop()
i = 0
while i < program.length
if program[i].equals(sub)
inInterpreter.boolStack.push true
return
i++
inInterpreter.boolStack.push false
pushInstructionList = (inInterpreter, inStack) ->
if inStack.length > 1
o1 = inStack.pop()
o2 = inStack.pop()
newCode = new Array()
newCode.push o2
newCode.push o1
inStack.push newCode
pushInstructionCons = (inInterpreter, inStack) ->
if inStack.length > 1
cdr = inStack.pop()
car = inStack.pop()
unless isPushProgram(cdr)
program = new Array()
program.push cdr
cdr = program
cdr.unshift car
inStack.push cdr
pushInstructionNoop = (inInterpreter, inStack) ->
pushInstructionDo = (inInterpreter, inStack) ->
if inInterpreter.codeStack.length > 0
inInterpreter.execStack.push "CODE.POP"
inInterpreter.execStack.push inInterpreter.codeStack[inInterpreter.codeStack.length - 1]
pushInstructionDoStar = (inInterpreter, inStack) ->
inInterpreter.execStack.push inInterpreter.codeStack.pop() if inInterpreter.codeStack.length > 0
pushInstructionDoCount = (inInterpreter, inStack) ->
if inStack.length > 0 and inInterpreter.intStack.length > 0
count = inInterpreter.intStack.pop()
return if count < 1
code = inStack.pop()
program = new Array()
program.push new pushInt(0)
program.push new pushInt(count - 1)
program.push "EXEC.DO*RANGE"
program.push code
inInterpreter.execStack.push program
pushInstructionDoTimes = (inInterpreter, inStack) ->
if inStack.length > 0 and inInterpreter.intStack.length > 1
code = inStack.pop()
unless isPushProgram(code)
program = new Array()
program.push code
code = program
code.splice 0, 0, "INTEGER.POP"
inStack.push code
pushInstructionDoRange inInterpreter, inStack
pushInstructionDoRange = (inInterpreter, inStack) ->
if inStack.length > 0 and inInterpreter.intStack.length > 1
end = inInterpreter.intStack.pop()
start = inInterpreter.intStack.pop()
code = inStack.pop()
inc = 1
inc = -1 if end > start
i = end
while i != start + inc
inInterpreter.execStack.push code
inInterpreter.execStack.push new pushInt(i)
i += inc
pushInstructionIf = (inInterpreter, inStack) ->
if inStack.length > 1 and inInterpreter.boolStack.length > 0
cond = inInterpreter.boolStack.pop()
ifFalse = inStack.pop()
ifTrue = inStack.pop()
if cond
inInterpreter.execStack.push ifTrue
else
inInterpreter.execStack.push ifFalse
pushInstructionLength = (inInterpreter, inStack) ->
if inStack.length > 0
code = inStack.pop()
inInterpreter.intStack.push code.length
pushInstructionNull = (inInterpreter, inStack) ->
if inStack.length > 0
code = inStack.pop()
inInterpreter.boolStack.push isPushProgram(code) and code.length == 0
pushInstructionAtom = (inInterpreter, inStack) ->
inInterpreter.boolStack.push not isPushProgram(inStack.pop()) if inStack.length > 0
pushInstructionK = (inInterpreter, inStack) ->
inStack.splice inStack.length - 1, 1 if inStack.length > 1
pushInstructionS = (inInterpreter, inStack) ->
if inStack.length > 2
a = inStack.pop()
b = inStack.pop()
c = inStack.pop()
list = new Array()
list.push b
list.push c
inStack.push list
inStack.push c
inStack.push a
pushInstructionY = (inInterpreter, inStack) ->
if inStack.length > 0
top = inStack.pop()
list = new Array()
list.push "EXEC.Y"
list.push top
pushInstructionGreaterThan = (inInterpreter, inStack) ->
if inStack.length > 1
o1 = inStack.pop()
o2 = inStack.pop()
inInterpreter.boolStack.push o2 > o1
pushInstructionLessThan = (inInterpreter, inStack) ->
if inStack.length > 1
o1 = inStack.pop()
o2 = inStack.pop()
inInterpreter.boolStack.push o2 < o1
pushInstructionEquals = (inInterpreter, inStack) ->
if inStack.length > 1
o1 = inStack.pop()
o2 = inStack.pop()
inInterpreter.boolStack.push o2.equals(o1)
pushInstructionAdd = (inInterpreter, inStack) ->
if inStack.length > 1
o1 = inStack.pop()
o2 = inStack.pop()
inStack.push o2 + o1
pushInstructionSubtract = (inInterpreter, inStack) ->
if inStack.length > 1
o1 = inStack.pop()
o2 = inStack.pop()
inStack.push o2 - o1
pushInstructionCos = (inInterpreter, inStack) ->
inStack.push Math.cos(inStack.pop()) if inStack.length > 0
pushInstructionSin = (inInterpreter, inStack) ->
inStack.push Math.sin(inStack.pop()) if inStack.length > 0
pushInstructionTan = (inInterpreter, inStack) ->
inStack.push Math.tan(inStack.pop()) if inStack.length > 0
pushInstructionMultiply = (inInterpreter, inStack) ->
if inStack.length > 1
o1 = inStack.pop()
o2 = inStack.pop()
inStack.push o2 * o1
pushInstructionDivide = (inInterpreter, inStack) ->
if inStack.length > 1
o1 = inStack.pop()
if o1 == 0.0
inStack.push o1
return
o2 = inStack.pop()
inStack.push o2 / o1
pushInstructionModulus = (inInterpreter, inStack) ->
if inStack.length > 1
o1 = inStack.pop()
o2 = inStack.pop()
inStack.push o2 % o1
pushInstructionMin = (inInterpreter, inStack) ->
if inStack.length > 1
o1 = inStack.pop()
o2 = inStack.pop()
inStack.push Math.min(o1, o2)
pushInstructionMax = (inInterpreter, inStack) ->
if inStack.length > 1
o1 = inStack.pop()
o2 = inStack.pop()
inStack.push Math.max(o1, o2)
pushInstructionPop = (inInterpreter, inStack) ->
inStack.pop() if inStack.length > 0
pushInstructionStackdepth = (inInterpreter, inStack) ->
inInterpreter.intStack.push inStack.length
pushInstructionDup = (inInterpreter, inStack) ->
inStack.push inStack[inStack.length - 1] if inStack.length > 0
pushInstructionDefine = (inInterpreter, inStack) ->
inInterpreter[inInterpreter.nameStack.pop()] = new pushDefine(inStack, inStack.pop()) if inStack.length > 0 and inInterpreter.nameStack.length > 0
pushInstructionYank = (inInterpreter, inStack) ->
intReq = 1
intReq = 2 if inStack == inInterpreter.intStack
if inInterpreter.intStack.length >= intReq and inStack.length > 0
index = inInterpreter.intStack.pop()
inStack.push inStack.splice(inStack.length - (index + 1), 1)[0] if index < inStack.length
pushInstructionYankDup = (inInterpreter, inStack) ->
intReq = 1
intReq = 2 if inStack == inInterpreter.intStack
if inInterpreter.intStack.length >= intReq and inStack.length > 0
index = inInterpreter.intStack.pop()
inStack.push inStack[inStack.length - (index + 1)] if index < inStack.length
pushInstructionShove = (inInterpreter, inStack) ->
intReq = 1
intReq = 2 if inStack == inInterpreter.intStack
if inInterpreter.intStack.length >= intReq and inStack.length > 0
index = inInterpreter.intStack.pop()
if index < inStack.length
replace = inStack.pop()
inStack.splice inStack.length - index, 0, replace
pushInstructionSwap = (inInterpreter, inStack) ->
if inStack.length > 1
o1 = inStack.pop()
o2 = inStack.pop()
inStack.push o1
inStack.push o2
pushInstructionRot = (inInterpreter, inStack) ->
if inStack.length > 2
index = inStack.length - 3
inStack.push inStack.splice(index, 1)[0]
pushInstructionFlush = (inInterpreter, inStack) ->
inStack.splice 0, inStack.length
float_input = (inInterpreter) ->
inInterpreter.floatStack.push inInterpreter["inputValue"]
inInterpreter.intStack.push inInterpreter["inputValue"]
pushInterpreter = ->
@floatStack = []
@execStack = []
@codeStack = []
@intStack = []
@boolStack = []
@nameStack = []
@_nameCounter = 0
@intStack.push = (inValue) ->
@parentpush = Array::push
@parentpush parseInt(inValue)
@boolStack.push = (inValue) ->
@parentpush = Array::push
@parentpush inValue != 0
@codeStack.push = (inValue) ->
@parentpush = Array::push
inValue = inValue.copy() if isPushProgram(inValue)
@parentpush inValue
@execStack.push = (inValue) ->
@parentpush = Array::push
inValue = inValue.copy() if isPushProgram(inValue)
@parentpush inValue
@clearStacks = ->
@floatStack.splice 0, @floatStack.length
@execStack.splice 0, @execStack.length
@codeStack.splice 0, @codeStack.length
@intStack.splice 0, @intStack.length
@boolStack.splice 0, @boolStack.length
@nameStack.splice 0, @nameStack.length
@toString = ->
text = "Float stack contents: " + @floatStack + "<br>"
text += "Int stack contents: " + @intStack + "<br>"
text += "Bool stack contents: " + @boolStack + "<br>"
text += "Name stack contents: " + @nameStack + "<br>"
text += "Code stack contents: " + @codeStack + "<br>"
text += "Exec stack contents: " + @execStack + "<br>"
text
@floatStackTop = ->
@floatStack[@floatStack.length - 1]
@intStackTop = ->
@intStack[@intStack.length - 1]
@boolStackTop = ->
@boolStack[@boolStack.length - 1]
@nameStackTop = ->
@boolStack[@nameStack.length - 1]
@execStackTop = ->
@execStack[@execStack.length - 1]
@codeStackTop = ->
@codeStack[@codeStack.length - 1]
this["INTEGER.FROMFLOAT"] = new pushInstruction(@intStack, pushInstructionFromFloat)
this["BOOLEAN.FROMFLOAT"] = new pushInstruction(@boolStack, pushInstructionFromFloat)
this["FLOAT.FROMINTEGER"] = new pushInstruction(@floatStack, pushInstructionFromInteger)
this["BOOLEAN.FROMINTEGER"] = new pushInstruction(@boolStack, pushInstructionFromInteger)
this["FLOAT.FROMBOOLEAN"] = new pushInstruction(@floatStack, pushInstructionFromBoolean)
this["INTEGER.FROMBOOLEAN"] = new pushInstruction(@integerStack, pushInstructionFromBoolean)
this["FLOAT.COS"] = new pushInstruction(@floatStack, pushInstructionCos)
this["FLOAT.SIN"] = new pushInstruction(@floatStack, pushInstructionSin)
this["FLOAT.TAN"] = new pushInstruction(@floatStack, pushInstructionTan)
this["INTEGER.>"] = new pushInstruction(@intStack, pushInstructionGreaterThan)
this["FLOAT.>"] = new pushInstruction(@floatStack, pushInstructionGreaterThan)
this["INTEGER.<"] = new pushInstruction(@intStack, pushInstructionLessThan)
this["FLOAT.<"] = new pushInstruction(@floatStack, pushInstructionLessThan)
this["INTEGER.="] = new pushInstruction(@intStack, pushInstructionEquals)
this["FLOAT.="] = new pushInstruction(@floatStack, pushInstructionEquals)
this["BOOLEAN.="] = new pushInstruction(@boolStack, pushInstructionEquals)
this["NAME.="] = new pushInstruction(@nameStack, pushInstructionEquals)
this["EXEC.="] = new pushInstruction(@execStack, pushInstructionEquals)
this["CODE.="] = new pushInstruction(@codeStack, pushInstructionEquals)
this["INTEGER.+"] = new pushInstruction(@intStack, pushInstructionAdd)
this["FLOAT.+"] = new pushInstruction(@floatStack, pushInstructionAdd)
this["INTEGER.-"] = new pushInstruction(@intStack, pushInstructionSubtract)
this["FLOAT.-"] = new pushInstruction(@floatStack, pushInstructionSubtract)
this["INTEGER./"] = new pushInstruction(@intStack, pushInstructionDivide)
this["FLOAT./"] = new pushInstruction(@floatStack, pushInstructionDivide)
this["INTEGER.*"] = new pushInstruction(@intStack, pushInstructionMultiply)
this["FLOAT.*"] = new pushInstruction(@floatStack, pushInstructionMultiply)
this["INTEGER.%"] = new pushInstruction(@intStack, pushInstructionModulus)
this["FLOAT.%"] = new pushInstruction(@floatStack, pushInstructionModulus)
this["INTEGER.MIN"] = new pushInstruction(@intStack, pushInstructionMin)
this["FLOAT.MIN"] = new pushInstruction(@floatStack, pushInstructionMin)
this["INTEGER.MAX"] = new pushInstruction(@intStack, pushInstructionMax)
this["FLOAT.MAX"] = new pushInstruction(@floatStack, pushInstructionMax)
this["FLOAT.DEFINE"] = new pushInstruction(@floatStack, pushInstructionDefine)
this["INTEGER.DEFINE"] = new pushInstruction(@intStack, pushInstructionDefine)
this["CODE.DEFINE"] = new pushInstruction(@codeStack, pushInstructionDefine)
this["EXEC.DEFINE"] = new pushInstruction(@execStack, pushInstructionDefine)
this["BOOLEAN.DEFINE"] = new pushInstruction(@boolStack, pushInstructionDefine)
this["FLOAT.POP"] = new pushInstruction(@floatStack, pushInstructionPop)
this["INTEGER.POP"] = new pushInstruction(@intStack, pushInstructionPop)
this["CODE.POP"] = new pushInstruction(@codeStack, pushInstructionPop)
this["EXEC.POP"] = new pushInstruction(@execStack, pushInstructionPop)
this["BOOLEAN.POP"] = new pushInstruction(@boolStack, pushInstructionPop)
this["NAME.POP"] = new pushInstruction(@nameStack, pushInstructionPop)
this["FLOAT.DUP"] = new pushInstruction(@floatStack, pushInstructionDup)
this["INTEGER.DUP"] = new pushInstruction(@intStack, pushInstructionDup)
this["CODE.DUP"] = new pushInstruction(@codeStack, pushInstructionDup)
this["EXEC.DUP"] = new pushInstruction(@execStack, pushInstructionDup)
this["BOOLEAN.DUP"] = new pushInstruction(@boolStack, pushInstructionDup)
this["NAME.DUP"] = new pushInstruction(@nameStack, pushInstructionDup)
this["FLOAT.YANK"] = new pushInstruction(@floatStack, pushInstructionYank)
this["INTEGER.YANK"] = new pushInstruction(@intStack, pushInstructionYank)
this["CODE.YANK"] = new pushInstruction(@codeStack, pushInstructionYank)
this["EXEC.YANK"] = new pushInstruction(@execStack, pushInstructionYank)
this["BOOLEAN.YANK"] = new pushInstruction(@boolStack, pushInstructionYank)
this["NAME.YANK"] = new pushInstruction(@nameStack, pushInstructionYank)
this["FLOAT.YANKDUP"] = new pushInstruction(@floatStack, pushInstructionYankDup)
this["INTEGER.YANKDUP"] = new pushInstruction(@intStack, pushInstructionYankDup)
this["CODE.YANKDUP"] = new pushInstruction(@codeStack, pushInstructionYankDup)
this["EXEC.YANKDUP"] = new pushInstruction(@execStack, pushInstructionYankDup)
this["BOOLEAN.YANKDUP"] = new pushInstruction(@boolStack, pushInstructionYankDup)
this["NAME.YANKDUP"] = new pushInstruction(@nameStack, pushInstructionYankDup)
this["FLOAT.SHOVE"] = new pushInstruction(@floatStack, pushInstructionShove)
this["INTEGER.SHOVE"] = new pushInstruction(@intStack, pushInstructionShove)
this["CODE.SHOVE"] = new pushInstruction(@codeStack, pushInstructionShove)
this["EXEC.SHOVE"] = new pushInstruction(@execStack, pushInstructionShove)
this["BOOLEAN.SHOVE"] = new pushInstruction(@boolStack, pushInstructionShove)
this["NAME.SHOVE"] = new pushInstruction(@nameStack, pushInstructionShove)
this["FLOAT.ROT"] = new pushInstruction(@floatStack, pushInstructionRot)
this["INTEGER.ROT"] = new pushInstruction(@intStack, pushInstructionRot)
this["CODE.ROT"] = new pushInstruction(@codeStack, pushInstructionRot)
this["EXEC.ROT"] = new pushInstruction(@execStack, pushInstructionRot)
this["BOOLEAN.ROT"] = new pushInstruction(@boolStack, pushInstructionRot)
this["NAME.ROT"] = new pushInstruction(@nameStack, pushInstructionRot)
this["FLOAT.STACKDEPTH"] = new pushInstruction(@floatStack, pushInstructionStackdepth)
this["INTEGER.STACKDEPTH"] = new pushInstruction(@intStack, pushInstructionStackdepth)
this["CODE.STACKDEPTH"] = new pushInstruction(@codeStack, pushInstructionStackdepth)
this["EXEC.STACKDEPTH"] = new pushInstruction(@execStack, pushInstructionStackdepth)
this["BOOLEAN.STACKDEPTH"] = new pushInstruction(@boolStack, pushInstructionStackdepth)
this["NAME.STACKDEPTH"] = new pushInstruction(@nameStack, pushInstructionStackdepth)
this["FLOAT.SWAP"] = new pushInstruction(@floatStack, pushInstructionSwap)
this["INTEGER.SWAP"] = new pushInstruction(@intStack, pushInstructionSwap)
this["CODE.SWAP"] = new pushInstruction(@codeStack, pushInstructionSwap)
this["EXEC.SWAP"] = new pushInstruction(@execStack, pushInstructionSwap)
this["BOOLEAN.SWAP"] = new pushInstruction(@boolStack, pushInstructionSwap)
this["NAME.SWAP"] = new pushInstruction(@nameStack, pushInstructionSwap)
this["FLOAT.FLUSH"] = new pushInstruction(@floatStack, pushInstructionFlush)
this["INTEGER.FLUSH"] = new pushInstruction(@intStack, pushInstructionFlush)
this["CODE.FLUSH"] = new pushInstruction(@codeStack, pushInstructionFlush)
this["EXEC.FLUSH"] = new pushInstruction(@execStack, pushInstructionFlush)
this["BOOLEAN.FLUSH"] = new pushInstruction(@boolStack, pushInstructionFlush)
this["NAME.FLUSH"] = new pushInstruction(@nameStack, pushInstructionFlush)
this["BOOLEAN.AND"] = new pushInstruction(@boolStack, pushInstructionAnd)
this["BOOLEAN.OR"] = new pushInstruction(@boolStack, pushInstructionOr)
this["BOOLEAN.NOT"] = new pushInstruction(@boolStack, pushInstructionNot)
this["CODE.QUOTE"] = new pushInstruction(@codeStack, pushInstructionQuote)
this["CODE.CAR"] = new pushInstruction(@codeStack, pushInstructionCar)
this["CODE.CDR"] = new pushInstruction(@codeStack, pushInstructionCdr)
this["CODE.CONTAINS"] = new pushInstruction(@codeStack, pushInstructionContains)
this["CODE.NTH"] = new pushInstruction(@codeStack, pushInstructionNth)
this["CODE.LIST"] = new pushInstruction(@codeStack, pushInstructionList)
this["CODE.CONS"] = new pushInstruction(@codeStack, pushInstructionCons)
this["CODE.DO"] = new pushInstruction(@codeStack, pushInstructionDo)
this["CODE.DO*"] = new pushInstruction(@codeStack, pushInstructionDoStar)
this["CODE.DO*RANGE"] = new pushInstruction(@codeStack, pushInstructionDoRange)
this["CODE.DO*COUNT"] = new pushInstruction(@codeStack, pushInstructionDoCount)
this["CODE.DO*TIMES"] = new pushInstruction(@codeStack, pushInstructionDoTimes)
this["CODE.IF"] = new pushInstruction(@codeStack, pushInstructionIf)
this["CODE.NULL"] = new pushInstruction(@codeStack, pushInstructionNull)
this["CODE.ATOM"] = new pushInstruction(@codeStack, pushInstructionAtom)
this["CODE.LENGTH"] = new pushInstruction(@codeStack, pushInstructionLength)
this["CODE.NOOP"] = new pushInstruction(@codeStack, pushInstructionNoop)
this["EXEC.DO*RANGE"] = new pushInstruction(@execStack, pushInstructionDoRange)
this["EXEC.DO*TIMES"] = new pushInstruction(@execStack, pushInstructionDoTimes)
this["EXEC.DO*COUNT"] = new pushInstruction(@execStack, pushInstructionDoCount)
this["EXEC.IF"] = new pushInstruction(@execStack, pushInstructionIf)
this["EXEC.S"] = new pushInstruction(@execStack, pushInstructionS)
this["EXEC.K"] = new pushInstruction(@execStack, pushInstructionK)
this["EXEC.Y"] = new pushInstruction(@execStack, pushInstructionY)
this["BOOLEAN.RAND"] = new pushInstruction(@boolStack, pushInstructionRandomBool)
this["INTEGER.RAND"] = new pushInstruction(@intStack, pushInstructionRandomNumber)
this["FLOAT.RAND"] = new pushInstruction(@floatStack, pushInstructionRandomNumber)
this["NAME.RAND"] = new pushInstruction(@nameStack, pushInstructionRandomName)
this["TRUE"] = new pushDefine(@boolStack, true)
this["FALSE"] = new pushDefine(@boolStack, false)
this["INPUT"] = float_input
pushRunProgram = (inInterpreter, inProgramArray) ->
inInterpreter._effort = 0
test = new Array()
inInterpreter.codeStack.push inProgramArray
inInterpreter.execStack.push inProgramArray
while inInterpreter.execStack.length > 0
atom = inInterpreter.execStack.pop()
if isPushProgram(atom)
while atom.length > 0
inInterpreter.execStack.push atom.pop()
else if isPushFloat(atom)
inInterpreter.floatStack.push atom._value
else if isPushInt(atom)
inInterpreter.intStack.push atom._value
else
func = inInterpreter[atom]
unless func?
inInterpreter.nameStack.push atom
else if isPushInstruction(func) or isPushDefine(func)
func.call inInterpreter
else
func inInterpreter
inInterpreter._effort++
if inInterpreter._effort > 1000
inInterpreter._errorMessage = "Hardcoded effort limit reached (1000 instructions)"
inInterpreter._error = 1
return -1
0
pushSetInputValue = (inInterpreter, inValue) ->
inInterpreter["inputValue"] = inValue
pushFloatStackPush = (inInterpreter, inValue) ->
inInterpreter.floatStack.push inValue
pushIntStackPush = (inInterpreter, inValue) ->
inInterpreter.intStack.push inValue
pushParseString = (inString) ->
parens = /[\(\)]/
inString = " ( " + inString + " ) " unless parens.test(inString)
inString = inString.replace(/([\(\)])/g, " $1 ")
inString = inString.replace(/[\r\n]/g, " ")
tokens = inString.split(" ")
listStack = new Array()
currentList = null
lastList = null
spaces = /\ +/
decimal = /\./
num = 0
i = 0
while i < tokens.length
unless spaces.test(tokens[i])
if tokens[i] == "("
listStack.push new Array()
currentList = listStack[listStack.length - 1]
else if tokens[i] == ")"
return null if listStack.length < 1
newList = listStack.pop()
lastList = newList
currentList = listStack[listStack.length - 1]
currentList.push newList if currentList?
else if (num = parseFloat(tokens[i])) == tokens[i]
return null unless currentList?
if decimal.test(tokens[i])
currentList.push new pushFloat(num)
else
currentList.push new pushInt(num)
else unless tokens[i] == ""
return null unless currentList?
currentList.push tokens[i]
i++
return null if listStack.length > 0
lastList
#
# Parses a string into a program and executes the program with a new interpreter
#
# @return The string state of the interpreter
#
pushRunString = (inProgram) ->
program = pushParseString(inProgram)
interpreter = new pushInterpreter()
info = pushRunProgram(interpreter, program)
interpreter.toString()
String::equals = (inOther) ->
inOther == this
Boolean::equals = (inOther) ->
inOther == this
Number::equals = (inOther) ->
inOther == this
Array::_isPushProgram = true
Array::toString = ->
str = ""
i = 0
while i < @length
str += this[i] + " "
i++
"( " + str + ")"
Array::copy = ->
newCopy = new Array()
i = 0
while i < @length
if isPushProgram(this[i])
newCopy.push this[i].copy()
else
newCopy.push this[i]
i++
newCopy
Array::equals = (inOther) ->
return false unless isPushProgram(inOther)
return false unless inOther.length == @length
i = 0
while i < @length
return false unless this[i].equals(inOther[i])
i++
true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment