コード例 #1
0
ファイル: calculator.py プロジェクト: eagleblitz/mathbot
def array_splice(array, start, end):
    if not isinstance(array, Array):
        raise EvaluationError('Cannot splice non-array')
    if not isinstance(start, int) or not isinstance(end, int):
        raise EvaluationError('Non-integer indexes passed to splice')
    # TODO: Make this efficient
    return Array(array.values[start:end])
コード例 #2
0
ファイル: calculator.py プロジェクト: eagleblitz/mathbot
    def call(self, arguments, interpereter):
        # TODO: setup scope
        if len(arguments) > 128:
            raise EvaluationError('No more than 128 \
arguments may be passed to a function at once.')
        if self.variadic:
            if len(arguments) < len(self.parameters) - 1:
                raise EvaluationError(
                    'Incorrect number of arguments for function.')
        else:
            if len(arguments) != len(self.parameters):
                raise EvaluationError(
                    'Incorrect number of arguments for function.')
        tp = tuple(arguments)
        if tp not in self.cache:
            if self.variadic:
                extra_arguments = arguments[len(self.parameters) - 1:]
                main_arguments = arguments[:len(self.parameters)]
                values = {
                    key: value
                    for key, value in zip(self.parameters[:-1], main_arguments)
                }
                values[self.parameters[-1]] = Array(extra_arguments)
                subscope = Scope(self.scope, values)
                self.cache[tp] = yield from ev(self.expression, subscope,
                                               interpereter)
            else:
                subscope = Scope(self.scope, {
                    key: value
                    for key, value in zip(self.parameters, arguments)
                })
                self.cache[tp] = yield from ev(self.expression, subscope,
                                               interpereter)
        return self.cache[tp]
コード例 #3
0
ファイル: calculator.py プロジェクト: eagleblitz/mathbot
def array_join(*items):
    if len(items) == 0:
        raise EvaluationError('Cannot join no arrays together.')
    result = []
    for i in items:
        if not isinstance(i, Array):
            raise EvaluationError('Cannot call join on non-array')
        result += i.values
    return Array(result)
コード例 #4
0
ファイル: calculator.py プロジェクト: eagleblitz/mathbot
def if_statement(*arguments):
    if len(arguments) < 3:
        raise EvaluationError('Too few arguments for if function. Requires 3.')
    if len(arguments) > 3:
        raise EvaluationError(
            'Too many arguments for if function. Requires 3.')
    condition, if_true, if_false = arguments
    if (yield from condition()):
        return (yield from if_true())
    return (yield from if_false())
コード例 #5
0
ファイル: interpereter.py プロジェクト: mxbi/mathbot
	async def inst_access_array_element(self):
		index = self.pop()
		array = self.pop()
		if not isinstance(array, (Array, Interval)):
			raise EvaluationError('Cannot access element of non-array object')
		if not isinstance(index, int):
			raise EvaluationError('Cannot access non-integer element of an array')
		if index < 0 or index >= len(array):
			raise EvaluationError('Attempted to access out-of-bounds element of an array')
		self.push(array(index))
コード例 #6
0
def make_range(start, end):
    start = int(start)
    end = int(end)
    if not isinstance(start, int):
        raise EvaluationError('Cannot create range on non-int')
    if not isinstance(end, int):
        raise EvaluationError('Cannot create range on non-int')
    if end < start:
        raise EvaluationError('Cannot create backwards ranges')
    return Interval(start, 1, end - start)
コード例 #7
0
async def protected_power(a, b):
	if a == 0 and b == 0:
		raise EvaluationError('Cannot raise 0 to the power of 0')
	sa = float(sympy.Abs(a))
	sb = float(sympy.Abs(b))
	if sa < 4000 and sb < 20:
		return a ** b
	try:
		return await calculator.crucible.run(_protected_power_crucible, (a, b), timeout=2)
	except asyncio.TimeoutError:
		raise EvaluationError('Operation timed out. Perhaps the values were too large?')
コード例 #8
0
ファイル: calculator.py プロジェクト: newey/mathbot
def m_choose(*args):
    if len(args) != 2:
        raise EvaluationError('choose function requires two arguments')
    n, k = args
    try:
        return calculator.operators.operator_division(
            calculator.operators.function_factorial(n),
            calculator.operators.operator_multiply(
                calculator.operators.function_factorial(k),
                calculator.operators.function_factorial(
                    calculator.operators.operator_subtract(n, k))))
    except:
        raise EvaluationError(
            'Cannot run choose function with arguments {} and {}', n, k)
コード例 #9
0
	def call_builtin_function(self, function, arguments, return_to):
		try:
			result = function(*arguments)
		except Exception:
			# arg = arguments if len(arguments)
			# pylint: disable=raising-format-tuple
			if not arguments:
				raise EvaluationError('Failed to call {} with no arguments.', function)
			elif len(arguments) == 1:
				raise EvaluationError('Failed to call {} on {}', function, arguments[0])
			else:
				raise EvaluationError('Failed to call {} on {}', function, arguments)
		except EvaluationError:
			raise
		self.push(result)
		self.bytes, self.place = return_to
コード例 #10
0
ファイル: calculator.py プロジェクト: eagleblitz/mathbot
 def call(self, arguments, interpereter):
     if len(arguments) != 1 or not isinstance(arguments[0], int) or not (
             0 <= arguments[0] < len(self.values)):
         raise EvaluationError(
             'Attempted to get non-existent value of array')
     return self.values[arguments[0]]
     yield
コード例 #11
0
ファイル: interpereter.py プロジェクト: Ytrog/mathbot
 async def inst_list_extract_rest(self):
     value = self.pop()
     if not isinstance(
             value,
         (calculator.functions.ListBase, calculator.functions.Array)):
         raise EvaluationError('Attempted to extract tail of non-list')
     self.push(value.rest)
コード例 #12
0
ファイル: interpereter.py プロジェクト: Ytrog/mathbot
    async def run_async(self,
                        segment=None,
                        tick_limit=None,
                        error_if_exhausted=False,
                        get_entire_stack=False,
                        assignment_protection_level=None,
                        assignment_auth_level=0):
        ''' Run some number of ticks.
			tick_limit         - The maximum number of ticks to run. If not specified there is no limit.
			error_if_exhausted - If True, an error will be thrown if execution is not finished in the
								 specified number of ticks.
			expect_complete    - Deprecated
		'''
        self.assignment_protection_level = assignment_protection_level
        self.assignment_auth_level = assignment_auth_level
        self.bytes = segment
        self.place = 0
        if tick_limit is None:
            while self.head != bytecode.I.END:
                await self.tick()
        else:
            while self.head != bytecode.I.END and tick_limit > 0:
                tick_limit -= 1
                await self.tick()
        if error_if_exhausted and tick_limit == 0:
            raise EvaluationError('Execution timed out (by tick count)')
        if get_entire_stack:
            return self.stack[1:]
        return self.top
コード例 #13
0
ファイル: calculator.py プロジェクト: eagleblitz/mathbot
 def internal(*x):
     try:
         return f(*x)
     except Exception:
         if len(x) == 0:
             raise EvaluationError(
                 'Can\'t run {} function with no arguments.'.format(name))
         elif len(x) == 1:
             formatted = format_value(x[0])
             raise EvaluationError(
                 'Can\'t run {} function on value {}'.format(
                     name, formatted))
         else:
             formatted = ', '.join(map(format_value, x))
             raise EvaluationError(
                 'Can\'t run {} function on values ({})'.format(
                     name, formatted))
コード例 #14
0
ファイル: interpereter.py プロジェクト: mxbi/mathbot
	async def call_function(self, function, arguments, return_to, disable_cache=False, macro_unprepped=False, do_tco=False):
		if isinstance(function, (BuiltinFunction, Array, Interval, SingularValue)):
			await self.call_builtin_function(function, arguments, return_to)
		elif isinstance(function, Function):
			inspector = FunctionInspector(self, function)
			need_to_call = True
			if not disable_cache:
				cache_key = tuple([function] + arguments)
				if not inspector.is_macro and cache_key in self.calling_cache:
					self.push(self.calling_cache[cache_key])
					self.bytes, self.place = return_to
					need_to_call = False
			if need_to_call:
				num_parameters = inspector.num_parameters
				if inspector.is_variadic:
					if len(arguments) < num_parameters - 1:
						raise EvaluationError('Not enough arguments for variadic function {}', function)
					main = arguments[:num_parameters - 1]
					extra = arguments[num_parameters - 1:]
					scope_array = main
					scope_array.append(Array(extra))
					new_scope = IndexedScope(function.scope, num_parameters, scope_array)
				else:
					if num_parameters != len(arguments):
						raise EvaluationError('Improper number of arguments for function {}', function)
					if num_parameters == 0:
						new_scope = function.scope
					elif inspector.is_macro and macro_unprepped:
						wrapped = tuple(map(SingularValue, arguments))
						new_scope = IndexedScope(function.scope, num_parameters, wrapped)
					else:
						new_scope = IndexedScope(function.scope, num_parameters, arguments)
				# Remember the current scope
				if not do_tco:
					self.push(return_to)
					self.push(self.current_scope)
					# For normal functions, the last thing that happens is that the result is
					# stored in a cache. Need the key in order to do that.
					self.push(None if disable_cache or inspector.is_macro else cache_key)
				# Enter the function
				self.current_scope = new_scope
				self.bytes = inspector.code_segment
				self.place = inspector.code_address
		else:
			raise EvaluationError('{} is not a function', function)
		self.place -= 1 # Negate the +1 after this
コード例 #15
0
ファイル: calculator.py プロジェクト: eagleblitz/mathbot
def switch_statement(*arguments):
    if len(arguments) % 2 == 0 or len(arguments) < 3:
        raise EvaluationError(
            'Invalid number of arguments for switch expression')
    for i in range(0, len(arguments) - 2, 2):
        if (yield from arguments[i]()):
            return (yield from arguments[i + 1]())
    return (yield from arguments[-1]())
コード例 #16
0
ファイル: calculator.py プロジェクト: eagleblitz/mathbot
 def __getitem__(self, key):
     try:
         return self.values[key]
     except KeyError:
         try:
             return self.previous[key]
         except TypeError:
             raise EvaluationError('Unknown name: {}'.format(key))
コード例 #17
0
ファイル: interpereter.py プロジェクト: mxbi/mathbot
	def reset(scope, index, depth, permission = 0, protection = None):
		while depth > 0:
			scope = scope.superscope
			depth -= 1
		if index < len(scope.slots):
			_, current_security = scope.slots[index]
			if current_security > permission:
				raise EvaluationError('Not permitted to perform this unassignment')
			scope.slots[index] = DataSlot(None, protection if protection is not None else current_security)
コード例 #18
0
ファイル: calculator.py プロジェクト: eagleblitz/mathbot
def rolldie(times, faces):
    if isinstance(times, float):
        times = int(times)
    if isinstance(faces, float):
        faces = int(faces)
    if not isinstance(times, int) or not isinstance(faces, int):
        raise EvaluationError('Cannot roll {} dice with {} faces'.format(
            format_value(times), format_value(faces)))
    if times < 1:
        return 0
    if times > 1000:
        raise EvaluationError('Cannot roll more than 1000 dice')
    if faces < 1:
        raise EvaluationError('Cannot roll die with less than one face')
    if isinstance(faces, float) and not faces.is_integer():
        raise EvaluationError(
            'Cannot roll die with fractional number of faces')
    return sum(random.randint(1, faces) for i in range(times))
コード例 #19
0
ファイル: calculator.py プロジェクト: eagleblitz/mathbot
    def __init__(self, values):
        # self.front = []
        self.back = values
        # self.has_ownership = True
        self.values = list(values)
        if len(values) > 128:
            raise EvaluationError(
                'Created an array with more than 128 elements. This limitation \
is in place while the feature is in the development.')
コード例 #20
0
ファイル: interpereter.py プロジェクト: mxbi/mathbot
	def set(scope, index, depth, value, permission = 0, protection = None):
		while depth > 0:
			scope = scope.superscope
			depth -= 1
		while len(scope.slots) <= index:
			scope.slots.append(DataSlot(None, 0))
		_, current_security = scope.slots[index]
		if current_security > permission:
			raise EvaluationError('Not permitted to perform this assignment')
		scope.slots[index] = DataSlot(value, protection if protection is not None else current_security)
コード例 #21
0
ファイル: interpereter.py プロジェクト: Ytrog/mathbot
async def protected_power(use_crucible, a, b):
    if use_crucible:
        try:
            return await calculator.crucible.run(_protected_power_crucible,
                                                 (a, b),
                                                 timeout=2)
        except asyncio.TimeoutError:
            raise EvaluationError(
                'Operation timed out. Perhaps the values were too large?')
    else:
        return _protected_power_crucible(a, b)
コード例 #22
0
ファイル: interpereter.py プロジェクト: mxbi/mathbot
		async def internal(self):
			right = self.pop()
			left = self.pop()
			try:
				result = bool(await comparator(left, right))
			except EvaluationError:
				raise
			except Exception:
				raise EvaluationError('Operation failed on {} and {}', left, right)
			self.stack[-1] = self.stack[-1] and result
			self.push(right)
コード例 #23
0
ファイル: interpereter.py プロジェクト: mxbi/mathbot
		async def internal(self):
			left = self.pop()
			right = self.pop()
			try:
				result = op(left, right)
				if is_coroutine:
					result = await result
				self.push(result)
			except EvaluationError:
				raise
			except Exception:
				raise EvaluationError('Operation failed on {} and {}', left, right)
コード例 #24
0
ファイル: calculator.py プロジェクト: eagleblitz/mathbot
 def step(self):
     # print(self.stack)
     generator, injector = self.stack[-1]
     try:
         new_thing = next(generator)
         # print(new_thing)
         if new_thing is not None:
             if len(self.stack) >= self.limit_stack_size:
                 raise EvaluationError('Stack overflow: too much recursion')
             self.stack.append(new_thing)
     except StopIteration as e:
         injector.append(e.value)
         self.stack.pop()
コード例 #25
0
ファイル: interpereter.py プロジェクト: mxbi/mathbot
	async def inst_unr_fac(self):
		''' Factorial operator '''
		try:
			original_value = self.pop()
			argument = original_value
			# Prevent a burning attack from happening
			if argument < -2000 or argument > 2000:
				argument = sympy.Number(float(argument))
			result = sympy.factorial(argument)
			if result == sympy.zoo or result == sympy.oo:
				raise TypeError
		except Exception:
			raise EvaluationError('Cannot run factorial function on {}', original_value)
		self.push(result)
コード例 #26
0
def array_expand(*arrays):
    for i in arrays:
        if not isinstance(i, (Array, ListBase)):
            raise EvaluationError(
                'Cannot expand something that\'s not an array or list')
    return Expanded(arrays)
コード例 #27
0
def array_length(val):
    if not isinstance(val, (Array, Interval, ListBase)):
        raise EvaluationError('Cannot get the length of non-array object')
    return len(val)
コード例 #28
0
def int_to_glyph(integer):
    if not isinstance(integer, (int, sympy.Integer)):
        raise EvaluationError('chr received non-integer')
    return Glyph(chr(int(integer)))
コード例 #29
0
def glyph_to_int(glyph):
    if not isinstance(glyph, Glyph):
        raise EvaluationError('ord received non-glyph')
    return sympy.Integer(ord(glyph.value))
コード例 #30
0
ファイル: calculator.py プロジェクト: eagleblitz/mathbot
def evaluate_step(p, scope, it):
    while True:
        node_type = p['#']
        if node_type == 'number':
            return convert_number(p['string'])
        elif node_type == 'bin_op':
            left = yield from evaluate_step(p['left'], scope, it)
            right = yield from evaluate_step(p['right'], scope, it)
            op = OPERATOR_DICT.get(p['operator'])
            assert op is not None
            return op(left, right)
        elif node_type == 'not':
            value = yield from evaluate_step(p['expression'], scope, it)
            return 0 if value else 1
        elif node_type == 'die':
            times = (yield from evaluate_step(p['times'], scope, it)) \
             if 'times' in p else 1
            faces = (yield from evaluate_step(p['faces'], scope, it))
            return rolldie(times, faces)
        elif node_type == 'udie':
            # THIS IS OLD
            faces = yield from evaluate_step(p['faces'], scope, it)
            return rolldie(1, faces)
        elif node_type == 'uminus':
            return -(yield from evaluate_step(p['value'], scope, it))
        elif node_type == 'function_call':
            function = yield from evaluate_step(p['function'], scope, it)
            if not isinstance(function, BaseFunction) and not isinstance(
                    function, Macro):
                raise EvaluationError('{} is not a function'.format(
                    format_value(function)))
            # Get the list of AST objects
            items = p.get('arguments', {'items': []})['items']
            args = []
            # print(items)
            for i in items:
                if isinstance(function, Macro):
                    args.append(wrap_ev(i, scope, it))
                else:
                    value = yield from evaluate_step(i, scope, it)
                    if isinstance(value, Expanded):
                        args += list(value)
                    else:
                        args.append(value)
            return (yield from function.call(args, it))
        elif node_type == 'word':
            name = p['string'].lower()
            return scope[name]
        elif node_type == 'factorial':
            return calculator.operators.function_factorial(
                (yield from evaluate_step(p['value'], scope, it)))
        elif node_type == 'assignment':
            name = p['variable']['string'].lower()
            value = yield from evaluate_step(p['value'], scope, it)
            scope[name] = value
            return value
        elif node_type == 'statement_list':
            yield from ev(p['statement'], scope, it)
            p = p['next']
        elif node_type == 'program':
            result = 0
            for i in p['items']:
                result = yield from ev(i, scope, it)
            return result
        elif node_type == 'function_definition':
            parameters = [
                i['string'].lower() for i in p['parameters']['items']
            ]
            function = Function(parameters, p['expression'], scope,
                                p['variadic'])
            if p['kind'] == '~>':
                function = Macro(function)
            return function
        elif node_type == 'comparison':
            previous = yield from evaluate_step(p['first'], scope, it)
            for i in p['rest']:
                op = i['operator']
                current = yield from evaluate_step(i['value'], scope, it)
                if not OPERATOR_DICT[op](previous, current):
                    return 0
                previous = current
            return 1
        elif node_type == 'output':
            result = yield from evaluate_step(p['expression'], scope, it)
            print(result)
            return result
        else:
            return None