Commits

Nick Meharry committed 6b62e4a

Beginning of major rewrite.

Comments (0)

Files changed (3)

-from gtypes import *
+from gtypes import builtin, Box, Number, String
 
-vars = {}
+from sys import stderr
 
-Tilde = GFunc(1)
-def run_INT(stack, a):
-    return [GObject(~a.value, INT)]
-Tilde.run_INT = run_INT
-def run_STR(stack, a):
-    stack.eval(a.value, stack)
-    return []
-Tilde.run_STR = run_STR
-def run_BLOCK(stack, a):
-    stack.eval(' '.join(a.value), stack)
-    return []
-Tilde.run_BLOCK = run_BLOCK
-def run_ARRAY(stack, a):
-    return a.value
-Tilde.run_ARRAY = run_ARRAY
-vars['~'] = Tilde
-del Tilde, run_INT, run_STR, run_BLOCK, run_ARRAY
-
-#------------------------------------------------------------------------------
-
-Backtick = GFunc(1)
-def run(stack, a):
-    return [GObject(repr(a.value), STR)]
-Backtick.run_INT = run
-Backtick.run_STR = run
-def run_iterable(stack, a):
-    return [GObject(str(a), STR)]
-Backtick.run_BLOCK = run_iterable
-Backtick.run_ARRAY = run_iterable
-vars['`'] = Backtick
-del Backtick, run, run_iterable
-
-#------------------------------------------------------------------------------
-
-Bang = GFunc(1)
-def run(stack, a):
-    result = GObject(0, INT)
-    if a.type is INT:
-        result.value = int(a.value == 0)
-    elif a.type is STR:
-        result.value = int(a.value == '')
-    elif a.type in (ARRAY, BLOCK):
-        result.value = int(len(a.value) == 0)
-    return [result]
-Bang.run_INT = run
-Bang.run_STR = run
-Bang.run_BLOCK = run
-Bang.run_ARRAY = run
-vars['!'] = Bang
-del Bang, run
-
-
-#------------------------------------------------------------------------------
-
-At = GFunc(3, ((ANY, ANY, ANY),))
-def run(stack, a, b, c):
-    return [b, a, c]
-At.run_ANY_ANY_ANY = run
-vars['@'] = At
-del At, run
-
-#------------------------------------------------------------------------------
-
-Dollar = GFunc((1, 2), ((INT,), (ARRAY,), (STR,), (BLOCK, ARRAY)))
-def run_INT(stack, a):
-    return [stack[a.value]]
-Dollar.run_INT = run_INT
-def run_ARRAY(stack, a):
-    a.value.sort()
-    return [a]
-Dollar.run_ARRAY = run_ARRAY
-def run_STR(stack, a):
-    s = ''.join(sorted(a.value))
-    return [GObject(s, STR)]
-Dollar.run_STR = run_STR
-vars['$'] = Dollar
-del Dollar, run_INT, run_ARRAY, run_STR
-
-#------------------------------------------------------------------------------
-
-Plus = GFunc(2, ((ANY, ANY),))
-def run_ANY_ANY(stack, a, b):
-    if a.type is b.type is INT:
-        return [GObject(a.value + b.value, INT)]
-    elif a.type is STR and b.type is BLOCK:
-        b.value = a.value + ' ' + b.value
-        return [b]
-    elif a.type is BLOCK and b.type is STR:
-        a.value = b.value + ' ' + a.value
-        return [a]
-    elif a.type is b.type and a.type in (ARRAY, STR):
-        return [GObject(b.value + a.value, a.type)]
-Plus.run_ANY_ANY = run_ANY_ANY
-vars['+'] = Plus
-del Plus, run_ANY_ANY
-
-#------------------------------------------------------------------------------
-
-Minus = GFunc(2, ((INT, INT), (ARRAY, ARRAY), (ANY, ARRAY)))
-def run_INT_INT(stack, a, b):
-    return [GObject(b.value - a.value, INT)]
-Minus.run_INT_INT = run_INT_INT
-def run_ARRAY_ARRAY(stack, a, b):
-    for item in a.value:
-        while item in b.value:
-            b.value.remove(item)
-    return [b]
-Minus.run_ARRAY_ARRAY = run_ARRAY_ARRAY
-def run_ANY_ARRAY(stack, a, b):
-    while a.value in b.value:
-        b.value.remove(a.value)
-    return [b]
-Minus.run_ANY_ARRAY = run_ANY_ARRAY
-vars['-'] = Minus
-del Minus, run_INT_INT, run_ARRAY_ARRAY, run_ANY_ARRAY
-#------------------------------------------------------------------------------
-
-Star = GFunc(2, ((INT, INT), (INT, BLOCK), (INT, ARRAY),
-                 (INT, STR), (ARRAY, INT), (STR, INT),
-                 (STR, ARRAY), (ARRAY, ARRAY), (STR, STR),
-                 (BLOCK, ARRAY), (BLOCK, STR)))
-def run_INT_INT(stack, a, b):
-    return [GObject(a.value * b.value, INT)]
-Star.run_INT_INT = run_INT_INT
-def run_INT_BLOCK(stack, a, b):
-    for _ in xrange(a.value):
-        stack.eval(' '.join(b.value), stack)
-    return []
-Star.run_INT_BLOCK = run_INT_BLOCK
-def run_INT_iterable(stack, a, b):
-    b.value *= a.value
-    return [b]
-Star.run_INT_ARRAY = run_INT_iterable
-Star.run_INT_STR = run_INT_iterable
-def run_iterable_INT(stack, a, b):
-    a.value *= b.value
-    return [a]
-Star.run_ARRAY_INT = run_iterable_INT
-Star.run_STR_INT = run_iterable_INT
-def run_ARRAY_ARRAY(stack, a, b):
-    result = []
-    for item in b.value:
-        result.append(item)
-        result.extend(a.value)
-    return [GObject(result[:-len(a.value)], ARRAY)]
-Star.run_ARRAY_ARRAY = run_ARRAY_ARRAY
-def run_STR_STR(stack, a, b):
-    return [GObject(a.value.join(b.value), STR)]
-Star.run_STR_STR = run_STR_STR
-def run_BLOCK_ARRAY(stack, a, b):
-    b.value.reverse()
-    s = Stack()
-    for item in b.value:
-        s.push(item)
-    while s.size() > 1:
-        stack.eval(' '.join(a.value), s)
-    result = []
-    while s.size():
-        result.append(s.pop())
-    return result
-Star.run_BLOCK_ARRAY = run_BLOCK_ARRAY
-def run_BLOCK_STR(stack, a, b):
-    s = Stack()
-    for item in reversed(b.value):
-        s.push(ord(item), INT)
-    while s.size() > 1:
-        stack.eval(' '.join(a.value), s)
-    result = []
-    while s.size():
-        result.append(s.pop())
-    return result
-Star.run_BLOCK_STR = run_BLOCK_STR
-def run_STR_ARRAY(stack, a, b):
-    return [GObject(a.value.join(str(x) for x in b.value), STR)]
-Star.run_STR_ARRAY = run_STR_ARRAY
-vars['*'] = Star
-del Star, run_INT_INT, run_INT_BLOCK, run_INT_iterable, run_iterable_INT, \
-    run_ARRAY_ARRAY, run_STR_STR, run_BLOCK_ARRAY, run_BLOCK_STR, run_STR_ARRAY
-
-#------------------------------------------------------------------------------
-
-Slash = GFunc(2, ((INT, INT), (ARRAY, ARRAY), (STR, STR),
-                  (INT, ARRAY), (BLOCK, BLOCK), (BLOCK, ARRAY)))
-def run_INT_INT(stack, a, b):
-    return [GObject(b.value/a.value, INT)]
-Slash.run_INT_INT = run_INT_INT
-def run_ARRAY_ARRAY(stack, a, b):
-    result = GObject([], ARRAY)
-    sub_length = len(a.value)
-    good_nodes = []
-    i = 0
-    while i < len(b.value):
-        if b.value[i:i+sub_length] == a.value:
-            result.value.append(GObject(
-                [b.value[x] for x in good_nodes],
-                ARRAY))
-            i += sub_length-1
-            good_nodes = []
-        else:
-            good_nodes.append(i)
-        i += 1
-    if good_nodes:
-        result.value.append(GObject(
-            [b.value[x] for x in good_nodes],
-            ARRAY))
-    return [result]
-Slash.run_ARRAY_ARRAY = run_ARRAY_ARRAY
-def run_STR_STR(stack, a, b):
-    s = [GObject(x, STR) for x in b.value.split(a.value)]
-    return [GObject(s, ARRAY)]
-Slash.run_STR_STR = run_STR_STR
-def run_INT_ARRAY(stack, a, b):
-    result = GObject([], ARRAY)
-    c = 0
-    sub = None
-    while len(b.value):
-        if c == 0:
-            if sub is not None:
-                result.value.append(sub)
-            sub = GObject([], ARRAY)
-        sub.value.append(b.value.pop(0))
-        c = (c+1) % a.value
-    if len(sub.value):
-        result.value.append(sub)
-    return [result]
-Slash.run_INT_ARRAY = run_INT_ARRAY
-def run_BLOCK_BLOCK(stack, a, b):
-    # This is a "collect while" loop, that spits out it's ultimate result
-    # as well as collecting all the intermediaries in an array.
-    bucket = GObject([], ARRAY)
-    while True:
-        stack.push(stack.peek()) # Duplicate
-        stack.eval(b.value, stack)
-        if stack.pop().value:
-            bucket.value.append(stack.peek())
-        else:
-            stack.pop()
-            break
-        stack.eval(a.value, stack)
-    return [stack.pop(), bucket]
-Slash.run_BLOCK_BLOCK = run_BLOCK_BLOCK
-def run_BLOCK_ARRAY(stack, a, b):
-    result = []
-    for item in b.value:
-        s = Stack()
-        s.push(item)
-        s.eval(a.value, s)
-        while s.size():
-            result.append(s.pop())
-    return result
-Slash.run_BLOCK_ARRAY = run_BLOCK_ARRAY
-vars['/'] = Slash
-del Slash, run_INT_INT, run_ARRAY_ARRAY, run_STR_STR, run_INT_ARRAY, \
-    run_BLOCK_BLOCK, run_BLOCK_ARRAY
-
-
-#------------------------------------------------------------------------------
-
-Mod = GFunc(2, ((INT, INT), (STR, STR), (ARRAY, ARRAY), (INT, ARRAY), (BLOCK, ARRAY)))
-def run_INT_INT(stack, a, b):
-    return [GObject(b.value % a.value, INT)]
-Mod.run_INT_INT = run_INT_INT
-def run_STR_STR(stack, a, b):
-    result = b.value.split(a.value)
-    return [GObject(
-        [GObject(x, STR) for x in result if x], ARRAY)]
-Mod.run_STR_STR = run_STR_STR
-def run_ARRAY_ARRAY(stack, a, b):
-    pass
-Mod.run_ARRAY_ARRAY = run_ARRAY_ARRAY
-def run_INT_ARRAY(stack, a, b):
-    b.value = b.value[::a.value]
-    return [b]
-Mod.run_INT_ARRAY = run_INT_ARRAY
-def run_BLOCK_ARRAY(stack, a, b):
-    result = GObject([], ARRAY)
-    for item in b.value:
-        s = Stack()
-        s.push(item)
-        stack.eval(a.value, s)
-        while s.size():
-            result.value.append(s.pop())
-    return [result]
-Mod.run_BLOCK_ARRAY = run_BLOCK_ARRAY
-vars['%'] = Mod
-del Mod, run_INT_INT, run_STR_STR, run_ARRAY_ARRAY, run_INT_ARRAY, run_BLOCK_ARRAY
-
-#------------------------------------------------------------------------------
-
-Bar = GFunc(2, ((INT, INT), (ARRAY, ARRAY)))
-def run_INT_INT(stack, a, b):
-    return [GObject(a.value | b.value, INT)]
-Bar.run_INT_INT = run_INT_INT
-def run_ARRAY_ARRAY(stack, a, b):
-    for item in b.value:
-        if item not in a.value:
-            a.value.append(item)
-    a.value.sort(key=lambda x: x.value)
-    return [a]
-Bar.run_ARRAY_ARRAY = run_ARRAY_ARRAY
-vars['|'] = Bar
-del Bar, run_INT_INT, run_ARRAY_ARRAY
-
-#------------------------------------------------------------------------------
-
-Ampersand = GFunc(2, ((INT, INT), (ARRAY, ARRAY)))
-def run_INT_INT(stack, a, b):
-    return [GObject(a.value & b.value, INT)]
-Ampersand.run_INT_INT = run_INT_INT
-def run_ARRAY_ARRAY(stack, a, b):
-    both = GObject([], ARRAY)
-    for item in a.value:
-        if item in b.value:
-            both.value.append(item)
-    return [both]
-Ampersand.run_ARRAY_ARRAY = run_ARRAY_ARRAY
-vars['&'] = Ampersand
-del Ampersand, run_INT_INT, run_ARRAY_ARRAY
-
-#------------------------------------------------------------------------------
-
-Caret = GFunc(2, ((INT, INT), (ARRAY, ARRAY)))
-def run_INT_INT(stack, a, b):
-    return [GObject(a.value ^ b.value, INT)]
-Caret.run_INT_INT = run_INT_INT
-def run_ARRAY_ARRAY(stack, a, b):
-    union = []
-    for item in a.value:
-        union.append(item)
-    for item in b.value:
-        union.append(item)
-    difference = []
-    for item in union:
-        if not (item in a.value and item in b.value) and item not in difference:
-            difference.append(item)
-    difference.sort(key=lambda x: x.value)
-    return [GObject(difference, ARRAY)]
-Caret.run_ARRAY_ARRAY = run_ARRAY_ARRAY
-vars['^'] = Caret
-del Caret, run_INT_INT, run_ARRAY_ARRAY
-
-#------------------------------------------------------------------------------
-
-Backslash = GFunc(2, ((ANY, ANY),))
-def run_ANY_ANY(stack, a, b):
-    return [a, b]
-Backslash.run_ANY_ANY = run_ANY_ANY
-vars['\\'] = Backslash
-del Backslash, run_ANY_ANY
-
-#------------------------------------------------------------------------------
-
-Semicolon = GFunc(1, ((ANY,),))
-def run_ANY(stack, a):
-    return []
-Semicolon.run_ANY = run_ANY
-vars[';'] = Semicolon
-del Semicolon, run_ANY
-
-#------------------------------------------------------------------------------
-
-#------------------------------------------------------------------------------
-
-LessThan = GFunc(2, ((INT, INT), (STR, STR), (ARRAY, ARRAY), (BLOCK, BLOCK),
-                     (INT, STR), (INT, ARRAY), (INT, BLOCK)))
-def run_same(stack, a, b):
-    return [GObject(int(b.value < a.value), INT)]
-LessThan.run_INT_INT = run_same
-LessThan.run_STR_STR = run_same
-LessThan.run_ARRAY_ARRAY = run_same
-LessThan.run_BLOCK_BLOCK = run_same
-def run_INT_iterable(stack, a, b):
-    b.value = b.value[:a.value:]
-    return [b]
-LessThan.run_INT_STR = run_INT_iterable
-LessThan.run_INT_ARRAY = run_INT_iterable
-LessThan.run_INT_BLOCK = run_INT_iterable
-vars['<'] = LessThan
-del LessThan, run_same, run_INT_iterable
-
-#------------------------------------------------------------------------------
-
-GreaterThan = GFunc(2, ((INT, INT), (STR, STR), (ARRAY, ARRAY), (BLOCK, BLOCK),
-                     (INT, STR), (INT, ARRAY), (INT, BLOCK)))
-def run_same(stack, a, b):
-    return [GObject(int(b.value > a.value), INT)]
-GreaterThan.run_INT_INT = run_same
-GreaterThan.run_STR_STR = run_same
-GreaterThan.run_ARRAY_ARRAY = run_same
-GreaterThan.run_BLOCK_BLOCK = run_same
-def run_INT_iterable(stack, a, b):
-    b.value = b.value[a.value::]
-    return [b]
-GreaterThan.run_INT_STR = run_INT_iterable
-GreaterThan.run_INT_ARRAY = run_INT_iterable
-GreaterThan.run_INT_BLOCK = run_INT_iterable
-vars['>'] = GreaterThan
-del GreaterThan, run_same, run_INT_iterable
-
-#------------------------------------------------------------------------------
-
-Equals = GFunc(2, ((INT, INT), (STR, STR), (ARRAY, ARRAY), (BLOCK, BLOCK),
-                     (INT, STR), (INT, ARRAY), (INT, BLOCK)))
-def run_same(stack, a, b):
-    return [GObject(int(b.value == a.value), INT)]
-Equals.run_INT_INT = run_same
-Equals.run_STR_STR = run_same
-Equals.run_ARRAY_ARRAY = run_same
-Equals.run_BLOCK_BLOCK = run_same
-def run_INT_ARRAY(stack, a, b):
-    return [b.value[a.value]]
-def run_INT_STR(stack, a, b):
-    return [GObject(ord(b.value[a.value]), INT)]
-Equals.run_INT_ARRAY = run_INT_ARRAY
-Equals.run_INT_STR = run_INT_STR
-Equals.run_INT_BLOCK = run_INT_STR
-vars['='] = Equals
-del Equals, run_same, run_INT_ARRAY, run_INT_STR
-
-#------------------------------------------------------------------------------
-
-Comma = GFunc((1, 2), ((INT,), (ARRAY,), (BLOCK, ARRAY)))
-def run_INT(stack, a):
-    return [GObject(
-        [GObject(x, INT) for x in xrange(a.value)],
-        ARRAY)]
-Comma.run_INT = run_INT
-def run_ARRAY(stack, a):
-    return [GObject(len(a.value), INT)]
-Comma.run_ARRAY = run_ARRAY
-def run_BLOCK_ARRAY(stack, a, b):
-    trues = []
-    for item in b.value:
-        stack.push(item)
-        stack.eval(a.value, stack)
-        if stack.pop().value:
-            trues.append(item)
-    return [GObject(trues, ARRAY)]
-Comma.run_BLOCK_ARRAY = run_BLOCK_ARRAY
-vars[','] = Comma
-del Comma, run_INT, run_ARRAY, run_BLOCK_ARRAY
-
-#------------------------------------------------------------------------------
-
-Dot = GFunc(1, ((ANY,),))
-def run_ANY(stack, a):
-    return [a, a]
-Dot.run_ANY = run_ANY
-vars['.'] = Dot
-del Dot, run_ANY
-
-#------------------------------------------------------------------------------
-
-Question = GFunc(2, ((INT, INT), (ARRAY, INT), (INT, ARRAY), (BLOCK, ARRAY)))
-def run_INT_INT(stack, a, b):
-    return [GObject(b.value ** a.value, INT)]
-Question.run_INT_INT = run_INT_INT
-def run_ARRAY_INT(stack, a, b):
-    position = -1
-    for i, item in enumerate(a.value):
-        if item == b:
-            position = i
-            break
-    return [GObject(position, INT)]
-Question.run_ARRAY_INT = run_ARRAY_INT
-def run_INT_ARRAY(stack, a, b):
-    return run_ARRAY_INT(stack, b, a)
-Question.run_INT_ARRAY = run_INT_ARRAY
-def run_BLOCK_ARRAY(stack, a, b):
-    for item in b.value:
-        stack.push(item)
-        stack.eval(a.value, stack)
-        if stack.pop().value:
-            return [item]
-Question.run_BLOCK_ARRAY = run_BLOCK_ARRAY
-vars['?'] = Question
-del Question, run_INT_INT, run_ARRAY_INT, run_INT_ARRAY
-
-#------------------------------------------------------------------------------
-
-OpenParen = GFunc(1, ((INT,), (ARRAY,)))
-def run_INT(stack, a):
-    a.value -= 1
-    return [a]
-OpenParen.run_INT = run_INT
-def run_ARRAY(stack, a):
-    value = a.value.pop(0)
-    return [a, value]
-OpenParen.run_ARRAY = run_ARRAY
-vars['('] = OpenParen
-del OpenParen, run_INT, run_ARRAY
-
-#------------------------------------------------------------------------------
-
-CloseParen = GFunc(1, ((INT,), (ARRAY,)))
-def run_INT(stack, a):
-    a.value += 1
-    return [a]
-CloseParen.run_INT = run_INT
-def run_ARRAY(stack, a):
-    value = a.value.pop()
-    return [a, value]
-CloseParen.run_ARRAY = run_ARRAY
-vars[')'] = CloseParen
-del CloseParen, run_INT, run_ARRAY
-
-#------------------------------------------------------------------------------
-
-#------------------------------------------------------------------------------
-
-#------------------------------------------------------------------------------
-
-If = GFunc(3, ((ANY, ANY, ANY),))
-def run(stack, a, b, c):
-    if c.type is BLOCK:
-        stack.eval(c.value, stack)
-        result = stack.pop()
-    else:
-        result = c
-    
-    if result.value:
-        if b.type is BLOCK:
-            stack.eval(b.value, stack)
-            return []
-        else:
-            return [b]
-    else:
-        if a.type is BLOCK:
-            stack.eval(a.value, stack)
-            return []
-        else:
-            return [a]
-If.run_ANY_ANY_ANY = run
-vars['if'] = If
-del If, run
-
-#------------------------------------------------------------------------------
-
-And = GFunc(0, ())
-def run(stack):
-    stack.eval('1$if', stack)
-    return []
-And.run = run
-vars['and'] = And
-del And, run
-
-#------------------------------------------------------------------------------
-
-Or = GFunc(0, ())
-def run(stack):
-    stack.eval(r'1$\if', stack)
-    return []
-Or.run = run
-vars['or'] = Or
-del Or, run
-
-#------------------------------------------------------------------------------
-
-XOr = GFunc(1, ((ANY, ANY),))
-def run(stack, a, b):
-    stack.push(b)
-    stack.push(a)
-    stack.eval(r'\!!{!}*', stack)
-XOr.run = run
-vars['xor'] = XOr
-del XOr, run
-
-#------------------------------------------------------------------------------
-
-
-#------------------------------------------------------------------------------
-
-
-__all__ = ('vars',)
+@builtin('~', 1, Number)
+def Tilde(stack, vars):
+    a = stack.pop(Number)
+    result = ~ a.unbox()
+    print >>stderr, 'before = %i, after = %i' % (a.unbox(), result)
+    stack.push(Box(result, Number))
+@builtin('~', 1, String)
+def Tilde(stack, vars):
+    a = stack.pop(Number)
+    stack.eval(a.unbox(), stack, vars)
 #!/usr/bin/env python
 
+from copy import deepcopy
 import re
 import os, sys
 import traceback
 
-from gtypes import *
+import gtypes
 import default_vars
-vars = {}
 
 def parse(program):
     tokenizer = re.compile(
 
 eval_depth = 0
 
-def eval(program, stack=None):
+def eval(program, stack=None, vars=None):
     global eval_depth
     print '  '*eval_depth + 'Entering eval loop'
     eval_depth += 1
-    global vars
+    if vars is None:
+        vars = gtypes.FallthroughDict(parent=gtypes.vars)
+    else:
+        vars = gtypes.FallthroughDict(parent=vars)
     if stack is None:
-        stack = Stack()
+        stack = gtypes.Stack()
         stack.clear()
-        reload(default_vars)
-        vars = default_vars.vars
     print '  '*eval_depth + 'program=%r, stack=%r, vars=%s' % (program, stack, vars.keys())
     tokens, block_map = parse(program)
     array_stack = []
     while True:
         token = tokens[pc]
         if token != ' ':
-            print '  '*eval_depth + 'token=%r, stack=%s, pc=%r' % (token, stack, pc)
-        
+            print '  '*eval_depth + 'token=%r, stack=%s, vars=%s, pc=%r' % (token, stack, vars.keys(), pc)
         # Variables
         if token == ':':
             print 'assigning %r to var %r' % (stack.peek(), tokens[pc+1])
             vars[tokens[pc+1]] = stack.peek()
             pc += 1
         elif token in vars:
-            if isinstance(vars[token], GFunc):
-                result = vars[token](stack)
-                if not isinstance(result, list):
-                    result = [result]
-                for item in result:
-                    assert isinstance(item, GObject), 'functions must return a'\
-                        ' list of "GObject"s, not "%s"s' % \
-                            item.__class__.__name__
-                    stack.push(item)
-            else:
-                stack.push(vars[token])
+            vars[token].run(stack, vars)
         # Literals
+        elif token.replace('-','').isdigit():
+            stack.push(int(token), gtypes.Number)
+        
+        elif token.startswith('"') and token.endswith('"'):
+            stack.push(token[1:-1], gtypes.String)
+        
+        elif token.startswith("'") and token.endswith("'"):
+            stack.push(token[1:-1], gtypes.String)
         elif token == '{': # Start block
             ts = []
             start = pc
             while pc < end:
                 ts.append(tokens[pc])
                 pc += 1
-            stack.push(''.join(ts[1:]), BLOCK)
+            stack.push(''.join(ts[1:]), gtypes.Block)
         elif token == '}':
             pass
+        # According to the official docs, these are actually variables.
+        # When I get around to making them variables, then this section will be
+        # superseded by the variable matching branch above.
         elif token == '[':
             array_stack.append(len(stack))
         elif token == ']':
             while len(stack) != old_size:
                 new_array.append(stack.pop())
             new_array.reverse()
-            stack.push(new_array, ARRAY)
-        elif token.replace('-','').isdigit():
-            stack.push(int(token), INT)
-        
-        elif token.startswith('"') and token.endswith('"'):
-            stack.push(token[1:-1], STR)
-        
-        elif token.startswith("'") and token.endswith("'"):
-            stack.push(token[1:-1], STR)
+            stack.push(new_array, gtypes.Array)
+        else:
+            print >>sys.stderr, "undefined token %r" % token
+            # Nothing else really needs to be done. The token is already popped,
+            # so we just ignore it.
         
         pc += 1
         if pc >= len(tokens):
     print '  '*eval_depth + 'Exiting eval loop'
     return stack
 
-Stack.eval = staticmethod(eval)
+gtypes.Stack.eval = staticmethod(eval)
 
 def mainloop(program):
     global vars
+from collections import defaultdict
+
+class FallthroughDict(dict):
+    '''This is like how Django does contexts in templates.
+       The scoping is dynamic.'''
+    def __init__(self, parent={}, *args, **kwargs):
+        super(FallthroughDict, self).__init__(*args, **kwargs)
+        self.parent = parent
+    def __missing__(self, key):
+        return self.parent[key]
+    def __contains__(self, key):
+        return super(FallthroughDict, self).__contains__(key) or key in self.parent
+    def keys(self):
+        return list(set(super(FallthroughDict, self).keys()) | set(self.parent.keys()))
+
 class Box(object):
     def __init__(self, value, type):
-        assert type in Type.s
+        assert type in types
         self.value = value
         self.type = type
     def unbox(self):
         return self.value
+    def __str__(self):
+        return str(self.value)
 
 
 types = []
     @classmethod
     def null(cls):
         raise NotImplementedError
+    def run(self, stack, vars):
+        return self
 
 class Any(Type):
     @classmethod
     def null(cls):
         return Box([], Array)
 Array()
+class String(Type):
+    def null(cls):
+        return Box("", String)
+String()
+class Block(Type):
+    def null(cls):
+        return Box("", Block)
+Block()
 
 
+vars = FallthroughDict()
+
+class Builtin(Type):
+    def __init__(self, type='native'):
+        self.is_native = type == 'native'
+        self.funcs = (
+            defaultdict(dict),
+            defaultdict(dict),
+            defaultdict(dict),
+            defaultdict(dict),
+        )
+    def add_func(self, function, arg_count, arg_types):
+        # function is a native function that takes the arg_count args of type arg_types
+        assert arg_count < len(self.funcs), 'Why does your function need so many args!'
+        for tuple in arg_types:
+            self.funcs[arg_count][tuple] = function
+    def run(self, stack, vars):
+        print self.funcs
+        for arg_count in xrange(len(self.funcs)):
+            args = [stack.peek(i+1) for i in xrange(arg_count)]
+            arg_types = [arg.type for arg in args]
+            print 'arg_count = %i, args = %s' % (arg_count, args)
+            for requested_args, func in self.funcs[arg_count].iteritems():
+                print 'requested_args = %s, arg_types = %s' % (requested_args, arg_types)
+                if not isinstance(requested_args, (list, tuple)):
+                    requested_args = [requested_args]
+                if requested_args == arg_types:
+                    return func(stack, vars)
+        raise AttributeError("No matching functions found.")
+Builtin()
+
+def builtin(var, arg_count, *arg_types):
+    if arg_count == 'block':
+        type = 'block'
+    else:
+        type = 'native'
+
+    if var not in vars:
+        vars[var] = Builtin(type)
+
+    def middle(func):
+        vars[var].add_func(func, arg_count, arg_types)
+        return None
+
+    return middle
+
 class Stack(object):
     stack = []
     def clear(self):
         self.stack = []
     def push(self, value, type=None):
         if isinstance(value, Box):
-            #print '    Pushing object with value %r and type %s' % (value.value, value.type)
             self.stack.append(value)
         else:
-            #print '    Pushing object with value %r and type %s' % (value, type)
             self.stack.append(Box(value, type))
     append = push
-    def pop(self):
+    def pop(self, type=Any):
         if self.size() == 0:
-            return Any.null()
+            return type.null()
         return self.stack.pop()
-    def peek(self):
+    def peek(self, depth=1):
         return self.stack[-1]
     def size(self):
         return len(self.stack)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.