stackGen

by not important

CoffeeScript

# imperative stack-based programming language, like Forth
# http://docs.oracle.com/cd/E19455-01/816-1177-10/fthtools.html
class StackProg
    words: {}

    constructor: ->

    run: (sourceCode, state, stack = []) ->
        defaultOptions = 
            variables: {}
            functions: {}
            operations: []
            store: []
            returnStack: []
            storeIndex: 0
        state = state || defaultOptions
        state.operations = sourceCode.replace(/(\n|\t)/g, ' ').split(' ').concat state.operations
        while operation = state.operations.shift()
            if operation is 'variable'
                name = state.operations.shift()
                state.variables[name] = null
            else if state.functions[operation] isnt undefined
                state.functions[operation]()
            else if state.variables[operation] isnt undefined
                stack.unshift operation
            else
                @evaluate state, stack, operation
        stack.pop()

    evaluate: (state, stack, operation) ->
        if !isNaN(+operation)
            @words['\d+'] state, stack, +operation
        else if operation.charAt(0) is '"'
            value = operation.match /\s*\"(.*?)\"/
            value = value || []
            @words['\s*\"(.*?)\"'].call this, state, stack, value[1]
        else
            if typeof @words[operation] is 'string'
                stack.unshift @run @words[operation], state, stack
            else
                if @words[operation]
                    @words[operation].call this, state, stack
                else
                    throw "Error: Undefined command '#{operation}'"

StackProg::words['\d+'] = (state, stack, val) ->
    stack.unshift val

StackProg::words['-'] = (state, stack) ->
    a = stack.shift()
    b = stack.shift()
    stack.unshift a - b

StackProg::words['+'] = (state, stack) ->
    a = stack.shift()
    b = stack.shift()
    stack.unshift a + b
    
StackProg::words['*'] =...