Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit 42ac1d3167e8db1618907fb9dc9a0a21b6e04ddb 0 parents
Cameron Paul authored
1  .gitignore
@@ -0,0 +1 @@
+*.pyc
4 README.md
@@ -0,0 +1,4 @@
+# nali
+
+**nali** is a programming language I created for fun. It is largely unfinished,
+unstable, and unusable for any real tasks. It is a toy and nothing more.
0  __init__.py
No changes.
4 __main__.py
@@ -0,0 +1,4 @@
+#!/usr/bin/python
+import interpreter
+
+interpreter.repl()
107 interpreter.py
@@ -0,0 +1,107 @@
+from lang import *
+
+class Interpreter(object):
+
+ def __init__(self):
+ self.namespace = dict(stdlib.items())
+ self.namespace['def'] = Namespace(self.namespace)
+
+ def nali_eval(self, tokens, namespace):
+ expression = []
+
+ while len(tokens) > 0:
+ token = tokens.pop(0)
+ if token == '(':
+ expression.append(self.nali_eval(tokens, namespace))
+ elif token == ')':
+ break
+ elif token[0] == "[":
+ expression.append(parse_function(tokens, namespace))
+ elif token[0] == "\"":
+ expression.append(token[1:len(token) - 1])
+ elif token[0] == ":":
+ expression.append(Symbol(token))
+ elif token[0] == ".":
+ expression.append(Message(token))
+ elif token.isdigit():
+ expression.append(Number(int(token)))
+ else:
+ expression.append(namespace[token])
+
+ return self.nali_exec(expression)
+
+ def nali_exec(self, expression):
+
+ for i in range(len(expression)):
+ if isinstance(expression[i], list):
+ expression[i] = self.nali_execute(expression[i])
+
+ if len(expression) == 1 and expression[0].arg_count() > 0:
+ return expression[0]
+
+ obj = expression[0]
+ arg = expression[1:]
+
+ if(len(arg) == 0):
+ obj = obj.execute(None)
+
+ while len(arg) > 0:
+ arg_count = obj.arg_count()
+ obj = obj.execute(arg[:arg_count])
+ arg = arg[arg_count:]
+
+ return obj
+
+def tokenize(expression):
+ tokens = ['(',')','[',']','|','+','-',';']
+ prefixes = ['.',':']
+
+ for token in tokens:
+ expression = expression.replace(token, token.join([' ',' ']))
+
+ for prefix in prefixes:
+ expression = expression.replace(prefix, prefix.join([' ','']))
+
+ return expression.split()
+
+def parse_function(tokens, namespace):
+ prototype = []
+ expressions = []
+ expression = []
+ expressions.append(expression)
+
+ if(tokens[0] == '|'):
+ tokens.pop(0)
+ while not tokens[0] == '|':
+ prototype.append(tokens.pop(0))
+ tokens.pop(0)
+
+ count = 1
+
+ while count > 0:
+ token = tokens.pop(0)
+ if token == '[':
+ count = count + 1
+ if token == ']':
+ count = count - 1
+ if token == ';':
+ expression = []
+ expressions.append(expression)
+ else:
+ expression.append(token)
+
+ expression.pop()
+
+ return Function(namespace, prototype, expressions, self.nali_eval)
+
+def parse_string(tokens):
+ pass
+
+def repl():
+ i = Interpreter()
+
+ while(True):
+ try:
+ print i.nali_eval(tokenize(raw_input('>> ')), i.namespace)
+ except Exception, e:
+ print e.__class__.__name__ + ": " + e.message
207 lang.py
@@ -0,0 +1,207 @@
+import copy
+
+class Object(object):
+
+ def __init__(self):
+ self.namespace = {}
+
+ def execute(self, args):
+ if type(args[0]) == Symbol:
+ return Setter(self, str(args[0]))
+ elif isinstance(self.namespace[str(args[0])], Function):
+ return Caller(self, self.namespace[str(args[0])])
+ else:
+ return self.namespace[str(args[0])]
+
+ def arg_count(self):
+ return 1
+
+ def __str__(self):
+ return '[object]'
+
+class Function(Object):
+
+ def __init__(self, namespace, prototype, expressions, eval_func):
+ self.namespace = namespace
+ self.prototype = prototype
+ self.expressions = expressions
+ self.eval_func = eval_func
+
+ def execute(self, args):
+ if args:
+ namespace = dict(self.namespace.items() + dict(zip(self.prototype, args)).items())
+ else:
+ namespace = dict(self.namespace.items())
+ namespace['def'] = Namespace(namespace)
+ for expression in self.expressions:
+ result = self.eval_func(expression[:], namespace)
+ return result
+
+ def arg_count(self):
+ return len(self.prototype)
+
+ def __str__(self):
+ return "[function]"
+
+class Namespace(Object):
+ def __init__(self, namespace):
+ self.namespace = namespace
+
+class Message(Object):
+ def __init__(self, value):
+ self.value = value
+
+ def __str__(self):
+ return self.value[1:]
+
+class Symbol(Object):
+ def __init__(self, value):
+ super(Symbol, self).__init__()
+ self.value = value
+
+ def __str__(self):
+ return self.value[1:]
+
+class Setter(Object):
+ def __init__(self, target, name):
+ self.target = target
+ self.name = name
+
+ def execute(self, args):
+ self.target.namespace[self.name] = args[0]
+ return args[0]
+
+class Caller(Object):
+ def __init__(self, caller, function):
+ self.caller = caller
+ self.function = function
+
+ def execute(self, args):
+ if not args:
+ args = []
+ return self.function.execute([self.caller] + args)
+
+ def arg_count(self):
+ return self.function.arg_count() - 1
+
+class Print(Function):
+
+ def __init__(self):
+ pass
+
+ def execute(self, args):
+ print args[0]
+ return Object()
+
+ def arg_count(self):
+ return 1
+
+class Exit(Function):
+
+ def __init__(self):
+ pass
+
+ def execute(self, args):
+ exit()
+
+ def arg_count(self):
+ return 0
+
+class Add(Function):
+
+ def __init__(self):
+ pass
+
+ def execute(self, args):
+ return Number(args[0].val() + args[1].val())
+
+ def arg_count(self):
+ return 2
+
+class Subtract(Function):
+
+ def __init__(self):
+ pass
+
+ def execute(self, args):
+ return Number(args[0].val() - args[1].val())
+
+ def arg_count(self):
+ return 2
+
+class Multiply(Function):
+
+ def __init__(self):
+ pass
+
+ def execute(self, args):
+ return Number(args[0].val() * args[1].val())
+
+ def arg_count(self):
+ return 2
+
+class Divide(Function):
+
+ def __init__(self):
+ pass
+
+ def execute(self, args):
+ return Number(args[0].val() / args[1].val())
+
+ def arg_count(self):
+ return 2
+
+class Mod(Function):
+
+ def __init__(self):
+ pass
+
+ def execute(self, args):
+ return Number(args[0].val() % args[1].val())
+
+ def arg_count(self):
+ return 2
+
+class New(Function):
+
+ def __init__(self):
+ pass
+
+ def execute(self, args):
+ return copy.deepcopy(args[0])
+
+ def arg_count(self):
+ return 1
+
+class Number(Object):
+
+ def __init__(self, value):
+ super(Number, self).__init__()
+ self.value = value
+ self.namespace["add"] = stdlib['add']
+ self.namespace["sub"] = stdlib['sub']
+ self.namespace["mul"] = stdlib['mul']
+ self.namespace["div"] = stdlib['div']
+ self.namespace["mod"] = stdlib['mod']
+
+ def val(self):
+ return self.value
+
+ def __str__(self):
+ return str(self.value)
+
+stdlib = {
+ 'object': Object(),
+ 'new': New(),
+ 'add': Add(),
+ 'sub': Subtract(),
+ 'mul': Multiply(),
+ 'div': Divide(),
+ 'mod': Mod(),
+ 'exit': Exit(),
+ '+': Message('.add'),
+ '-': Message('.sub'),
+ '*': Message('.mul'),
+ '/': Message('.div'),
+ '%': Message('.mod')
+}
Please sign in to comment.
Something went wrong with that request. Please try again.