summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimotej Lazar <timotej.lazar@araneo.org>2014-12-17 12:24:25 +0100
committerAleš Smodiš <aless@guru.si>2015-08-11 14:26:00 +0200
commit487b9a3cb6849a49189c56925cbd4ddd30c230bf (patch)
treece1d93962d368450d32f3848e071985b62f9b1c1
parentd83cb19082697bff407286be7b1085494a759c2d (diff)
Mark solution predicates as static after loading
This prevents incorrect student solutions from overwriting or adding to predicates in solution<n> modules.
-rw-r--r--prolog/engine.py15
1 files changed, 11 insertions, 4 deletions
diff --git a/prolog/engine.py b/prolog/engine.py
index 07489df..088948e 100644
--- a/prolog/engine.py
+++ b/prolog/engine.py
@@ -85,6 +85,7 @@ class PrologEngine(object):
'arg/3': PL_predicate(b'arg', 3, None),
'assertz/1': PL_predicate(b'assertz', 1, None),
'call_with_time_limit/2': PL_predicate(b'call_with_time_limit', 2, None),
+ 'compile_predicates/1': PL_predicate(b'compile_predicates', 1, None),
'consult/1': PL_predicate(b'consult', 1, None),
'functor/3': PL_predicate(b'functor', 3, None),
'message_to_string/2': PL_predicate(b'message_to_string', 2, None),
@@ -116,19 +117,25 @@ class PrologEngine(object):
# Loads the correct solution [code] to problem [pid].
# TODO handle library loading.
def load_solution(self, pid, code):
- fid = PL_open_foreign_frame()
module = 'solution{}'.format(pid)
+
+ fid = PL_open_foreign_frame()
+ predicates = set()
for rule in prolog.util.split(code):
self.call('assertz/1', [Term('{}:({})'.format(module, rule))])
+ predicates.add('{}:{}'.format(module, self.predicate_indicator(rule)))
+ self.call('compile_predicates/1', [Term([Term(p) for p in predicates])])
PL_discard_foreign_frame(fid)
# Import the correct solution for problem [pid] into module for user [uid].
def mark_solved(self, uid, pid):
- fid = PL_open_foreign_frame()
m_user = 'user{}'.format(uid)
m_solution = 'solution{}'.format(pid)
- return self.call('add_import_module/3', [Term(m_user), Term(m_solution), Term('end')])
+
+ fid = PL_open_foreign_frame()
+ result = self.call('add_import_module/3', [Term(m_user), Term(m_solution), Term('end')])
PL_discard_foreign_frame(fid)
+ return result
# Get up to [n] solutions to query [q]. If there are no solutions, return
# an empty list. Raise an exception on error (either from self.call, or due
@@ -206,7 +213,7 @@ class PrologEngine(object):
self.call('assertz/1', [Term('{}:({})'.format(m_user, rule))])
predicates.add(self.predicate_indicator(rule))
- for i, query in enumerate(queries):
+ for query in queries:
result = self.query(query, m_user)
correct &= (len(result) == 1 and result[0]['X'] == self.answers[(pid, query)])
except Exception as ex: