; 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)))))))