From caf91bc0a8b793bf30446fa7dcfdaa17315e5ce7 Mon Sep 17 00:00:00 2001 From: cecilkorik Date: Tue, 23 Apr 2019 17:34:40 -0700 Subject: [PATCH] parser and virtualmachine seem to be functional again in python 3 --HG-- branch : mung --- bi.py | 2 +- bytecode.py | 1486 ++++++++++++++++++++++----------------------- database.py | 4 +- ebnf.py | 298 ++++----- errors.py | 182 +++--- language_tools.py | 150 ++--- language_types.py | 444 +++++++------- optimizer.py | 4 +- pbkdf2.py | 268 ++++---- pyenum.py | 32 +- virtualmachine.py | 6 +- 11 files changed, 1438 insertions(+), 1438 deletions(-) diff --git a/bi.py b/bi.py index cd5f5b5..d6c4618 100755 --- a/bi.py +++ b/bi.py @@ -102,7 +102,7 @@ builtin_map.update({ """ builtin_map.update({ - 'serverlog': bi.serverlog, + b'serverlog': bi.serverlog, }) """ diff --git a/bytecode.py b/bytecode.py index 9a68b72..3c5e506 100644 --- a/bytecode.py +++ b/bytecode.py @@ -1,743 +1,743 @@ -from language_tools import * -from bi import builtin_map -import optimizer - - - - -def coerce(value): - from language_types import VMInteger, VMList, VMString, VMTable, VMObjRef, VMFloat, VMType - if isinstance(value, int): - return VMInteger(value) - elif isinstance(value, (tuple, list)): - return VMList(list(value)) - elif isinstance(value, str): - return VMString(value) - elif isinstance(value, dict): - return VMTable(value) - elif isinstance(value, ObjRef): - return VMObjRef(value) - elif isinstance(value, float): - return VMFloat(value) - elif value == None: - return VMInteger(0) - elif isinstance(value, VMType): - return value - else: - raise TypeError("Unknown type %s cannot be coerced to VMType" % (type(value),)) - - -def uncoerce(value): - from language_types import VMType - assert isinstance(value, VMType) - return value.value - - -def codejoin(*args): - rv = [] - for arg in args: - if isinstance(arg, CodeOpSequence): - for subarg in arg.sequence: - rv.extend(codejoin(subarg)) - elif isinstance(arg, list): - for subarg in arg: - rv.extend(codejoin(subarg)) - else: - rv.append(arg) - - return rv - seq = CodeOpSequence.new(rv) - return seq - #return flatten(rv, ltypes=(list,)) - - -class CodeOp(VMBaseObject): - def load_stack(self, vm): - pass - - def ticks(self): - return 1 - -class CodeOpSequence(CodeOp): - - @staticmethod - def new(input): - c = CodeOpSequence() - c.sequence = input - return c - - def load_stack(self, vm): - pass - - def ticks(self): - return 0 - - -class StackCodeOp(CodeOp): - def __init__(self, stack_value): - CodeOp.__init__(self) - self.stack_value = stack_value - - def load_stack(self, vm): - vm.push(self.stack_value) - - -class NoOp(CodeOp): - def execute(self, vm): - pass - - def ticks(self): - return 0 - - @staticmethod - @tokenparser - def parse(tokens): - return [] - - -class GetProperty(CodeOp): - def execute(self, vm): - obj, prop = vm.pop(2) - objstore = vm.db.get_obj(obj) - val = objstore.get_prop(prop) - vm.push(val) - - @staticmethod - @tokenparser - def parse(tokens): - return codejoin(GetProperty()) - -class SetProperty(CodeOp): - def execute(self, vm): - val, prop, obj = vm.pop(3) - vm.db.set_property(obj, prop, val) - vm.push(val) - - @staticmethod - @tokenparser - def parse(tokens): - return codejoin(StackLiteral(tokens[0])) - -class GetFile(CodeOp): - def execute(self, vm): - obj, prop = vm.pop(2) - objstore = vm.db.get_obj(obj) - val = objstore.get_file(prop) - vm.push(val) - -class SetFile(CodeOp): - def execute(self, vm): - val, prop, obj = vm.pop(3) - vm.db.set_file(obj, prop, val) - vm.push(val) - -class SetVariable(CodeOp): - def execute(self, vm): - val, varname = vm.pop(2) - vm.setvar(varname, val) - vm.push(val) - - @staticmethod - @tokenparser - def parse(tokens): - assert isinstance(tokens[0], GetVariable) - return codejoin(SetVariable(tokens[0].stack_value)) - - -class GetVariable(CodeOp): - def execute(self, vm): - varname, = vm.pop(1) - vm.push(vm.getvar(varname)) - - @staticmethod - @tokenparser - def parse(tokens): - return codejoin(tokens[0], GetVariable()) - -class CallBuiltin(CodeOp): - def execute(self, vm): - funcname, args = vm.pop(2) - funcname = funcname.encode('ascii', 'ignore') - retval = builtin_map[funcname](vm, args) - vm.push(retval) - - @staticmethod - @tokenparser - def parse(tokens): - #if not tokens[0] in builtin_map: - # raise ParseException('Attempt to call undefined builtin function: "%s"' % (tokens[0],)) - return codejoin(tokens[0], tokens[1], CallBuiltin()) - -class CallFunction(CodeOp): - def execute(self, vm): - obj, name = vm.pop(2) - vm.code_push(codejoin(StartContext(), vm.get_code(obj, name), EndContext())) - - @staticmethod - @tokenparser - def parse(tokens): - return codejoin(tokens[0], CallFunction()) - -class ArithAdd(CodeOp): - def execute(self, vm): - v1, v2 = vm.pop(2) - vm.push(v1+v2) - - @staticmethod - @tokenparser - def parse(tokens): - if tokens[0] == "+": - return codejoin(tokens[1], ArithAdd()) - else: - return codejoin(tokens[1], ArithSub()) - -class ArithSub(CodeOp): - def execute(self, vm): - v1, v2 = vm.pop(2) - vm.push(v1-v2) - - -class ArithMul(CodeOp): - def execute(self, vm): - v1, v2 = vm.pop(2) - vm.push(v1*v2) - - @staticmethod - @tokenparser - def parse(tokens): - if tokens[0] == "*": - return codejoin(tokens[1], ArithMul()) - else: - return codejoin(tokens[1], ArithDiv()) - -class ArithDiv(CodeOp): - def execute(self, vm): - v1, v2 = vm.pop(2) - vm.push(v1/v2) - -class ArithExp(CodeOp): - def execute(self, vm): - v1, v2 = vm.pop(2) - vm.push(v1**v2) - - @staticmethod - @tokenparser - def parse(tokens): - return codejoin(tokens[1], ArithExp()) - - -class BoolCompare(CodeOp): - map = { - '==': lambda x, y: int(x==y), - '!=': lambda x, y: int(x!=y), - '>': lambda x, y: int(x>y), - '<': lambda x, y: int(x=': lambda x, y: int(x>=y), - 'in': lambda x, y: int(x in y) - } - - def __init__(self, cmpfunc): - CodeOp.__init__(self) - self.cmp = cmpfunc - - def execute(self, vm): - v1, v2 = vm.pop(2) - vm.push(self.cmp(v1, v2)) - - @staticmethod - @tokenparser - def parse(tokens): - op = tokens[0] - - return codejoin(tokens[1], BoolCompare(BoolCompare.map[op])) - - -class BoolLogic(CodeOp): - map = { - '&&': lambda x, y: int(x and y), - '||': lambda x, y: int(x or y), - '~~': lambda x, y: int((x or y) and not (x and y)), - 'and': lambda x, y: int(x and y), - 'or': lambda x, y: int(x or y), - 'xor': lambda x, y: int((x or y) and not (x and y)), - } - - def __init__(self, cmpfunc): - CodeOp.__init__(self) - self.cmp = cmpfunc - - def execute(self, vm): - v1, v2 = vm.pop(2) - vm.push(self.cmp(v1, v2)) - - @staticmethod - @tokenparser - def parse(tokens): - op = tokens[0] - - return codejoin(tokens[1], BoolLogic(BoolLogic.map[op])) - -class UnaryOp(CodeOp): - map = { - "!": lambda x: int(not x), - "-": lambda x: -x - } - - def __init__(self, cmpfunc): - CodeOp.__init__(self) - self.cmp = cmpfunc - - def execute(self, vm): - v = vm.pop(1) - vm.push(self.cmp(v)) - - @staticmethod - @tokenparser - def parse(tokens): - rv = [] - ops = [] - for t in tokens: - if isinstance(t, (str, bytes)) and t in UnaryOp.map: - ops.append(UnaryOp(UnaryOp.map[t])) - else: - rv.append(t) - return codejoin(rv, ops) - -class Assignment(CodeOp): - @staticmethod - @tokenparser - def parse(tokens): - from language_types import VMVariable, VMPropRef, VMFileRef - if len(tokens) > 2: - assert tokens[1] == "=" - var = tokens[0] - if isinstance(var, VMVariable): - var = var.ref() + [SetVariable()] - elif isinstance(var, VMPropRef): - var = var.ref() + [SetProperty()] - elif isinstance(var, VMFileRef): - var = var.ref() + [SetFile()] - else: - raise ValueError("Assignment to unknown type: %s" % (var,)) - - return codejoin(tokens[2:], var) - return tokens - -class StackLiteral(StackCodeOp): - def execute(self, vm): - vm.push(self.stack_value) - - @staticmethod - @tokenparser - def parse(tokens): - return StackLiteral(tokens[0]) - - def __repr__(self): - try: - nv = coerce(self.stack_value) - except TypeError: - return "<** INVALID STACKLITERAL: %r **>" % (self.stack_value,) - return "" % (coerce(self.stack_value),) - - -class StackToList(CodeOp): - def execute(self, vm): - from language_types import VMList - count, = vm.pop(1) - stacklist = vm.pop_raw(count) - i = 0 - while i < len(stacklist): - if isinstance(stacklist[i], VMList) and stacklist[i].flat: - nexti = i + len(stacklist[i]) - stacklist[i:i+1] = uncoerce(stacklist[i]) - else: - stacklist[i] = uncoerce(stacklist[i]) - nexti = i + 1 - - i = nexti - vm.push(stacklist) - - @staticmethod - @tokenparser - def parse(tokens): - if not tokens: - return codejoin(StackLiteral(0), StackToList()) - rv = codejoin(tokens[0][0], StackLiteral(len(tokens)), StackToList()) - return rv - -class Flatten(CodeOp): - def execute(self, vm): - flatlist, = vm.pop_raw(1) - flatlist.flat = 1 - vm.push(flatlist) - - @staticmethod - @tokenparser - def parse(tokens): - if len(tokens) > 0 and tokens[0] == '@': - return codejoin(tokens[0], Flatten()) - else: - return tokens - - -class CallFunc(CodeOp): - def execute(self, vm): - obj, funcname, args = vm.pop(3) - vm.push_context(args) - vm.push_code(codejoin( - vm.get_code(obj, funcname), - EndContext() - )) - - - @staticmethod - @tokenparser - def parse(tokens): - assert len(tokens) == 4 and tokens[1] == ":" - return codejoin(tokens[0], tokens[2], tokens[3], CallFunc()) - - -class DiscardStack(CodeOp): - def execute(self, vm): - vm.pop(1) - - - @staticmethod - @tokenparser - def parse(tokens): - return codejoin(DiscardStack()) - -class ExtractStack(CodeOp): - def __init__(self, callback, count): - CodeOp.__init__(count) - self.callback = callback - - def execute(self, vm): - count, = vm.pop(1) - self.callback(vm.pop(count)) - -class KeywordReturn(CodeOp): - def execute(self, vm): - vm.jump_code(EndContext) - - @staticmethod - @tokenparser - def parse(tokens): - return codejoin(tokens[1:], KeywordReturn()) - -class LoopBreak(CodeOp): - def execute(self, vm): - vm.jump("break") - -class LoopContinue(CodeOp): - def execute(self, vm): - vm.jump("cont") - -class StartContext(CodeOp): - def execute(self, vm): - vm.push_context() - -class EndContext(CodeOp): - def execute(self, vm): - vm.pop_context() - -class LabelCodeOp(CodeOp): - def __init__(self, label): - CodeOp.__init__(self) - self.label = label - def execute(self, vm): - pass - - def ticks(self): - return 0 - -class JumpUncond(LabelCodeOp): - def execute(self, vm): - vm.jump(self.label) - -class JumpIfFalse(LabelCodeOp): - def execute(self, vm): - cond, = vm.pop(1) - if not cond: - vm.jump(self.label) - -class JumpIfTrue(LabelCodeOp): - def execute(self, vm): - cond, = vm.pop(1) - if cond: - vm.jump(self.label) - -class EndBlock(LabelCodeOp): - def execute(self, vm): - pass - - -class FinallyBlock(EndBlock): - def execute(self, vm): - if vm.exc_stack: - # finally can be invoked by the exception handler itself, so - # it's possible the error has not been handled yet. - # if there is an unhandled exception still on the stack, then - # continue searching for a handler. - vm.reraise() - - -class ExcHandlerBlock(EndBlock): - def __init__(self, label, code): - EndBlock.__init__(self, label) - - self.code = code - - def execute(self, vm): - while vm.exc_stack: - # get the exception that's being handled and place it on the real stack - exc = vm.exc_pop() - vm.push(exc) - - # and queue up the exception handler code - vm.code_push(self.code) - - - -class WhileBlock(CodeOp): - def __init__(self): - CodeOp.__init__(self) - - self.cond = None - self.block = [] - - def execute(self, vm): - # load the block's code into the vm at runtime - # prevents conflicts with jump targets - vm.code_push(codejoin( - self.cond, - JumpIfFalse("break"), - self.block, - EndBlock("cont"), - self, - EndBlock("break") - )) - - @staticmethod - @tokenparser - def parse(tokens): - rv = WhileBlock() - - for i in range(1, len(tokens)): - tok = tokens[i] - if rv.cond == None: - rv.cond = tok - else: - rv.block.append(tok) - - return rv - -class TryBlock(CodeOp): - def __init__(self): - CodeOp.__init__(self) - - self.var = None - self.blocks = {} - self.blocks = {"try": [], "except": [], "else": [], "finally": []} - - def execute(self, vm): - code = [] - code.append(self.blocks["try"]) - - if "else" in self.blocks: - code.append(JumpUncond("exc_else")) - elif "finally" in self.blocks: - code.append(JumpUncond("exc_finally")) - else: - code.append(JumpUncond("exc_normalexit")) - - if "except" in self.blocks: - handler_code = codejoin( - SetVariable(self.var), - self.blocks["except"] - ) - code.append(ExcHandlerBlock("exc_handler", handler_code)) - if "finally" in self.blocks: - code.append(JumpUncond("exc_finally")) - else: - code.append(JumpUncond("exc_normalexit")) - - if "else" in self.blocks: - vm.code_push(self.blocks["else"]) - if "finally" in self.blocks: - code.append(JumpUncond("exc_finally")) - else: - code.append(JumpUncond("exc_normalexit")) - - if "finally" in self.blocks: - code.append(FinallyBlock("exc_finally")) - code.append(self.blocks["finally"]) - - code.append(EndBlock("exc_normalexit")) - vm.code_push(code) - - @staticmethod - @tokenparser - def parse(tokens): - rv = TryBlock() - - active_tok = None - for i in range(1, len(tokens)): - tok = tokens[i] - if tok in ("try", "except", "else", "finally"): - active_tok = tok - continue - - if active_tok == "except" and self.var == None: - self.var = tok - else: - self.blocks[active_tok].append(tok) - - return rv - -class ForeachExtractList(CodeOp): - def __init__(self, foreach): - CodeOp.__init__(self) - self.foreach = foreach - self.pos = foreach.pos - - def execute(self, vm): - ldata, = vm.pop(1) - if isinstance(ldata, dict): - vm.push(ldata.keys()) - vm.push(0) - elif isinstance(ldata, list): - vm.push(ldata) - vm.push(0) - else: - vm.raise_exc("Error") - -class ForeachPop(CodeOp): - def __init__(self, foreach): - CodeOp.__init__(self) - self.foreach = foreach - self.pos = foreach.pos - - def execute(self, vm): - ldata, idx = vm.pop(2) - if idx > len(ldata): - "no more values to pop" - vm.push(0) - else: - "more values to pop" - val = ldata[idx] - vm.set_var(self.foreach.var, val) - vm.push(ldata) - vm.push(idx+1) - vm.push(1) - - -class ForeachIterator(CodeOp): - def __init__(self, foreach): - CodeOp.__init__(self) - self.foreach = foreach - self.pos = foreach.pos - - def execute(self, vm): - vm.code_push(codejoin( - ForeachPop(), - JumpIfFalse("break"), - self.foreach.block, - EndBlock("cont"), - self, - EndBlock("break") - )) - - -class ForeachBlock(CodeOp): - def __init__(self): - CodeOp.__init__(self) - - self.src = None - self.list = None - self.var = None - self.block = [] - - - def execute(self, vm): - # load the block's code into the vm at runtime - # prevents conflicts with jump targets - vm.code_push(codejoin( - self.src, - ForeachExtractList(), - self.new_iterator() - )) - - def new_iterator(self): - return ForeachIterator(self) - - @staticmethod - @tokenparser - def parse(tokens): - rv = ForeachBlock() - - for i in range(1, len(tokens)): - tok = tokens[i] - if rv.var == None: - rv.var = tok - elif tok == "in": - continue - elif rv.src == None: - rv.src = tok - else: - rv.block.append(tok) - - return rv - - -class IfBlock(CodeOp): - def __init__(self): - CodeOp.__init__(self) - - self.conditions = [] - - def execute(self, vm): - # load the ifblock code into the vm at runtime - # why, I don't know, but it makes my life easier - code = [] - for cond, block in self.conditions: - code.append(cond) - code.append(JumpIfFalse("next")) - code.append(block) - code.append(JumpUncond("endif")) - code.append(EndBlock("next")) - code.append(EndBlock("endif")) - codeseq = codejoin(code) - vm.code_push(codeseq) - - @staticmethod - @tokenparser - def parse(tokens): - conds = [] - tok_count = 0 - active_tok = None - for i in range(len(tokens)): - tok = tokens[i] - - if tok == "endif": - break - if tok in ("if", "elseif", "else"): - tok_count += 1 - active_tok = tok - else: - if tok_count > len(conds): - if active_tok == "else": - cond = [StackLiteral(1)] - block = tok - else: - cond = [tok] - block = [] - conds.append([cond, [block]]) - else: - conds[tok_count-1][1].append(tok) - - ib = IfBlock() - conds = [[optimizer.optimize(x), optimizer.optimize(y)] for x, y in conds] - ib.conditions = conds - return ib +from language_tools import * +from bi import builtin_map +import optimizer + + + + +def coerce(value): + from language_types import ObjRef, VMInteger, VMList, VMString, VMTable, VMObjRef, VMFloat, VMType + if isinstance(value, int): + return VMInteger(value) + elif isinstance(value, (tuple, list)): + return VMList(list(value)) + elif isinstance(value, str): + return VMString(value) + elif isinstance(value, dict): + return VMTable(value) + elif isinstance(value, ObjRef): + return VMObjRef(value) + elif isinstance(value, float): + return VMFloat(value) + elif value == None: + return VMInteger(0) + elif isinstance(value, VMType): + return value + else: + raise TypeError("Unknown type %s cannot be coerced to VMType" % (type(value),)) + + +def uncoerce(value): + from language_types import VMType + assert isinstance(value, VMType) + return value.value + + +def codejoin(*args): + rv = [] + for arg in args: + if isinstance(arg, CodeOpSequence): + for subarg in arg.sequence: + rv.extend(codejoin(subarg)) + elif isinstance(arg, list): + for subarg in arg: + rv.extend(codejoin(subarg)) + else: + rv.append(arg) + + return rv + seq = CodeOpSequence.new(rv) + return seq + #return flatten(rv, ltypes=(list,)) + + +class CodeOp(VMBaseObject): + def load_stack(self, vm): + pass + + def ticks(self): + return 1 + +class CodeOpSequence(CodeOp): + + @staticmethod + def new(input): + c = CodeOpSequence() + c.sequence = input + return c + + def load_stack(self, vm): + pass + + def ticks(self): + return 0 + + +class StackCodeOp(CodeOp): + def __init__(self, stack_value): + CodeOp.__init__(self) + self.stack_value = stack_value + + def load_stack(self, vm): + vm.push(self.stack_value) + + +class NoOp(CodeOp): + def execute(self, vm): + pass + + def ticks(self): + return 0 + + @staticmethod + @tokenparser + def parse(tokens): + return [] + + +class GetProperty(CodeOp): + def execute(self, vm): + obj, prop = vm.pop(2) + objstore = vm.db.get_obj(obj) + val = objstore.get_prop(prop) + vm.push(val) + + @staticmethod + @tokenparser + def parse(tokens): + return codejoin(GetProperty()) + +class SetProperty(CodeOp): + def execute(self, vm): + val, prop, obj = vm.pop(3) + vm.db.set_property(obj, prop, val) + vm.push(val) + + @staticmethod + @tokenparser + def parse(tokens): + return codejoin(StackLiteral(tokens[0])) + +class GetFile(CodeOp): + def execute(self, vm): + obj, prop = vm.pop(2) + objstore = vm.db.get_obj(obj) + val = objstore.get_file(prop) + vm.push(val) + +class SetFile(CodeOp): + def execute(self, vm): + val, prop, obj = vm.pop(3) + vm.db.set_file(obj, prop, val) + vm.push(val) + +class SetVariable(CodeOp): + def execute(self, vm): + val, varname = vm.pop(2) + vm.setvar(varname, val) + vm.push(val) + + @staticmethod + @tokenparser + def parse(tokens): + assert isinstance(tokens[0], GetVariable) + return codejoin(SetVariable(tokens[0].stack_value)) + + +class GetVariable(CodeOp): + def execute(self, vm): + varname, = vm.pop(1) + vm.push(vm.getvar(varname)) + + @staticmethod + @tokenparser + def parse(tokens): + return codejoin(tokens[0], GetVariable()) + +class CallBuiltin(CodeOp): + def execute(self, vm): + funcname, args = vm.pop(2) + funcname = funcname.encode('ascii', 'ignore') + retval = builtin_map[funcname](vm, args) + vm.push(retval) + + @staticmethod + @tokenparser + def parse(tokens): + #if not tokens[0] in builtin_map: + # raise ParseException('Attempt to call undefined builtin function: "%s"' % (tokens[0],)) + return codejoin(tokens[0], tokens[1], CallBuiltin()) + +class CallFunction(CodeOp): + def execute(self, vm): + obj, name = vm.pop(2) + vm.code_push(codejoin(StartContext(), vm.get_code(obj, name), EndContext())) + + @staticmethod + @tokenparser + def parse(tokens): + return codejoin(tokens[0], CallFunction()) + +class ArithAdd(CodeOp): + def execute(self, vm): + v1, v2 = vm.pop(2) + vm.push(v1+v2) + + @staticmethod + @tokenparser + def parse(tokens): + if tokens[0] == "+": + return codejoin(tokens[1], ArithAdd()) + else: + return codejoin(tokens[1], ArithSub()) + +class ArithSub(CodeOp): + def execute(self, vm): + v1, v2 = vm.pop(2) + vm.push(v1-v2) + + +class ArithMul(CodeOp): + def execute(self, vm): + v1, v2 = vm.pop(2) + vm.push(v1*v2) + + @staticmethod + @tokenparser + def parse(tokens): + if tokens[0] == "*": + return codejoin(tokens[1], ArithMul()) + else: + return codejoin(tokens[1], ArithDiv()) + +class ArithDiv(CodeOp): + def execute(self, vm): + v1, v2 = vm.pop(2) + vm.push(v1/v2) + +class ArithExp(CodeOp): + def execute(self, vm): + v1, v2 = vm.pop(2) + vm.push(v1**v2) + + @staticmethod + @tokenparser + def parse(tokens): + return codejoin(tokens[1], ArithExp()) + + +class BoolCompare(CodeOp): + map = { + '==': lambda x, y: int(x==y), + '!=': lambda x, y: int(x!=y), + '>': lambda x, y: int(x>y), + '<': lambda x, y: int(x=': lambda x, y: int(x>=y), + 'in': lambda x, y: int(x in y) + } + + def __init__(self, cmpfunc): + CodeOp.__init__(self) + self.cmp = cmpfunc + + def execute(self, vm): + v1, v2 = vm.pop(2) + vm.push(self.cmp(v1, v2)) + + @staticmethod + @tokenparser + def parse(tokens): + op = tokens[0] + + return codejoin(tokens[1], BoolCompare(BoolCompare.map[op])) + + +class BoolLogic(CodeOp): + map = { + '&&': lambda x, y: int(x and y), + '||': lambda x, y: int(x or y), + '~~': lambda x, y: int((x or y) and not (x and y)), + 'and': lambda x, y: int(x and y), + 'or': lambda x, y: int(x or y), + 'xor': lambda x, y: int((x or y) and not (x and y)), + } + + def __init__(self, cmpfunc): + CodeOp.__init__(self) + self.cmp = cmpfunc + + def execute(self, vm): + v1, v2 = vm.pop(2) + vm.push(self.cmp(v1, v2)) + + @staticmethod + @tokenparser + def parse(tokens): + op = tokens[0] + + return codejoin(tokens[1], BoolLogic(BoolLogic.map[op])) + +class UnaryOp(CodeOp): + map = { + "!": lambda x: int(not x), + "-": lambda x: -x + } + + def __init__(self, cmpfunc): + CodeOp.__init__(self) + self.cmp = cmpfunc + + def execute(self, vm): + v = vm.pop(1) + vm.push(self.cmp(v)) + + @staticmethod + @tokenparser + def parse(tokens): + rv = [] + ops = [] + for t in tokens: + if isinstance(t, (str, bytes)) and t in UnaryOp.map: + ops.append(UnaryOp(UnaryOp.map[t])) + else: + rv.append(t) + return codejoin(rv, ops) + +class Assignment(CodeOp): + @staticmethod + @tokenparser + def parse(tokens): + from language_types import VMVariable, VMPropRef, VMFileRef + if len(tokens) > 2: + assert tokens[1] == "=" + var = tokens[0] + if isinstance(var, VMVariable): + var = var.ref() + [SetVariable()] + elif isinstance(var, VMPropRef): + var = var.ref() + [SetProperty()] + elif isinstance(var, VMFileRef): + var = var.ref() + [SetFile()] + else: + raise ValueError("Assignment to unknown type: %s" % (var,)) + + return codejoin(tokens[2:], var) + return tokens + +class StackLiteral(StackCodeOp): + def execute(self, vm): + vm.push(self.stack_value) + + @staticmethod + @tokenparser + def parse(tokens): + return StackLiteral(tokens[0]) + + def __repr__(self): + try: + nv = coerce(self.stack_value) + except TypeError: + return "<** INVALID STACKLITERAL: %r **>" % (self.stack_value,) + return "" % (coerce(self.stack_value),) + + +class StackToList(CodeOp): + def execute(self, vm): + from language_types import VMList + count, = vm.pop(1) + stacklist = vm.pop_raw(count) + i = 0 + while i < len(stacklist): + if isinstance(stacklist[i], VMList) and stacklist[i].flat: + nexti = i + len(stacklist[i]) + stacklist[i:i+1] = uncoerce(stacklist[i]) + else: + stacklist[i] = uncoerce(stacklist[i]) + nexti = i + 1 + + i = nexti + vm.push(stacklist) + + @staticmethod + @tokenparser + def parse(tokens): + if not tokens: + return codejoin(StackLiteral(0), StackToList()) + rv = codejoin(tokens[0][0], StackLiteral(len(tokens)), StackToList()) + return rv + +class Flatten(CodeOp): + def execute(self, vm): + flatlist, = vm.pop_raw(1) + flatlist.flat = 1 + vm.push(flatlist) + + @staticmethod + @tokenparser + def parse(tokens): + if len(tokens) > 0 and tokens[0] == '@': + return codejoin(tokens[0], Flatten()) + else: + return tokens + + +class CallFunc(CodeOp): + def execute(self, vm): + obj, funcname, args = vm.pop(3) + vm.push_context(args) + vm.push_code(codejoin( + vm.get_code(obj, funcname), + EndContext() + )) + + + @staticmethod + @tokenparser + def parse(tokens): + assert len(tokens) == 4 and tokens[1] == ":" + return codejoin(tokens[0], tokens[2], tokens[3], CallFunc()) + + +class DiscardStack(CodeOp): + def execute(self, vm): + vm.pop(1) + + + @staticmethod + @tokenparser + def parse(tokens): + return codejoin(DiscardStack()) + +class ExtractStack(CodeOp): + def __init__(self, callback, count): + CodeOp.__init__(count) + self.callback = callback + + def execute(self, vm): + count, = vm.pop(1) + self.callback(vm.pop(count)) + +class KeywordReturn(CodeOp): + def execute(self, vm): + vm.jump_code(EndContext) + + @staticmethod + @tokenparser + def parse(tokens): + return codejoin(tokens[1:], KeywordReturn()) + +class LoopBreak(CodeOp): + def execute(self, vm): + vm.jump("break") + +class LoopContinue(CodeOp): + def execute(self, vm): + vm.jump("cont") + +class StartContext(CodeOp): + def execute(self, vm): + vm.push_context() + +class EndContext(CodeOp): + def execute(self, vm): + vm.pop_context() + +class LabelCodeOp(CodeOp): + def __init__(self, label): + CodeOp.__init__(self) + self.label = label + def execute(self, vm): + pass + + def ticks(self): + return 0 + +class JumpUncond(LabelCodeOp): + def execute(self, vm): + vm.jump(self.label) + +class JumpIfFalse(LabelCodeOp): + def execute(self, vm): + cond, = vm.pop(1) + if not cond: + vm.jump(self.label) + +class JumpIfTrue(LabelCodeOp): + def execute(self, vm): + cond, = vm.pop(1) + if cond: + vm.jump(self.label) + +class EndBlock(LabelCodeOp): + def execute(self, vm): + pass + + +class FinallyBlock(EndBlock): + def execute(self, vm): + if vm.exc_stack: + # finally can be invoked by the exception handler itself, so + # it's possible the error has not been handled yet. + # if there is an unhandled exception still on the stack, then + # continue searching for a handler. + vm.reraise() + + +class ExcHandlerBlock(EndBlock): + def __init__(self, label, code): + EndBlock.__init__(self, label) + + self.code = code + + def execute(self, vm): + while vm.exc_stack: + # get the exception that's being handled and place it on the real stack + exc = vm.exc_pop() + vm.push(exc) + + # and queue up the exception handler code + vm.code_push(self.code) + + + +class WhileBlock(CodeOp): + def __init__(self): + CodeOp.__init__(self) + + self.cond = None + self.block = [] + + def execute(self, vm): + # load the block's code into the vm at runtime + # prevents conflicts with jump targets + vm.code_push(codejoin( + self.cond, + JumpIfFalse("break"), + self.block, + EndBlock("cont"), + self, + EndBlock("break") + )) + + @staticmethod + @tokenparser + def parse(tokens): + rv = WhileBlock() + + for i in range(1, len(tokens)): + tok = tokens[i] + if rv.cond == None: + rv.cond = tok + else: + rv.block.append(tok) + + return rv + +class TryBlock(CodeOp): + def __init__(self): + CodeOp.__init__(self) + + self.var = None + self.blocks = {} + self.blocks = {"try": [], "except": [], "else": [], "finally": []} + + def execute(self, vm): + code = [] + code.append(self.blocks["try"]) + + if "else" in self.blocks: + code.append(JumpUncond("exc_else")) + elif "finally" in self.blocks: + code.append(JumpUncond("exc_finally")) + else: + code.append(JumpUncond("exc_normalexit")) + + if "except" in self.blocks: + handler_code = codejoin( + SetVariable(self.var), + self.blocks["except"] + ) + code.append(ExcHandlerBlock("exc_handler", handler_code)) + if "finally" in self.blocks: + code.append(JumpUncond("exc_finally")) + else: + code.append(JumpUncond("exc_normalexit")) + + if "else" in self.blocks: + vm.code_push(self.blocks["else"]) + if "finally" in self.blocks: + code.append(JumpUncond("exc_finally")) + else: + code.append(JumpUncond("exc_normalexit")) + + if "finally" in self.blocks: + code.append(FinallyBlock("exc_finally")) + code.append(self.blocks["finally"]) + + code.append(EndBlock("exc_normalexit")) + vm.code_push(code) + + @staticmethod + @tokenparser + def parse(tokens): + rv = TryBlock() + + active_tok = None + for i in range(1, len(tokens)): + tok = tokens[i] + if tok in ("try", "except", "else", "finally"): + active_tok = tok + continue + + if active_tok == "except" and self.var == None: + self.var = tok + else: + self.blocks[active_tok].append(tok) + + return rv + +class ForeachExtractList(CodeOp): + def __init__(self, foreach): + CodeOp.__init__(self) + self.foreach = foreach + self.pos = foreach.pos + + def execute(self, vm): + ldata, = vm.pop(1) + if isinstance(ldata, dict): + vm.push(ldata.keys()) + vm.push(0) + elif isinstance(ldata, list): + vm.push(ldata) + vm.push(0) + else: + vm.raise_exc("Error") + +class ForeachPop(CodeOp): + def __init__(self, foreach): + CodeOp.__init__(self) + self.foreach = foreach + self.pos = foreach.pos + + def execute(self, vm): + ldata, idx = vm.pop(2) + if idx > len(ldata): + "no more values to pop" + vm.push(0) + else: + "more values to pop" + val = ldata[idx] + vm.set_var(self.foreach.var, val) + vm.push(ldata) + vm.push(idx+1) + vm.push(1) + + +class ForeachIterator(CodeOp): + def __init__(self, foreach): + CodeOp.__init__(self) + self.foreach = foreach + self.pos = foreach.pos + + def execute(self, vm): + vm.code_push(codejoin( + ForeachPop(), + JumpIfFalse("break"), + self.foreach.block, + EndBlock("cont"), + self, + EndBlock("break") + )) + + +class ForeachBlock(CodeOp): + def __init__(self): + CodeOp.__init__(self) + + self.src = None + self.list = None + self.var = None + self.block = [] + + + def execute(self, vm): + # load the block's code into the vm at runtime + # prevents conflicts with jump targets + vm.code_push(codejoin( + self.src, + ForeachExtractList(), + self.new_iterator() + )) + + def new_iterator(self): + return ForeachIterator(self) + + @staticmethod + @tokenparser + def parse(tokens): + rv = ForeachBlock() + + for i in range(1, len(tokens)): + tok = tokens[i] + if rv.var == None: + rv.var = tok + elif tok == "in": + continue + elif rv.src == None: + rv.src = tok + else: + rv.block.append(tok) + + return rv + + +class IfBlock(CodeOp): + def __init__(self): + CodeOp.__init__(self) + + self.conditions = [] + + def execute(self, vm): + # load the ifblock code into the vm at runtime + # why, I don't know, but it makes my life easier + code = [] + for cond, block in self.conditions: + code.append(cond) + code.append(JumpIfFalse("next")) + code.append(block) + code.append(JumpUncond("endif")) + code.append(EndBlock("next")) + code.append(EndBlock("endif")) + codeseq = codejoin(code) + vm.code_push(codeseq) + + @staticmethod + @tokenparser + def parse(tokens): + conds = [] + tok_count = 0 + active_tok = None + for i in range(len(tokens)): + tok = tokens[i] + + if tok == "endif": + break + if tok in ("if", "elseif", "else"): + tok_count += 1 + active_tok = tok + else: + if tok_count > len(conds): + if active_tok == "else": + cond = [StackLiteral(1)] + block = tok + else: + cond = [tok] + block = [] + conds.append([cond, [block]]) + else: + conds[tok_count-1][1].append(tok) + + ib = IfBlock() + conds = [[optimizer.optimize(x), optimizer.optimize(y)] for x, y in conds] + ib.conditions = conds + return ib diff --git a/database.py b/database.py index 635a97b..592bda9 100755 --- a/database.py +++ b/database.py @@ -134,7 +134,7 @@ class Database(object): i += 1 break - def get_obj(self, objref): + def get_obj(self, objnum): i = objnum if i < len(self.objects): self.objects[i:] = [] @@ -198,4 +198,4 @@ class Database(object): return None - \ No newline at end of file + diff --git a/ebnf.py b/ebnf.py index 8dfcaea..0b357f7 100755 --- a/ebnf.py +++ b/ebnf.py @@ -1,149 +1,149 @@ -# This module tries to implement ISO 14977 standard with pyparsing. -# pyparsing version 1.1 or greater is required. - -# ISO 14977 standardize The Extended Backus-Naur Form(EBNF) syntax. -# You can read a final draft version here: -# http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html - - -from pyparsing import * - - -all_names = ''' -integer -meta_identifier -terminal_string -optional_sequence -repeated_sequence -grouped_sequence -syntactic_primary -syntactic_factor -syntactic_term -single_definition -definitions_list -syntax_rule -syntax -'''.split() - - -integer = Word(nums) -meta_identifier = Word(alphas, alphanums + '_') -terminal_string = Suppress("'") + CharsNotIn("'") + Suppress("'") ^ \ - Suppress('"') + CharsNotIn('"') + Suppress('"') -definitions_list = Forward() -optional_sequence = Suppress('[') + definitions_list + Suppress(']') -repeated_sequence = Suppress('{') + definitions_list + Suppress('}') -grouped_sequence = Suppress('(') + definitions_list + Suppress(')') -syntactic_primary = optional_sequence ^ repeated_sequence ^ \ - grouped_sequence ^ meta_identifier ^ terminal_string -syntactic_factor = Optional(integer + Suppress('*')) + syntactic_primary -syntactic_term = syntactic_factor + Optional(Suppress('-') + syntactic_factor) -single_definition = delimitedList(syntactic_term, ',') -definitions_list << delimitedList(single_definition, '|') -syntax_rule = meta_identifier + Suppress('=') + definitions_list + \ - Suppress(';') - -ebnfComment = ( "(*" + - ZeroOrMore( CharsNotIn("*") | ( "*" + ~Literal(")") ) ) + - "*)" ).streamline().setName("ebnfComment") - -syntax = OneOrMore(syntax_rule) -syntax.ignore(ebnfComment) - - -def do_integer(str, loc, toks): - return int(toks[0]) - -def do_meta_identifier(str, loc, toks): - if toks[0] in symbol_table: - return symbol_table[toks[0]] - else: - forward_count.value += 1 - symbol_table[toks[0]] = Forward() - return symbol_table[toks[0]] - -def do_terminal_string(str, loc, toks): - return Literal(toks[0]) - -def do_optional_sequence(str, loc, toks): - return Optional(toks[0]) - -def do_repeated_sequence(str, loc, toks): - return ZeroOrMore(toks[0]) - -def do_grouped_sequence(str, loc, toks): - return Group(toks[0]) - -def do_syntactic_primary(str, loc, toks): - return toks[0] - -def do_syntactic_factor(str, loc, toks): - if len(toks) == 2: - # integer * syntactic_primary - return And([toks[1]] * toks[0]) - else: - # syntactic_primary - return [ toks[0] ] - -def do_syntactic_term(str, loc, toks): - if len(toks) == 2: - # syntactic_factor - syntactic_factor - return NotAny(toks[1]) + toks[0] - else: - # syntactic_factor - return [ toks[0] ] - -def do_single_definition(str, loc, toks): - toks = toks.asList() - if len(toks) > 1: - # syntactic_term , syntactic_term , ... - return And(toks) - else: - # syntactic_term - return [ toks[0] ] - -def do_definitions_list(str, loc, toks): - toks = toks.asList() - if len(toks) > 1: - # single_definition | single_definition | ... - return Or(toks) - else: - # single_definition - return [ toks[0] ] - -def do_syntax_rule(str, loc, toks): - # meta_identifier = definitions_list ; - assert toks[0].expr is None, "Duplicate definition" - forward_count.value -= 1 - toks[0] << toks[1] - return [ toks[0] ] - -def do_syntax(str, loc, toks): - # syntax_rule syntax_rule ... - return symbol_table - - - -symbol_table = {} -class forward_count: - pass -forward_count.value = 0 -for name in all_names: - expr = vars()[name] - action = vars()['do_' + name] - expr.setName(name) - expr.setParseAction(action) - #~ expr.setDebug() - - -def parse(ebnf, given_table={}): - symbol_table.clear() - symbol_table.update(given_table) - forward_count.value = 0 - table = syntax.parseString(ebnf)[0] - assert forward_count.value == 0, "Missing definition" - for name in table: - expr = table[name] - expr.setName(name) - #~ expr.setDebug() - return table +# This module tries to implement ISO 14977 standard with pyparsing. +# pyparsing version 1.1 or greater is required. + +# ISO 14977 standardize The Extended Backus-Naur Form(EBNF) syntax. +# You can read a final draft version here: +# http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html + + +from pyparsing import * + + +all_names = ''' +integer +meta_identifier +terminal_string +optional_sequence +repeated_sequence +grouped_sequence +syntactic_primary +syntactic_factor +syntactic_term +single_definition +definitions_list +syntax_rule +syntax +'''.split() + + +integer = Word(nums) +meta_identifier = Word(alphas, alphanums + '_') +terminal_string = Suppress("'") + CharsNotIn("'") + Suppress("'") ^ \ + Suppress('"') + CharsNotIn('"') + Suppress('"') +definitions_list = Forward() +optional_sequence = Suppress('[') + definitions_list + Suppress(']') +repeated_sequence = Suppress('{') + definitions_list + Suppress('}') +grouped_sequence = Suppress('(') + definitions_list + Suppress(')') +syntactic_primary = optional_sequence ^ repeated_sequence ^ \ + grouped_sequence ^ meta_identifier ^ terminal_string +syntactic_factor = Optional(integer + Suppress('*')) + syntactic_primary +syntactic_term = syntactic_factor + Optional(Suppress('-') + syntactic_factor) +single_definition = delimitedList(syntactic_term, ',') +definitions_list << delimitedList(single_definition, '|') +syntax_rule = meta_identifier + Suppress('=') + definitions_list + \ + Suppress(';') + +ebnfComment = ( "(*" + + ZeroOrMore( CharsNotIn("*") | ( "*" + ~Literal(")") ) ) + + "*)" ).streamline().setName("ebnfComment") + +syntax = OneOrMore(syntax_rule) +syntax.ignore(ebnfComment) + + +def do_integer(str, loc, toks): + return int(toks[0]) + +def do_meta_identifier(str, loc, toks): + if toks[0] in symbol_table: + return symbol_table[toks[0]] + else: + forward_count.value += 1 + symbol_table[toks[0]] = Forward() + return symbol_table[toks[0]] + +def do_terminal_string(str, loc, toks): + return Literal(toks[0]) + +def do_optional_sequence(str, loc, toks): + return Optional(toks[0]) + +def do_repeated_sequence(str, loc, toks): + return ZeroOrMore(toks[0]) + +def do_grouped_sequence(str, loc, toks): + return Group(toks[0]) + +def do_syntactic_primary(str, loc, toks): + return toks[0] + +def do_syntactic_factor(str, loc, toks): + if len(toks) == 2: + # integer * syntactic_primary + return And([toks[1]] * toks[0]) + else: + # syntactic_primary + return [ toks[0] ] + +def do_syntactic_term(str, loc, toks): + if len(toks) == 2: + # syntactic_factor - syntactic_factor + return NotAny(toks[1]) + toks[0] + else: + # syntactic_factor + return [ toks[0] ] + +def do_single_definition(str, loc, toks): + toks = toks.asList() + if len(toks) > 1: + # syntactic_term , syntactic_term , ... + return And(toks) + else: + # syntactic_term + return [ toks[0] ] + +def do_definitions_list(str, loc, toks): + toks = toks.asList() + if len(toks) > 1: + # single_definition | single_definition | ... + return Or(toks) + else: + # single_definition + return [ toks[0] ] + +def do_syntax_rule(str, loc, toks): + # meta_identifier = definitions_list ; + assert toks[0].expr is None, "Duplicate definition" + forward_count.value -= 1 + toks[0] << toks[1] + return [ toks[0] ] + +def do_syntax(str, loc, toks): + # syntax_rule syntax_rule ... + return symbol_table + + + +symbol_table = {} +class forward_count: + pass +forward_count.value = 0 +for name in all_names: + expr = vars()[name] + action = vars()['do_' + name] + expr.setName(name) + expr.setParseAction(action) + #~ expr.setDebug() + + +def parse(ebnf, given_table={}): + symbol_table.clear() + symbol_table.update(given_table) + forward_count.value = 0 + table = syntax.parseString(ebnf)[0] + assert forward_count.value == 0, "Missing definition" + for name in table: + expr = table[name] + expr.setName(name) + #~ expr.setDebug() + return table diff --git a/errors.py b/errors.py index db17170..c92e654 100644 --- a/errors.py +++ b/errors.py @@ -1,92 +1,92 @@ -from pyenum import pyenum - -enum = pyenum() -enum.E_NONE = 0 -enum.E_PERM = 1 -enum.E_PROPNF = 2 -enum.E_FUNCNF = 3 -enum.E_FILENF = 4 -enum.E_VARNF = 5 -enum.E_INVARG = 6 -enum.E_TICKS = 7 -enum.E_SECONDS = 8 -enum.E_MEMORY = 9 -enum.E_IOERR = 10 -enum.E_TYPE = 11 -enum.E_ARGS = 12 -enum.E_FLOAT = 13 -enum.E_DIV = 14 -enum.E_SYNTAX = 15 -enum.E_UNICODE = 16 -enum.E_MAXREC = 17 -enum.E_PARSE = 18 -enum.E_RANGE = 19 -enum.E_INVIND = 20 -enum.E_RECMOVE = 21 -enum.E_NACC = 22 -enum.E_INVOBJ = 23 -enum.E_CONN = 24 - -enum.E_USER = 200 -enum.E_USER1 = 201 -enum.E_USER2 = 202 -enum.E_USER3 = 203 -enum.E_USER4 = 204 -enum.E_USER5 = 205 -enum.E_USER6 = 206 -enum.E_USER7 = 207 -enum.E_USER8 = 208 -enum.E_USER9 = 209 -enum.E_USER10 = 210 - -msgs = { - enum.E_NONE: "No error", - enum.E_PERM: "Permission denied", - enum.E_PROPNF: "Property not found", - enum.E_FUNCNF: "Function not found", - enum.E_FILENF: "File not found", - enum.E_VARNF: "Variable not found", - enum.E_INVARG: "Invalid argument", - enum.E_TICKS: "Out of ticks", - enum.E_SECONDS: "Out of seconds", - enum.E_MEMORY: "Out of memory", - enum.E_IOERR: "I/O error", - enum.E_TYPE: "Type mismatch", - enum.E_ARGS: "Incorrect number of arguments", - enum.E_FLOAT: "Floating point error", - enum.E_DIV: "Division by zero", - enum.E_SYNTAX: "Syntax error", - enum.E_UNICODE: "Invalid unicode character", - enum.E_MAXREC: "Maximum recursion depth reached", - enum.E_PARSE: "Unable to parse command", - enum.E_RANGE: "Index out of range", - enum.E_INVIND: "Invalid indirection", - enum.E_RECMOVE: "Recursive move", - enum.E_NACC: "Move refused by destination", - enum.E_INVOBJ: "Invalid object", - enum.E_CONN: "Connection error", - - enum.E_USER: "User-defined error", - enum.E_USER1: "User-defined error 1", - enum.E_USER2: "User-defined error 2", - enum.E_USER3: "User-defined error 3", - enum.E_USER4: "User-defined error 4", - enum.E_USER5: "User-defined error 5", - enum.E_USER6: "User-defined error 6", - enum.E_USER7: "User-defined error 7", - enum.E_USER8: "User-defined error 8", - enum.E_USER9: "User-defined error 9", - enum.E_USER10: "User-defined error 10", -} - -class VMRuntimeError(Exception): - def __init__(self, code, msg=None): - if msg == None and code in msgs: - msg = msgs[code] - elif msg == None: - msg = "Unknown error code" - Exception.__init__(self, msg) - self.errorcode = code - - +from pyenum import pyenum + +enum = pyenum() +enum.E_NONE = 0 +enum.E_PERM = 1 +enum.E_PROPNF = 2 +enum.E_FUNCNF = 3 +enum.E_FILENF = 4 +enum.E_VARNF = 5 +enum.E_INVARG = 6 +enum.E_TICKS = 7 +enum.E_SECONDS = 8 +enum.E_MEMORY = 9 +enum.E_IOERR = 10 +enum.E_TYPE = 11 +enum.E_ARGS = 12 +enum.E_FLOAT = 13 +enum.E_DIV = 14 +enum.E_SYNTAX = 15 +enum.E_UNICODE = 16 +enum.E_MAXREC = 17 +enum.E_PARSE = 18 +enum.E_RANGE = 19 +enum.E_INVIND = 20 +enum.E_RECMOVE = 21 +enum.E_NACC = 22 +enum.E_INVOBJ = 23 +enum.E_CONN = 24 + +enum.E_USER = 200 +enum.E_USER1 = 201 +enum.E_USER2 = 202 +enum.E_USER3 = 203 +enum.E_USER4 = 204 +enum.E_USER5 = 205 +enum.E_USER6 = 206 +enum.E_USER7 = 207 +enum.E_USER8 = 208 +enum.E_USER9 = 209 +enum.E_USER10 = 210 + +msgs = { + enum.E_NONE: "No error", + enum.E_PERM: "Permission denied", + enum.E_PROPNF: "Property not found", + enum.E_FUNCNF: "Function not found", + enum.E_FILENF: "File not found", + enum.E_VARNF: "Variable not found", + enum.E_INVARG: "Invalid argument", + enum.E_TICKS: "Out of ticks", + enum.E_SECONDS: "Out of seconds", + enum.E_MEMORY: "Out of memory", + enum.E_IOERR: "I/O error", + enum.E_TYPE: "Type mismatch", + enum.E_ARGS: "Incorrect number of arguments", + enum.E_FLOAT: "Floating point error", + enum.E_DIV: "Division by zero", + enum.E_SYNTAX: "Syntax error", + enum.E_UNICODE: "Invalid unicode character", + enum.E_MAXREC: "Maximum recursion depth reached", + enum.E_PARSE: "Unable to parse command", + enum.E_RANGE: "Index out of range", + enum.E_INVIND: "Invalid indirection", + enum.E_RECMOVE: "Recursive move", + enum.E_NACC: "Move refused by destination", + enum.E_INVOBJ: "Invalid object", + enum.E_CONN: "Connection error", + + enum.E_USER: "User-defined error", + enum.E_USER1: "User-defined error 1", + enum.E_USER2: "User-defined error 2", + enum.E_USER3: "User-defined error 3", + enum.E_USER4: "User-defined error 4", + enum.E_USER5: "User-defined error 5", + enum.E_USER6: "User-defined error 6", + enum.E_USER7: "User-defined error 7", + enum.E_USER8: "User-defined error 8", + enum.E_USER9: "User-defined error 9", + enum.E_USER10: "User-defined error 10", +} + +class VMRuntimeError(Exception): + def __init__(self, code, msg=None): + if msg == None and code in msgs: + msg = msgs[code] + elif msg == None: + msg = "Unknown error code" + Exception.__init__(self, msg) + self.errorcode = code + + \ No newline at end of file diff --git a/language_tools.py b/language_tools.py index 0d03377..c302008 100644 --- a/language_tools.py +++ b/language_tools.py @@ -1,75 +1,75 @@ -import sys -import traceback -import bisect -from pyparsing import ParseException - -def tokenparser(func): - def newfunc(s, loc, tokens): - try: - rv = func(tokens) - pos = lineno(s, loc) - if isinstance(rv, VMBaseObject): - rv.pos = pos - return rv - assert not False in [isinstance(x, (VMBaseObject, list)) for x in rv] - for x in rv: - if isinstance(x, VMBaseObject) and x.pos == None: - x.pos = pos - except: - e = sys.exc_info() - if e[0] == ParseException: - raise - gd = globals() - funcobj = None - for x in gd: - if hasattr(gd[x], "parse") and gd[x].parse == newfunc: - funcobj = x - print("Error with %s.parse tokens: %s" % (funcobj, tokens)) - traceback.print_exc(e) - raise - - return [rv] - - return newfunc - - -def lineno(s, loc): - if hash(s) in lineno.cache: - cache = lineno.cache[hash(s)] - else: - cache = [] - - i = 0 - while True: - n = s[i:].find("\n") + i - if n < i: - break - cache.append(n) - i = n + 1 - - cache.append(len(s)) - - lineno.cache[hash(s)] = cache - - cachepos = bisect.bisect_left(cache, loc) - line = cachepos + 1 - if cachepos == 0: - char = loc + 1 - else: - char = loc - cache[cachepos-1] - - - return (line, char) - -lineno.cache = {} - - -class VMBaseObject(object): - def __init__(self): - self.pos = None - - def bytecode(self): - return [self] - - def __repr__(self): - return "<%s>" % (self.__class__.__name__,) +import sys +import traceback +import bisect +from pyparsing import ParseException + +def tokenparser(func): + def newfunc(s, loc, tokens): + try: + rv = func(tokens) + pos = lineno(s, loc) + if isinstance(rv, VMBaseObject): + rv.pos = pos + return rv + assert not False in [isinstance(x, (VMBaseObject, list)) for x in rv] + for x in rv: + if isinstance(x, VMBaseObject) and x.pos == None: + x.pos = pos + except: + e = sys.exc_info() + if e[0] == ParseException: + raise + gd = globals() + funcobj = None + for x in gd: + if hasattr(gd[x], "parse") and gd[x].parse == newfunc: + funcobj = x + print("Error with %s.parse tokens: %s" % (funcobj, tokens)) + traceback.print_exc(e) + raise + + return [rv] + + return newfunc + + +def lineno(s, loc): + if hash(s) in lineno.cache: + cache = lineno.cache[hash(s)] + else: + cache = [] + + i = 0 + while True: + n = s[i:].find("\n") + i + if n < i: + break + cache.append(n) + i = n + 1 + + cache.append(len(s)) + + lineno.cache[hash(s)] = cache + + cachepos = bisect.bisect_left(cache, loc) + line = cachepos + 1 + if cachepos == 0: + char = loc + 1 + else: + char = loc - cache[cachepos-1] + + + return (line, char) + +lineno.cache = {} + + +class VMBaseObject(object): + def __init__(self): + self.pos = None + + def bytecode(self): + return [self] + + def __repr__(self): + return "<%s>" % (self.__class__.__name__,) diff --git a/language_types.py b/language_types.py index 4f5234c..276a03d 100755 --- a/language_types.py +++ b/language_types.py @@ -1,222 +1,222 @@ -from language_tools import * -from pyparsing import ParseException -from bytecode import * - -def disallow_keywords(tokens,keywords=None): - if keywords == None: - keywords = disallow_keywords.keywords - else: - keywords = set(keywords) - - for t in tokens: - if isinstance(t, VMIdent): - if t.name in keywords: - raise ParseException("Restricted keyword: %s" % (t.name,)) - elif isinstance(t, str): - tstr = t.encode('ascii', 'ignore') - if tstr in keywords: - raise ParseException("Restricted keyword: %s" % (tstr,)) - elif isinstance(t, str): - if t in keywords: - raise ParseException("Restricted keyword: %s" % (t,)) - -disallow_keywords.keywords = set('if,elseif,else,endif,try,except,finally,endtry,while,endwhile,continue,break,for,foreach,endfor'.split(',')) - - -class ObjRef(object): - def __init__(self, objnum): - self.objnum = objnum - - def __eq__(self, other): - return self.objnum == other.objnum - - - - -class VMType(VMBaseObject): - def bytecode(self): - return [StackLiteral(self)] - -class VMInteger(VMType): - def __init__(self, value): - VMType.__init__(self) - self.value = int(value) - - @staticmethod - @tokenparser - def parse(tokens): - return StackLiteral(VMInteger(tokens[0])) - - def __repr__(self): - return "%s" % (self.value,) - -class VMFloat(VMType): - def __init__(self, value): - VMType.__init__(self) - self.value = float(value) - - @staticmethod - @tokenparser - def parse(tokens): - return StackLiteral(VMFloat(tokens[0])) - - def __repr__(self): - return "%s" % (self.value,) - - -class VMTable(VMType): - def __init__(self, value): - VMType.__init__(self) - self.value = dict(value) - - @staticmethod - @tokenparser - def parse(tokens): - return StackLiteral(VMTable(tokens[0])) - -class VMList(VMType): - def __init__(self, value): - VMType.__init__(self) - self.value = list(value) - - @staticmethod - @tokenparser - def parse(tokens): - return StackLiteral(VMList()) - -class VMTablePair(VMType): - def __init__(self, value): - VMType.__init__(self) - self.key = key - self.value = value - - @staticmethod - @tokenparser - def parse(tokens): - return StackLiteral(VMList()) - -class VMString(VMType): - def __init__(self, value): - VMType.__init__(self) - if isinstance(value, str): - self.value = value - else: - self.value = str(value, 'ascii', 'ignore') - - def __repr__(self): - return "\"%s\"" % (repr(self.value)[1:].strip("'").replace("\\'", "'").replace('"', '\\"'),) - - @staticmethod - @tokenparser - def parse(tokens): - return StackLiteral(VMString(tokens[0])) - -class VMObjRef(VMType): - def __init__(self, value): - VMType.__init__(self) - if isinstance(value, ObjRef): - self.value = value - elif isinstance(value, (float, int)): - self.value = int(value) - else: - raise TypeError("Attempted to create VMObjRef with invalid object reference: %r" % (value,)) - - @staticmethod - @tokenparser - def parse(tokens): - return StackLiteral(VMObjRef(int(tokens[1]))) - - def __repr__(self): - return "#%s" % (self.value,) - -class VMRef(VMBaseObject): - pass - -class VMIdent(VMRef): - def __init__(self, name): - VMRef.__init__(self) - self.name = name - - def bytecode(self): - return [StackLiteral(str(self.name))] - - @staticmethod - @tokenparser - def parse(tokens): - disallow_keywords(tokens) - return VMIdent(tokens[0]) - - def __repr__(self): - return "" % (self.name,) - - -class VMVariable(VMRef): - def __init__(self, name): - VMRef.__init__(self) - self.name = name - - def ref(self): - return [StackLiteral(str(self.name))] - - def bytecode(self): - return codejoin(self.ref(), GetVariable()) - - @staticmethod - @tokenparser - def parse(tokens): - disallow_keywords(tokens) - return VMVariable(tokens[0]) - - def __repr__(self): - return "" % (self.name,) - -class VMFileRef(VMRef): - def __init__(self, obj, name): - VMRef.__init__(self) - self.obj = obj - self.name = name - - @staticmethod - @tokenparser - def parse(tokens): - assert tokens[1] == "!" - return VMFileRef(tokens[0], tokens[2]) - #return codejoin(tokens[0], StackLiteral(tokens[2]), GetProperty()) - - def ref(self): - return [self.obj, self.name] - - def __repr__(self): - return "" % (self.obj, self.name) - - def bytecode(self): - return codejoin(self.ref(), GetFile()) - -class VMPropRef(VMRef): - def __init__(self, obj, prop): - VMRef.__init__(self) - self.obj = obj - self.prop = prop - - @staticmethod - @tokenparser - def parse(tokens): - assert tokens[1] == "." - return VMPropRef(tokens[0], tokens[2]) - #return codejoin(tokens[0], StackLiteral(tokens[2]), GetProperty()) - - def ref(self): - return [self.obj, self.prop] - - def __repr__(self): - return "" % (self.obj, self.prop) - - def bytecode(self): - return codejoin(self.ref(), GetProperty()) - -class VMCoreRef(VMPropRef): - @staticmethod - @tokenparser - def parse(tokens): - return VMPropRef(VMObjRef(0), tokens[1]) - +from language_tools import * +from pyparsing import ParseException +from bytecode import * + +def disallow_keywords(tokens,keywords=None): + if keywords == None: + keywords = disallow_keywords.keywords + else: + keywords = set(keywords) + + for t in tokens: + if isinstance(t, VMIdent): + if t.name in keywords: + raise ParseException("Restricted keyword: %s" % (t.name,)) + elif isinstance(t, str): + tstr = t.encode('ascii', 'ignore') + if tstr in keywords: + raise ParseException("Restricted keyword: %s" % (tstr,)) + elif isinstance(t, str): + if t in keywords: + raise ParseException("Restricted keyword: %s" % (t,)) + +disallow_keywords.keywords = set('if,elseif,else,endif,try,except,finally,endtry,while,endwhile,continue,break,for,foreach,endfor'.split(',')) + + +class ObjRef(object): + def __init__(self, objnum): + self.objnum = objnum + + def __eq__(self, other): + return self.objnum == other.objnum + + + + +class VMType(VMBaseObject): + def bytecode(self): + return [StackLiteral(self)] + +class VMInteger(VMType): + def __init__(self, value): + VMType.__init__(self) + self.value = int(value) + + @staticmethod + @tokenparser + def parse(tokens): + return StackLiteral(VMInteger(tokens[0])) + + def __repr__(self): + return "%s" % (self.value,) + +class VMFloat(VMType): + def __init__(self, value): + VMType.__init__(self) + self.value = float(value) + + @staticmethod + @tokenparser + def parse(tokens): + return StackLiteral(VMFloat(tokens[0])) + + def __repr__(self): + return "%s" % (self.value,) + + +class VMTable(VMType): + def __init__(self, value): + VMType.__init__(self) + self.value = dict(value) + + @staticmethod + @tokenparser + def parse(tokens): + return StackLiteral(VMTable(tokens[0])) + +class VMList(VMType): + def __init__(self, value): + VMType.__init__(self) + self.value = list(value) + + @staticmethod + @tokenparser + def parse(tokens): + return StackLiteral(VMList()) + +class VMTablePair(VMType): + def __init__(self, value): + VMType.__init__(self) + self.key = key + self.value = value + + @staticmethod + @tokenparser + def parse(tokens): + return StackLiteral(VMList()) + +class VMString(VMType): + def __init__(self, value): + VMType.__init__(self) + if isinstance(value, str): + self.value = value + else: + self.value = str(value, 'ascii', 'ignore') + + def __repr__(self): + return "\"%s\"" % (repr(self.value)[1:].strip("'").replace("\\'", "'").replace('"', '\\"'),) + + @staticmethod + @tokenparser + def parse(tokens): + return StackLiteral(VMString(tokens[0])) + +class VMObjRef(VMType): + def __init__(self, value): + VMType.__init__(self) + if isinstance(value, ObjRef): + self.value = value + elif isinstance(value, (float, int)): + self.value = int(value) + else: + raise TypeError("Attempted to create VMObjRef with invalid object reference: %r" % (value,)) + + @staticmethod + @tokenparser + def parse(tokens): + return StackLiteral(VMObjRef(int(tokens[1]))) + + def __repr__(self): + return "#%s" % (self.value,) + +class VMRef(VMBaseObject): + pass + +class VMIdent(VMRef): + def __init__(self, name): + VMRef.__init__(self) + self.name = name + + def bytecode(self): + return [StackLiteral(str(self.name))] + + @staticmethod + @tokenparser + def parse(tokens): + disallow_keywords(tokens) + return VMIdent(tokens[0]) + + def __repr__(self): + return "" % (self.name,) + + +class VMVariable(VMRef): + def __init__(self, name): + VMRef.__init__(self) + self.name = name + + def ref(self): + return [StackLiteral(str(self.name))] + + def bytecode(self): + return codejoin(self.ref(), GetVariable()) + + @staticmethod + @tokenparser + def parse(tokens): + disallow_keywords(tokens) + return VMVariable(tokens[0]) + + def __repr__(self): + return "" % (self.name,) + +class VMFileRef(VMRef): + def __init__(self, obj, name): + VMRef.__init__(self) + self.obj = obj + self.name = name + + @staticmethod + @tokenparser + def parse(tokens): + assert tokens[1] == "!" + return VMFileRef(tokens[0], tokens[2]) + #return codejoin(tokens[0], StackLiteral(tokens[2]), GetProperty()) + + def ref(self): + return [self.obj, self.name] + + def __repr__(self): + return "" % (self.obj, self.name) + + def bytecode(self): + return codejoin(self.ref(), GetFile()) + +class VMPropRef(VMRef): + def __init__(self, obj, prop): + VMRef.__init__(self) + self.obj = obj + self.prop = prop + + @staticmethod + @tokenparser + def parse(tokens): + assert tokens[1] == "." + return VMPropRef(tokens[0], tokens[2]) + #return codejoin(tokens[0], StackLiteral(tokens[2]), GetProperty()) + + def ref(self): + return [self.obj, self.prop] + + def __repr__(self): + return "" % (self.obj, self.prop) + + def bytecode(self): + return codejoin(self.ref(), GetProperty()) + +class VMCoreRef(VMPropRef): + @staticmethod + @tokenparser + def parse(tokens): + return VMPropRef(VMObjRef(0), tokens[1]) + diff --git a/optimizer.py b/optimizer.py index f695a40..8a454ec 100755 --- a/optimizer.py +++ b/optimizer.py @@ -30,7 +30,7 @@ def bytecode_flatten(l, ltypes=(list, tuple, ParseResults)): if broken: continue assert not isinstance(l[i], ltypes) - assert not isinstance(l[i], (str, unicode, dict)) + assert not isinstance(l[i], (str, bytes, dict)) bc = l[i].bytecode() if len(bc) > 1 or bc[0] != l[i]: l[i:i+1] = bc @@ -51,4 +51,4 @@ def optimize(data): print("Missing position on element %s" % (x,)) return data - \ No newline at end of file + diff --git a/pbkdf2.py b/pbkdf2.py index 4c75d8b..1e480e8 100644 --- a/pbkdf2.py +++ b/pbkdf2.py @@ -1,134 +1,134 @@ -# -*- coding: utf-8 -*- -""" - pbkdf2 - ~~~~~~ - - This module implements pbkdf2 for Python. It also has some basic - tests that ensure that it works. The implementation is straightforward - and uses stdlib only stuff and can be easily be copy/pasted into - your favourite application. - - Use this as replacement for bcrypt that does not need a c implementation - of a modified blowfish crypto algo. - - Example usage: - - >>> pbkdf2_hex('what i want to hash', 'the random salt') - 'fa7cc8a2b0a932f8e6ea42f9787e9d36e592e0c222ada6a9' - - How to use this: - - 1. Use a constant time string compare function to compare the stored hash - with the one you're generating:: - - def safe_str_cmp(a, b): - if len(a) != len(b): - return False - rv = 0 - for x, y in izip(a, b): - rv |= ord(x) ^ ord(y) - return rv == 0 - - 2. Use `os.urandom` to generate a proper salt of at least 8 byte. - Use a unique salt per hashed password. - - 3. Store ``algorithm$salt:costfactor$hash`` in the database so that - you can upgrade later easily to a different algorithm if you need - one. For instance ``PBKDF2-256$thesalt:10000$deadbeef...``. - - - :copyright: (c) Copyright 2011 by Armin Ronacher. - :license: BSD, see LICENSE for more details. -""" -import hmac -import hashlib -from struct import Struct -from operator import xor -from itertools import starmap -import binascii - - -_pack_int = Struct('>I').pack - - -def pbkdf2_hex(data, salt, iterations=1000, keylen=24, hashfunc=None): - """Like :func:`pbkdf2_bin` but returns a hex encoded string.""" - return str(binascii.hexlify(pbkdf2_bin(data, salt, iterations, keylen, hashfunc)), 'ascii') - - -def pbkdf2_bin(data, salt, iterations=1000, keylen=24, hashfunc=None): - """Returns a binary digest for the PBKDF2 hash algorithm of `data` - with the given `salt`. It iterates `iterations` time and produces a - key of `keylen` bytes. By default SHA-256 is used as hash function, - a different hashlib `hashfunc` can be provided. - """ - - bchr = lambda v: bytes((v,)) - - hashfunc = hashfunc or hashlib.sha256 - mac = hmac.new(data, None, hashfunc) - def _pseudorandom(x, mac=mac): - h = mac.copy() - h.update(x) - return h.digest() - buf = [] - for block in range(1, -(-keylen // mac.digest_size) + 1): - rv = u = _pseudorandom(salt + _pack_int(block)) - for i in range(iterations - 1): - u = _pseudorandom(b''.join(map(bchr, u))) - rv = starmap(xor, zip(rv, u)) - buf.extend(rv) - return b''.join(map(bchr, buf))[:keylen] - - -def test(): - failed = [] - def check(data, salt, iterations, keylen, expected): - rv = pbkdf2_hex(bytes(data, "utf-8"), bytes(salt, "utf-8"), iterations, keylen, hashlib.sha1) - if rv != expected: - print('Test failed:') - print(' Expected: %s' % expected) - print(' Got: %s' % rv) - print(' Parameters:') - print(' data=%s' % data) - print(' salt=%s' % salt) - print(' iterations=%d' % iterations) - print - failed.append(1) - - # From RFC 6070 - check('password', 'salt', 1, 20, - '0c60c80f961f0e71f3a9b524af6012062fe037a6') - check('password', 'salt', 2, 20, - 'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957') - check('password', 'salt', 4096, 20, - '4b007901b765489abead49d926f721d065a429c1') - check('passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', - 4096, 25, '3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038') - check('pass\x00word', 'sa\x00lt', 4096, 16, - '56fa6aa75548099dcc37d7f03425e0c3') - # This one is from the RFC but it just takes for ages - ##check('password', 'salt', 16777216, 20, - ## 'eefe3d61cd4da4e4e9945b3d6ba2158c2634e984') - - # From Crypt-PBKDF2 - check('password', 'ATHENA.MIT.EDUraeburn', 1, 16, - 'cdedb5281bb2f801565a1122b2563515') - check('password', 'ATHENA.MIT.EDUraeburn', 1, 32, - 'cdedb5281bb2f801565a1122b25635150ad1f7a04bb9f3a333ecc0e2e1f70837') - check('password', 'ATHENA.MIT.EDUraeburn', 2, 16, - '01dbee7f4a9e243e988b62c73cda935d') - check('password', 'ATHENA.MIT.EDUraeburn', 2, 32, - '01dbee7f4a9e243e988b62c73cda935da05378b93244ec8f48a99e61ad799d86') - check('password', 'ATHENA.MIT.EDUraeburn', 1200, 32, - '5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13') - check('X' * 64, 'pass phrase equals block size', 1200, 32, - '139c30c0966bc32ba55fdbf212530ac9c5ec59f1a452f5cc9ad940fea0598ed1') - check('X' * 65, 'pass phrase exceeds block size', 1200, 32, - '9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a') - - raise SystemExit(bool(failed)) - - -if __name__ == '__main__': - test() +# -*- coding: utf-8 -*- +""" + pbkdf2 + ~~~~~~ + + This module implements pbkdf2 for Python. It also has some basic + tests that ensure that it works. The implementation is straightforward + and uses stdlib only stuff and can be easily be copy/pasted into + your favourite application. + + Use this as replacement for bcrypt that does not need a c implementation + of a modified blowfish crypto algo. + + Example usage: + + >>> pbkdf2_hex('what i want to hash', 'the random salt') + 'fa7cc8a2b0a932f8e6ea42f9787e9d36e592e0c222ada6a9' + + How to use this: + + 1. Use a constant time string compare function to compare the stored hash + with the one you're generating:: + + def safe_str_cmp(a, b): + if len(a) != len(b): + return False + rv = 0 + for x, y in izip(a, b): + rv |= ord(x) ^ ord(y) + return rv == 0 + + 2. Use `os.urandom` to generate a proper salt of at least 8 byte. + Use a unique salt per hashed password. + + 3. Store ``algorithm$salt:costfactor$hash`` in the database so that + you can upgrade later easily to a different algorithm if you need + one. For instance ``PBKDF2-256$thesalt:10000$deadbeef...``. + + + :copyright: (c) Copyright 2011 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" +import hmac +import hashlib +from struct import Struct +from operator import xor +from itertools import starmap +import binascii + + +_pack_int = Struct('>I').pack + + +def pbkdf2_hex(data, salt, iterations=1000, keylen=24, hashfunc=None): + """Like :func:`pbkdf2_bin` but returns a hex encoded string.""" + return str(binascii.hexlify(pbkdf2_bin(data, salt, iterations, keylen, hashfunc)), 'ascii') + + +def pbkdf2_bin(data, salt, iterations=1000, keylen=24, hashfunc=None): + """Returns a binary digest for the PBKDF2 hash algorithm of `data` + with the given `salt`. It iterates `iterations` time and produces a + key of `keylen` bytes. By default SHA-256 is used as hash function, + a different hashlib `hashfunc` can be provided. + """ + + bchr = lambda v: bytes((v,)) + + hashfunc = hashfunc or hashlib.sha256 + mac = hmac.new(data, None, hashfunc) + def _pseudorandom(x, mac=mac): + h = mac.copy() + h.update(x) + return h.digest() + buf = [] + for block in range(1, -(-keylen // mac.digest_size) + 1): + rv = u = _pseudorandom(salt + _pack_int(block)) + for i in range(iterations - 1): + u = _pseudorandom(b''.join(map(bchr, u))) + rv = starmap(xor, zip(rv, u)) + buf.extend(rv) + return b''.join(map(bchr, buf))[:keylen] + + +def test(): + failed = [] + def check(data, salt, iterations, keylen, expected): + rv = pbkdf2_hex(bytes(data, "utf-8"), bytes(salt, "utf-8"), iterations, keylen, hashlib.sha1) + if rv != expected: + print('Test failed:') + print(' Expected: %s' % expected) + print(' Got: %s' % rv) + print(' Parameters:') + print(' data=%s' % data) + print(' salt=%s' % salt) + print(' iterations=%d' % iterations) + print + failed.append(1) + + # From RFC 6070 + check('password', 'salt', 1, 20, + '0c60c80f961f0e71f3a9b524af6012062fe037a6') + check('password', 'salt', 2, 20, + 'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957') + check('password', 'salt', 4096, 20, + '4b007901b765489abead49d926f721d065a429c1') + check('passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', + 4096, 25, '3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038') + check('pass\x00word', 'sa\x00lt', 4096, 16, + '56fa6aa75548099dcc37d7f03425e0c3') + # This one is from the RFC but it just takes for ages + ##check('password', 'salt', 16777216, 20, + ## 'eefe3d61cd4da4e4e9945b3d6ba2158c2634e984') + + # From Crypt-PBKDF2 + check('password', 'ATHENA.MIT.EDUraeburn', 1, 16, + 'cdedb5281bb2f801565a1122b2563515') + check('password', 'ATHENA.MIT.EDUraeburn', 1, 32, + 'cdedb5281bb2f801565a1122b25635150ad1f7a04bb9f3a333ecc0e2e1f70837') + check('password', 'ATHENA.MIT.EDUraeburn', 2, 16, + '01dbee7f4a9e243e988b62c73cda935d') + check('password', 'ATHENA.MIT.EDUraeburn', 2, 32, + '01dbee7f4a9e243e988b62c73cda935da05378b93244ec8f48a99e61ad799d86') + check('password', 'ATHENA.MIT.EDUraeburn', 1200, 32, + '5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13') + check('X' * 64, 'pass phrase equals block size', 1200, 32, + '139c30c0966bc32ba55fdbf212530ac9c5ec59f1a452f5cc9ad940fea0598ed1') + check('X' * 65, 'pass phrase exceeds block size', 1200, 32, + '9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a') + + raise SystemExit(bool(failed)) + + +if __name__ == '__main__': + test() diff --git a/pyenum.py b/pyenum.py index e86af3d..ecb91dc 100644 --- a/pyenum.py +++ b/pyenum.py @@ -1,17 +1,17 @@ -class pyenum(object): - def __setattr__(self, name, val): - global enum_reversals - - object.__setattr__(self, name, val) - if not self in enum_reversals: - enum_reversals[self] = {} - enum_reversals[self][val] = name - -enum_reversals = {} - -def reverse_enum(e, v): - global enum_reversals - - if e in enum_reversals: - return enum_reversals[e][v] +class pyenum(object): + def __setattr__(self, name, val): + global enum_reversals + + object.__setattr__(self, name, val) + if not self in enum_reversals: + enum_reversals[self] = {} + enum_reversals[self][val] = name + +enum_reversals = {} + +def reverse_enum(e, v): + global enum_reversals + + if e in enum_reversals: + return enum_reversals[e][v] return None \ No newline at end of file diff --git a/virtualmachine.py b/virtualmachine.py index f075432..6f36489 100755 --- a/virtualmachine.py +++ b/virtualmachine.py @@ -111,11 +111,11 @@ class VirtualMachine(object): self.task.exc_stack.append(exc) def pop(self, count=1): - stack = [uncoerce(self.task.stack.pop()) for x in xrange(count)] + stack = [uncoerce(self.task.stack.pop()) for x in range(count)] return [x for x in reversed(stack)] def pop_raw(self, count=1): - stack = [self.task.stack.pop() for x in xrange(count)] + stack = [self.task.stack.pop() for x in range(count)] return [x for x in reversed(stack)] def push(self, value): @@ -251,4 +251,4 @@ class VirtualMachine(object): static_vm = VirtualMachine(None) if __name__ == "__main__": - static_vm.test() \ No newline at end of file + static_vm.test()