import operator import socket import prolog.engine from prolog.util import tokenize from server.hints import Hint, HintPopup id = 1 hint_type = { 'no_hint': Hint('no_hint'), 'program_already_correct': Hint('program_already_correct'), 'system_error': Hint('system_error'), 'test_results': Hint('test_results'), 'syntax_error': Hint('syntax_error'), 'monkey_main': Hint('monkey_main'), 'monkey_change': HintPopup('monkey_change', style='change'), 'monkey_insert': HintPopup('monkey_insert', style='insert'), 'monkey_remove': HintPopup('monkey_remove', style='remove'), 'monkey_highlight': HintPopup('monkey_highlight', style='highlight'), 'monkey_buggy_literal': Hint('monkey_buggy_literal'), 'monkey_buggy_variable': Hint('monkey_buggy_variable'), 'monkey_singleton': Hint('monkey_singleton'), 'monkey_missing': Hint('monkey_missing'), 'monkey_unknown': Hint('monkey_unknown'), 'noncapitalised_variable': Hint('noncapitalised_variable'), 'noncapitalised_variable_markup': HintPopup('noncapitalised_variable_markup'), 'fail_rule': HintPopup('fail_rule'), } # Check program for syntax errors. def check_syntax(code, aux_code): engine_id = None try: engine_id, output = prolog.engine.create(code=code+aux_code, timeout=1.0) if 'error' in map(operator.itemgetter(0), output): errors_msg = '\n'.join(['{}: {}'.format(m_type, m_text) for m_type, m_text in output]) return [{'id': 'syntax_error', 'args': {'messages': errors_msg}}] except socket.timeout as ex: # TODO check if a timeout can actually happen here pass finally: if engine_id is not None: prolog.engine.destroy(engine_id) return [] def hint(code, aux_code): tokens = tokenize(code) hints = [] # rules like a(X) :- fail. for i, t in enumerate(tokens[:-2]): t1 = tokens[i+1] t2 = tokens[i+2] if t.val == ':-' and t1.val in ('fail', 'false') and t2.val == '.': hints += [{'id': 'fail_rule', 'start': t.pos, 'end': t2.pos + len(t2.val)}] return hints