# -*- coding: utf-8 -*-
# $Id: Haskell.py 1634 2013-04-12 15:36:36Z amelung $
#
# Copyright (c) 2007-2011 Otto-von-Guericke-Universität Magdeburg
#
# This file is part of ECSpooler.
################################################################################
# Changelog #
################################################################################
#
# 16.04.2009, chbauman:
# substituted all occurences of '.hs' with srcFileSuffix
# 30.04.2009, chbauman:
# using replace instead of expensive re.sub operation in
# _preProcessCheckSyntax.
# replaced re.sub with replace whereever possible.
# local imports
# load Haskell function to do a simple test
try:
# load Haskell function to do a test which allows permutation of list elems
try:
# load Haskell function to do a test which allows tolerance
try:
WRAPPER_TEMPLATE = \
"""module Main where
import Model
import Student
${helpFunctions}
-- must be named 'haskell_backend_internal_equality_test'
${testFunction}
main = putStr(\"isEqual=\" ++ show(haskell_backend_internal_equality_test (o1) (o2)) ++ \";;expected=\" ++ show(o1) ++ \";;received=\" ++ show(o2))
where
o1 = Model.${testData}
o2 = Student.${testData}
"""
SYNTAX_TEMPLATE = \
"""module Main where
${SOURCE}
main = putStr(\"\")
"""
GENERIC_TEMPLATE = \
"""module %s where
%s
"""
# input schema
'modelSolution',
),
'helpFunctions',
),
'testData',
#accessor = # must return a list; default is one element per line
'A function call consists of the ' +
'function name (given in the exercise directives) ' +
'and test data as parameters of this funtion. '+
'Each function call must be written in a single line.',
),
))
# testSchema
'simple',
),
'permutation',
),
'tolerance',
),
))
#runhugsRegEx = 'Type checking\n?|Parsing\n?|[Parsing]*[Dependency analysis]*[Type checking]*[Compiling]*\x08 *'
RUNHUGS_RE = re.compile(r'Type checking\n?|Parsing\n?|[Parsing]*[Dependency analysis]*[Type checking]*[Compiling]*\x08 *')
"""
A backend for checking Haskell programs by comparing
student and model solution on given test data.
"""
"""
This constructor is needed to reset the logging environment.
"""
"""
Pre process student's submissions and syntax check wrapper code.
Override this method if you need to reformat the wrapper code or
the student's submission.
@param: test:
@param: src:
@return: source and module name if needed
"""
result = ''
#result = re.sub('\$\{SOURCE\}', src, test.syntax)
else:
return result, 'Student'
"""
@see: AbtractSimpleBackend._postProcessCheckSyntax
"""
# take care of hexadecimal Unicode escape sequences sent to stdout
# or stderr
# find line number in result
# set line number minus x lines and return
msg)
else:
return msg
"""
Post process interpreter messages. Override this method if you need
to remove or reformat messages.
@param: message:
"""
#result = re.sub('isEqual=', '', message)
return result
"""
Test a Haskell programs using balck box tests, e.g., compare results
of a model solution with results of a students' solution on same
test data.
@return: a BackendResult object with result code and value
"""
# test for available test specs
msg = 'No test specification selected.'
# test for defined repeat fields in the schema definition
assert repeatFields, 'No RepeatField found.'
# test for available test data
msg = 'No test data defined.'
# we have some test data -> lets start the evaluation
# get model solution and student's submission
"Semantic check requires valid 'model solution' (%s)" % model
"Semantic check requires valid 'student solution' (%s)" % submission
# define return values
# run selected test specifications
if not solved: break
# get the interpreter
# write model solution and students' solution to a file
# get wrapper code
# get values for all other input fields from schema which are
# available in the job data
#src = re.sub('\$\{%s\}' % field.getName(), repl, src)
# set test function
#src = re.sub('\$\{testFunction\}', test.test, src)
# run with all test data
for t in testdata:
# and now add repeatable data values
#wrapper = re.sub('\$\{%s\}' % repeatField.getName(), t, src)
# remove all remaining placeholders
# execute wrapper code in haskell interpreter
try:
# write module for wrapper
# execute
# remove all special characters written by runhugs
#result = re.sub(HaskellConf.runhugsRegEx, '', result)
except Exception, e:
msg = 'Internal error during semantic check: %s: %s' % \
# an error occured
# FIXME: os.EX_OK is available only for Macintosh and Unix!
result = "\nYour submission failed. Test " \
"case was: '%s' (%s)" \
"\n\n Received result: %s"\
# has the students' solution passed this test?
else:
#log.debug(result)
# TODO: i18n
feedback = "\nYour submission failed. Test " \
"case was: '%s' (%s)" \
feedback += '\n\n Expected result: %s\n ' \
'Received result: %s' \
break # means: end testing right now
# end inner for loop
#end out for loop
if solved :
# TODO: i18n
feedback = '\nYour submission passed all tests.'