;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -*- Mode: Lisp -*- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; File - defex-user.lisp
;; Description -
;; Author - Tim Bradshaw (tfb at lostwithiel)
;; Created On - Wed Feb 2 13:18:19 2000
;; Last Modified On - Mon Jul 9 08:04:40 2001
;; Last Modified By - Gail Anderson (ga at lostwithiel)
;; Update Count - 73
;; Status - Unknown
;;
;; $Id: defex-user.lisp,v 1.1 2003/01/09 02:11:34 colin Exp $
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User part of DEFINE-EXERCISE, does not do much.
;;; this should be edited to reference whatever package the student's
;;; solution should be defined and run in
(in-package :exercise)
;;; used to store details about the current student submission
(defparameter *current-submission* nil)
;;; hash table containing details about all the student submissions
(defparameter *submissions* (make-hash-table :test #'equalp))
;;; the marker can edit the call to define-exercise in the student's
;;; submission to note whether the file loaded into
;;; Lisp OK, whether it compiled OK, and to add comments about the
;;; result of loading, compiling, or general comments.
(defmacro define-exercise (name &key
;; name of student/author
author
;; login name of student author
;; (used to name submission)
login-name
;; list of all symbols for which student
;; has submitted a definition
defined-symbols
;; list of symbols for which student has
;; submitted a non-working, partial
;; definition (subset of DEFINED-SYMBOLS)
nonworking-symbols
;; list of symbols for which student has
;; tried to define, but which are submitted
;; as comments because they don't compile
commented-symbols
;; any comments which the student wishes to
;; make about the submission
commentary
;; for marker's use: whether an error
;; occurred on loading the file
load-error
;; for marker's use: comments about cause
;; of load errors, etc
load-comment
;; for marker's use: whether an error occurred
;; on compiling the file
compile-error
;; for marker's use: comments about cause of
;; compile errors, etc
compile-comment
;; for marker's use: any other
;; comments about the submission
other-comments)
"Define an exercise"
;;; calls a function do-define-exercise to do the work
`(do-define-exercise ',name ; name of the exercise (e.g. :ex1)
:author ',author
:login-name ',login-name
:defined-symbols ',defined-symbols
:nonworking-symbols ',nonworking-symbols
:commented-symbols ',commented-symbols
:commentary ',commentary
:load-error ',load-error
:load-comment ',load-comment
:compile-error ',compile-error
:compile-comment ',compile-comment
:other-comments ',other-comments))
;;; Structure to store information about the submission
;;; Information supplied by do-define-exercise; entered either by the
;;; student, or by the marker.
(defstruct exercise
author
login-name
defined-symbols
nonworking-symbols
commented-symbols
(commentary "")
(load-error nil)
(load-comment "")
(compile-error nil)
(compile-comment "")
(other-comments "")
(tests nil))
;;; The guts of define-exercise
(defun do-define-exercise (name &rest args
&key
author
login-name
defined-symbols
nonworking-symbols
commented-symbols
commentary
load-error
load-comment
compile-error
compile-comment
other-comments)
;; syntax checks
(assert (typep name 'symbol)
(name)
"exercise name, ~S must be a symbol" name)
(assert (first *exercise*)
(name)
"exercise name ~S is not a legal name, should be a member of ~S"
name *exercise*)
(assert (typep author 'string)
(author)
"author ~S is not a string" author)
(assert (typep login-name 'string)
(login-name)
"login name ~S is not a string" login-name)
(assert (typep defined-symbols 'list)
(defined-symbols)
"The `list of defined symbols' ~S is not a list!" defined-symbols)
(assert (every #'symbolp defined-symbols)
(defined-symbols)
"Not every element of the `list of defined symbols' ~S is a symbol!"
defined-symbols)
(assert (typep nonworking-symbols 'list)
(nonworking-symbols)
"The `list of nonworking symbols' ~S is not a list!" nonworking-symbols)
(assert (every #'symbolp nonworking-symbols)
(nonworking-symbols)
"Not every element of the `list of nonworking symbols' ~S is a symbol!"
nonworking-symbols)
(assert (typep commented-symbols 'list)
(commented-symbols)
"The `list of commented symbols' ~S is not a list!" commented-symbols)
(assert (every #'symbolp commented-symbols)
(commented-symbols)
"Not every element of the `list of commented symbols' ~S is a symbol!"
commented-symbols)
(assert (typep commentary 'string)
(commentary)
"The commentary ~S should be a string, if provided" commentary)
(assert (typep load-error 'boolean)
(load-error)
"The value of load-error should be T or NIL.")
(assert (typep load-comment 'string)
(load-comment)
"login name ~S is not a string" load-comment)
(assert (typep compile-error 'boolean)
(compile-error)
"The value of compile-error should be T or NIL.")
(assert (typep compile-comment 'string)
(compile-comment)
"login name ~S is not a string" compile-comment)
(assert (typep other-comments 'string)
(other-comments)
"login name ~S is not a string" other-comments)
;; create a new submission for this student's exercise, and add it to
;; the list of all submissions
(setf (gethash login-name *submissions*)
(make-exercise
:author author
:login-name login-name
:defined-symbols defined-symbols
:nonworking-symbols nonworking-symbols
:commented-symbols commented-symbols))
;; remember this as the current submission
(setf *current-submission*
(gethash login-name *submissions*))
;; store the marking information in the submission
(setf (exercise-load-error *current-submission*)
load-error)
(setf (exercise-load-comment *current-submission*)
load-comment)
(setf (exercise-compile-error *current-submission*)
compile-error)
(setf (exercise-compile-comment *current-submission*)
compile-comment)
(setf (exercise-other-comments *current-submission*)
other-comments))
;;; undefine all student symbols; should be provided to the students if
;;; appropriate
(defun clean-student-symbols ()
"Make all the names you are meant to define have no definitions.
You can run this function after loading the compiled one, but before
loading your version to make sure you have not missed anything.
Returns a list of the symbols it has undefined."
(dolist (s (second *exercise*) (second *exercise*))
(makunbound s)
(fmakunbound s)))