43 lines
1.4 KiB
Racket
43 lines
1.4 KiB
Racket
; This will be used on the server to validate all source code by the participants before running it
|
|
; Allowed procedures and special-forms will vary with each challenge
|
|
|
|
#lang racket
|
|
|
|
(require "challenge.rkt")
|
|
(require "either.rkt")
|
|
|
|
(provide validate run)
|
|
|
|
(define (validate str allowed)
|
|
(call/cc
|
|
(lambda (c)
|
|
(call-with-exception-handler
|
|
(lambda (e)
|
|
(c (left (exn-message e))))
|
|
(lambda ()
|
|
(define expr (read (open-input-string str)))
|
|
(if (check-allowed expr allowed)
|
|
(right expr)
|
|
(left "Error: you used a procedure, special form or variable name that has been disabled.")))))))
|
|
|
|
(define (check-allowed expr allowed)
|
|
(if (pair? expr)
|
|
(andmap (lambda (x) (check-allowed x allowed)) expr)
|
|
(or (not (symbol? expr)) (member expr allowed))))
|
|
|
|
; Allowing for functions with multiple arguments is something I leave for the future generation to implement
|
|
; It should be quite trivial add
|
|
(define (run challenge code)
|
|
(call/cc
|
|
(lambda (c)
|
|
(call-with-exception-handler
|
|
(lambda (e)
|
|
(c (left (exn-message e))))
|
|
(lambda ()
|
|
(define input (challenge-input challenge))
|
|
(define func (eval code (make-base-namespace)))
|
|
(define res (map (lambda (in) (apply func (list in))) input))
|
|
(if (equal? res (challenge-output challenge))
|
|
(right "")
|
|
(left res)))))))
|