Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --- ac.scm 2012-01-09 11:22:45.232049658 +0100
- +++ ac.scm.old 2012-01-10 18:16:11.695306289 +0100
- @@ -9,44 +9,18 @@
- (require (lib "foreign.ss"))
- (unsafe!)
- -(define main-namespace (current-namespace))
- -
- -(define (ac-global-name s)
- - (string->symbol (string-append "_" (symbol->string s))))
- -
- -(define-syntax defarc
- - (syntax-rules ()
- - ((defarc (name . args) body ...)
- - (defarc name (name . args) body ...))
- - ((defarc arc-name (scheme-name . args) body ...)
- - (begin
- - (xdef arc-name (lambda args body ...))
- - (defarc arc-name scheme-name)))
- - ((defarc arc-name scheme-name)
- - (define (scheme-name . args)
- -
- - ; The following 'parameterize has been added. See the note at
- - ; 'arc-exec, below.
- - ;
- - (apply (parameterize ((current-namespace main-namespace))
- - (namespace-variable-value (ac-global-name 'arc-name)))
- - args)))
- - ((defarc name)
- - (defarc name name))))
- -
- ; compile an Arc expression into a Scheme expression,
- ; both represented as s-expressions.
- ; env is a list of lexically bound variables, which we
- ; need in order to decide whether set should create a global.
- -(defarc (ac s env)
- +(define (ac s env)
- (cond ((string? s) (ac-string s env))
- ((literal? s) s)
- ((eqv? s 'nil) (list 'quote 'nil))
- ((ssyntax? s) (ac (expand-ssyntax s) env))
- ((symbol? s) (ac-var-ref s env))
- ((ssyntax? (xcar s)) (ac (cons (expand-ssyntax (car s)) (cdr s)) env))
- - ((eq? (xcar s) '$) (ac-$ (cadr s) env))
- ((eq? (xcar s) 'quote) (list 'quote (ac-niltree (cadr s))))
- ((eq? (xcar s) 'quasiquote) (ac-qq (cadr s) env))
- ((eq? (xcar s) 'if) (ac-if (cdr s) env))
- @@ -56,14 +30,16 @@
- ; ... except that they work for macros (so prob should do this for
- ; every elt of s, not just the car)
- ((eq? (xcar (xcar s)) 'compose) (ac (decompose (cdar s) (cdr s)) env))
- - ((eq? (xcar (xcar s)) 'complement)
- + ((eq? (xcar (xcar s)) 'complement)
- (ac (list 'no (cons (cadar s) (cdr s))) env))
- ((eq? (xcar (xcar s)) 'andf) (ac-andf s env))
- ((pair? s) (ac-call (car s) (cdr s) env))
- (#t (err "Bad object in expression" s))))
- +(define atstrings #f)
- +
- (define (ac-string s env)
- - (if (ar-bflag 'atstrings)
- + (if atstrings
- (if (atpos s 0)
- (ac (cons 'string (map (lambda (x)
- (if (string? x)
- @@ -74,7 +50,7 @@
- (unescape-ats s))
- (string-copy s))) ; avoid immutable strings
- -(defarc ac-literal (literal? x)
- +(define (literal? x)
- (or (boolean? x)
- (char? x)
- (string? x)
- @@ -90,9 +66,9 @@
- (define (has-ssyntax-char? string i)
- (and (>= i 0)
- (or (let ((c (string-ref string i)))
- - (or (eqv? c #\:) (eqv? c #\~)
- + (or (eqv? c #\:) (eqv? c #\~)
- (eqv? c #\&)
- - ;(eqv? c #\_)
- + ;(eqv? c #\_)
- (eqv? c #\.) (eqv? c #\!)))
- (has-ssyntax-char? string (- i 1)))))
- @@ -107,7 +83,7 @@
- ; leave this off and see how often it would have been useful.
- ; Might want to make ~ have less precedence than &, because
- -; ~foo&bar prob should mean (andf (complement foo) bar), not
- +; ~foo&bar prob should mean (andf (complement foo) bar), not
- ; (complement (andf foo bar)).
- (define (expand-ssyntax sym)
- @@ -126,9 +102,9 @@
- `(complement ,(chars->value (cdr tok))))
- (chars->value tok)))
- (tokens (lambda (c) (eqv? c #\:))
- - (symbol->chars sym)
- - '()
- - '()
- + (symbol->chars sym)
- + '()
- + '()
- #f))))
- (if (null? (cdr elts))
- (car elts)
- @@ -145,26 +121,26 @@
- (car elts)
- (cons 'andf elts))))
- -; How to include quoted arguments? Can't treat all as quoted, because
- -; never want to quote fn given as first. Do we want to allow quote chars
- -; within symbols? Could be ugly.
- +; How to include quoted arguments? Can't treat all as quoted, because
- +; never want to quote fn given as first. Do we want to allow quote chars
- +; within symbols? Could be ugly.
- ; If release, fix the fact that this simply uses v0... as vars. Should
- ; make these vars gensyms.
- (define (expand-curry sym)
- - (let ((expr (exc (map (lambda (x)
- + (let ((expr (exc (map (lambda (x)
- (if (pair? x) (chars->value x) x))
- - (tokens (lambda (c) (eqv? c #\_))
- - (symbol->chars sym)
- - '()
- - '()
- + (tokens (lambda (c) (eqv? c #\_))
- + (symbol->chars sym)
- + '()
- + '()
- #t))
- 0)))
- - (list 'fn
- - (keep (lambda (s)
- - (and (symbol? s)
- - (eqv? (string-ref (symbol->string s) 0)
- + (list 'fn
- + (keep (lambda (s)
- + (and (symbol? s)
- + (eqv? (string-ref (symbol->string s) 0)
- #\v)))
- expr)
- expr)))
- @@ -212,7 +188,7 @@
- (define (tokens test source token acc keepsep?)
- (cond ((null? source)
- - (reverse (if (pair? token)
- + (reverse (if (pair? token)
- (cons (reverse token) acc)
- acc)))
- ((test (car source))
- @@ -233,44 +209,36 @@
- acc
- keepsep?))))
- -(defarc (ac-defined-var? s)
- - #f)
- +(define (ac-global-name s)
- + (string->symbol (string-append "_" (symbol->string s))))
- (define (ac-var-ref s env)
- - (cond ((lex? s env) s)
- - ((ac-defined-var? s) (list (ac-global-name s)))
- - (#t (ac-global-name s))))
- -
- -; lowering into mzscheme, with (unquote <foo>) lifting us back into arc
- -
- -(define (ac-$ args env)
- - (ac-qqx args
- - (lambda (x) (ac x env))
- - (lambda (x) (error 'ac-$ "Can't use ,@ from within $ in: ~a" args))))
- + (if (lex? s env)
- + s
- + (ac-global-name s)))
- ; quasiquote
- (define (ac-qq args env)
- - (list 'quasiquote (ac-qqx args
- - (lambda (x) (list 'unquote (ac x env)))
- - (lambda (x) (list 'unquote-splicing
- - (list 'ar-nil-terminate (ac x env)))))))
- + (list 'quasiquote (ac-qq1 1 args env)))
- ; process the argument of a quasiquote. keep track of
- ; depth of nesting. handle unquote only at top level (level = 1).
- ; complete form, e.g. x or (fn x) or (unquote (fn x))
- -(define (ac-qqx x unq splice)
- - (cond
- - ((not (pair? x)) x)
- - ((eqv? (car x) 'unquote) (unq (cadr x)))
- - ((eqv? (car x) 'unquote-splicing) (splice (cadr x)))
- - ((eqv? (car x) 'quasiquote)
- - (list 'quasiquote
- - (ac-qqx (cadr x)
- - (lambda (e) (list 'unquote (ac-qqx e unq splice)))
- - (lambda (e) (list 'unquote-splicing (ac-qqx e unq splice))))))
- - (#t (imap (lambda (e) (ac-qqx e unq splice)) x))))
- +(define (ac-qq1 level x env)
- + (cond ((= level 0)
- + (ac x env))
- + ((and (pair? x) (eqv? (car x) 'unquote))
- + (list 'unquote (ac-qq1 (- level 1) (cadr x) env)))
- + ((and (pair? x) (eqv? (car x) 'unquote-splicing) (= level 1))
- + (list 'unquote-splicing
- + (list 'ar-nil-terminate (ac-qq1 (- level 1) (cadr x) env))))
- + ((and (pair? x) (eqv? (car x) 'quasiquote))
- + (list 'quasiquote (ac-qq1 (+ level 1) (cadr x) env)))
- + ((pair? x)
- + (imap (lambda (x) (ac-qq1 level x env)) x))
- + (#t x)))
- ; like map, but don't demand '()-terminated list
- @@ -332,7 +300,7 @@
- ; be missing.
- (define (ac-complex-fn args body env)
- - (let* ((ra (gensym))
- + (let* ((ra (ar-gensym))
- (z (ac-complex-args args env ra #t)))
- `(lambda ,ra
- (let* ,z
- @@ -350,11 +318,11 @@
- ((symbol? args) (list (list args ra)))
- ((pair? args)
- (let* ((x (if (and (pair? (car args)) (eqv? (caar args) 'o))
- - (ac-complex-opt (cadar args)
- + (ac-complex-opt (cadar args)
- (if (pair? (cddar args))
- - (caddar args)
- + (caddar args)
- 'nil)
- - env
- + env
- ra)
- (ac-complex-args
- (car args)
- @@ -431,13 +399,8 @@
- (cond ((eqv? a 'nil) (err "Can't rebind nil"))
- ((eqv? a 't) (err "Can't rebind t"))
- ((lex? a env) `(set! ,a zz))
- - ((ac-defined-var? a) `(,(ac-global-name a) zz))
- -
- - ; The following has been changed from
- - ; 'namespace-set-variable-value! to 'set!. See
- - ; the note at 'arc-exec, below.
- - ;
- - (#t `(set! ,(ac-global-name a) zz)))
- + (#t `(namespace-set-variable-value! ',(ac-global-name a)
- + zz)))
- 'zz))
- (err "First arg to set must be a symbol" a)))
- @@ -468,9 +431,9 @@
- (define (ac-global-call fn args env)
- (cond ((and (assoc fn ac-binaries) (= (length args) 2))
- `(,(cadr (assoc fn ac-binaries)) ,@(ac-args '() args env)))
- - (#t
- + (#t
- `(,(ac-global-name fn) ,@(ac-args '() args env)))))
- -
- +
- ; compile a function call
- ; special cases for speed, to avoid compiled output like
- ; (ar-apply _pr (list 1 2))
- @@ -480,23 +443,30 @@
- ; and it's bound to a function, generate (foo bar) instead of
- ; (ar-funcall1 foo bar)
- +(define direct-calls #f)
- +
- (define (ac-call fn args env)
- (let ((macfn (ac-macro? fn)))
- (cond (macfn
- (ac-mac-call macfn args env))
- ((and (pair? fn) (eqv? (car fn) 'fn))
- `(,(ac fn env) ,@(ac-args (cadr fn) args env)))
- - ((and (ar-bflag 'direct-calls) (symbol? fn) (not (lex? fn env)) (bound? fn)
- -
- - ; The following has been changed from using
- - ; 'namespace-variable-value to using 'arc-eval. See
- - ; the note at 'arc-exec, below.
- - ;
- - (procedure? (arc-eval fn)))
- + ((and direct-calls (symbol? fn) (not (lex? fn env)) (bound? fn)
- + (procedure? (namespace-variable-value (ac-global-name fn))))
- (ac-global-call fn args env))
- + ((= (length args) 0)
- + `(ar-funcall0 ,(ac fn env) ,@(map (lambda (x) (ac x env)) args)))
- + ((= (length args) 1)
- + `(ar-funcall1 ,(ac fn env) ,@(map (lambda (x) (ac x env)) args)))
- + ((= (length args) 2)
- + `(ar-funcall2 ,(ac fn env) ,@(map (lambda (x) (ac x env)) args)))
- + ((= (length args) 3)
- + `(ar-funcall3 ,(ac fn env) ,@(map (lambda (x) (ac x env)) args)))
- + ((= (length args) 4)
- + `(ar-funcall4 ,(ac fn env) ,@(map (lambda (x) (ac x env)) args)))
- (#t
- - `((ar-coerce ,(ac fn env) 'fn)
- - ,@(map (lambda (x) (ac x env)) args))))))
- + `(ar-apply ,(ac fn env)
- + (list ,@(map (lambda (x) (ac x env)) args)))))))
- (define (ac-mac-call m args env)
- (let ((x1 (apply m (map ac-niltree args))))
- @@ -507,12 +477,9 @@
- (define (ac-macro? fn)
- (if (symbol? fn)
- -
- - ; The following has been changed from using
- - ; 'namespace-variable-value to using 'bound? and 'arc-eval. See
- - ; the note at 'arc-exec, below.
- - ;
- - (let ((v (and (bound? fn) (arc-eval fn))))
- + (let ((v (namespace-variable-value (ac-global-name fn)
- + #t
- + (lambda () #f))))
- (if (and v
- (ar-tagged? v)
- (eq? (ar-type v) 'mac))
- @@ -541,11 +508,6 @@
- (define (ac-denil x)
- (cond ((pair? x) (cons (ac-denil-car (car x)) (ac-denil-cdr (cdr x))))
- - ((hash-table? x)
- - (let ((xc (make-hash-table 'equal)))
- - (hash-table-for-each x
- - (lambda (k v) (hash-table-put! xc (ac-denil k) (ac-denil v))))
- - xc))
- (#t x)))
- (define (ac-denil-car x)
- @@ -581,9 +543,9 @@
- ; need ar-nil-terminate).
- (define (ac-niltree x)
- - (cond ((pair? x) (cons (ac-niltree (car x)) (ac-niltree (cdr x))))
- - ((or (eq? x #f) (eq? x '()) (void? x)) 'nil)
- - (#t x)))
- + (cond ((pair? x) (cons (ac-niltree (car x)) (ac-niltree (cdr x))))
- + ((or (eq? x #f) (eq? x '())) 'nil)
- + (#t x)))
- ; The next two are optimizations, except work for macros.
- @@ -593,7 +555,7 @@
- (#t (list (car fns) (decompose (cdr fns) args)))))
- (define (ac-andf s env)
- - (ac (let ((gs (map (lambda (x) (gensym)) (cdr s))))
- + (ac (let ((gs (map (lambda (x) (ar-gensym)) (cdr s))))
- `((fn ,gs
- (and ,@(map (lambda (f) `(,f ,@gs))
- (cdar s))))
- @@ -636,7 +598,7 @@
- (if (or (eqv? x 'nil) (eqv? x '()))
- 'nil
- (car x)))
- -
- +
- (define (ar-xcdr x)
- (if (or (eqv? x 'nil) (eqv? x '()))
- 'nil
- @@ -659,23 +621,64 @@
- ; call a function or perform an array ref, hash ref, &c
- ; Non-fn constants in functional position are valuable real estate, so
- -; should figure out the best way to exploit it. What could (1 foo) or
- +; should figure out the best way to exploit it. What could (1 foo) or
- ; ('a foo) mean? Maybe it should mean currying.
- ; For now the way to make the default val of a hash table be other than
- ; nil is to supply the val when doing the lookup. Later may also let
- -; defaults be supplied as an arg to table. To implement this, need: an
- -; eq table within scheme mapping tables to defaults, and to adapt the
- -; code in arc.arc that reads and writes tables to read and write their
- -; default vals with them. To make compatible with existing written tables,
- +; defaults be supplied as an arg to table. To implement this, need: an
- +; eq table within scheme mapping tables to defaults, and to adapt the
- +; code in arc.arc that reads and writes tables to read and write their
- +; default vals with them. To make compatible with existing written tables,
- ; just use an atom or 3-elt list to keep the default.
- (define (ar-apply fn args)
- - (apply (ar-coerce fn 'fn) args))
- + (cond ((procedure? fn)
- + (apply fn args))
- + ((pair? fn)
- + (list-ref fn (car args)))
- + ((string? fn)
- + (string-ref fn (car args)))
- + ((hash-table? fn)
- + (ar-nill (hash-table-get fn
- + (car args)
- + (if (pair? (cdr args)) (cadr args) #f))))
- +; experiment: means e.g. [1] is a constant fn
- +; ((or (number? fn) (symbol? fn)) fn)
- +; another possibility: constant in functional pos means it gets
- +; passed to the first arg, i.e. ('kids item) means (item 'kids).
- + (#t (err "Function call on inappropriate object" fn args))))
- (xdef apply (lambda (fn . args)
- (ar-apply fn (ar-apply-args args))))
- +; special cases of ar-apply for speed and to avoid consing arg lists
- +
- +(define (ar-funcall0 fn)
- + (if (procedure? fn)
- + (fn)
- + (ar-apply fn (list))))
- +
- +(define (ar-funcall1 fn arg1)
- + (if (procedure? fn)
- + (fn arg1)
- + (ar-apply fn (list arg1))))
- +
- +(define (ar-funcall2 fn arg1 arg2)
- + (if (procedure? fn)
- + (fn arg1 arg2)
- + (ar-apply fn (list arg1 arg2))))
- +
- +(define (ar-funcall3 fn arg1 arg2 arg3)
- + (if (procedure? fn)
- + (fn arg1 arg2 arg3)
- + (ar-apply fn (list arg1 arg2 arg3))))
- +
- +(define (ar-funcall4 fn arg1 arg2 arg3 arg4)
- + (if (procedure? fn)
- + (fn arg1 arg2 arg3 arg4)
- + (ar-apply fn (list arg1 arg2 arg3 arg4))))
- +
- ; replace the nil at the end of a list with a '()
- (define (ar-nil-terminate l)
- @@ -719,7 +722,7 @@
- ; (pairwise pred '(a b c d)) =>
- ; (and (pred a b) (pred b c) (pred c d))
- ; pred returns t/nil, as does pairwise
- -; reduce?
- +; reduce?
- (define (pairwise pred lst)
- (cond ((null? lst) 't)
- @@ -748,21 +751,21 @@
- (xdef t 't)
- (define (all test seq)
- - (or (null? seq)
- + (or (null? seq)
- (and (test (car seq)) (all test (cdr seq)))))
- (define (arc-list? x) (or (pair? x) (eqv? x 'nil) (eqv? x '())))
- -
- +
- ; Generic +: strings, lists, numbers.
- ; Return val has same type as first argument.
- (xdef + (lambda args
- (cond ((null? args) 0)
- ((char-or-string? (car args))
- - (apply string-append
- + (apply string-append
- (map (lambda (a) (ar-coerce a 'string))
- args)))
- - ((arc-list? (car args))
- + ((arc-list? (car args))
- (ac-niltree (apply append (map ar-nil-terminate args))))
- (#t (apply + args)))))
- @@ -838,7 +841,6 @@
- ((tcp-listener? x) 'socket)
- ((exn? x) 'exception)
- ((thread? x) 'thread)
- - ((thread-cell? x) 'thread-cell)
- (#t (err "Type: unknown type" x))))
- (xdef type ar-type)
- @@ -849,14 +851,22 @@
- (xdef rep ar-rep)
- -(xdef uniq gensym)
- +; currently rather a joke: returns interned symbols
- +
- +(define ar-gensym-count 0)
- +
- +(define (ar-gensym)
- + (set! ar-gensym-count (+ ar-gensym-count 1))
- + (string->symbol (string-append "gs" (number->string ar-gensym-count))))
- +
- +(xdef uniq ar-gensym)
- (xdef ccc call-with-current-continuation)
- (xdef infile open-input-file)
- -(xdef outfile (lambda (f . args)
- - (open-output-file f
- +(xdef outfile (lambda (f . args)
- + (open-output-file f
- 'text
- (if (equal? args '(append))
- 'append
- @@ -870,7 +880,7 @@
- (xdef inside get-output-string)
- (xdef stdout current-output-port) ; should be a vars
- -(xdef stdin current-input-port)
- +(xdef stdin current-input-port)
- (xdef stderr current-error-port)
- (xdef call-w/stdout
- @@ -887,11 +897,6 @@
- (current-input-port)))))
- (if (eof-object? c) 'nil c))))
- -(xdef readchars (lambda (n . str)
- - (let ((cs (read-string n (if (pair? str)
- - (car str)
- - (current-input-port)))))
- - (if (eof-object? cs) 'nil (string->list cs)))))
- (xdef readb (lambda str
- (let ((c (read-byte (if (pair? str)
- @@ -899,38 +904,27 @@
- (current-input-port)))))
- (if (eof-object? c) 'nil c))))
- -(xdef readbytes (lambda (n . str)
- - (let ((bs (read-bytes n (if (pair? str)
- - (car str)
- - (current-input-port)))))
- - (if (eof-object? bs) 'nil (bytes->list bs)))))
- -
- -(xdef peekc (lambda str
- +(xdef peekc (lambda str
- (let ((c (peek-char (if (pair? str)
- (car str)
- (current-input-port)))))
- (if (eof-object? c) 'nil c))))
- -(xdef writec (lambda (c . args)
- - (write-char c
- - (if (pair? args)
- - (car args)
- +(xdef writec (lambda (c . args)
- + (write-char c
- + (if (pair? args)
- + (car args)
- (current-output-port)))
- c))
- -(xdef writeb (lambda (b . args)
- - (write-byte b
- - (if (pair? args)
- - (car args)
- +(xdef writeb (lambda (b . args)
- + (write-byte b
- + (if (pair? args)
- + (car args)
- (current-output-port)))
- b))
- -(xdef writebytes (lambda (bs . args)
- - (write-bytes (list->bytes (ac-denil bs))
- - (if (pair? args)
- - (car args)
- - (current-output-port)))
- - bs))
- +(define explicit-flush #f)
- (define (printwith f args)
- (let ((port (if (> (length args) 1)
- @@ -938,11 +932,10 @@
- (current-output-port))))
- (when (pair? args)
- (f (ac-denil (car args)) port))
- - (unless (ar-bflag 'explicit-flush)
- - (flush-output port)))
- + (unless explicit-flush (flush-output port)))
- 'nil)
- -(defarc write (arc-write . args) (printwith write args))
- +(xdef write (lambda args (printwith write args)))
- (xdef disp (lambda args (printwith display args)))
- ; sread = scheme read. eventually replace by writing read
- @@ -958,109 +951,81 @@
- (define (iround x) (inexact->exact (round x)))
- -; look up first by target type, then by source type
- -(define coercions (make-hash-table 'equal))
- -
- -(for-each (lambda (e)
- - (let ((target-type (car e))
- - (conversions (make-hash-table 'equal)))
- - (hash-table-put! coercions target-type conversions)
- - (for-each
- - (lambda (x) (hash-table-put! conversions (car x) (cadr x)))
- - (cdr e))))
- - `((fn (cons ,(lambda (l) (lambda (i) (list-ref l i))))
- - (string ,(lambda (s) (lambda (i) (string-ref s i))))
- - (table ,(lambda (h) (case-lambda
- - ((k) (hash-table-get h k 'nil))
- - ((k d) (hash-table-get h k d))))))
- -
- - (string (int ,number->string)
- - (num ,number->string)
- - (char ,string)
- - (cons ,(lambda (l) (apply string-append
- - (map (lambda (y) (ar-coerce y 'string))
- - (ar-nil-terminate l)))))
- - (sym ,(lambda (x) (if (eqv? x 'nil) "" (symbol->string x)))))
- -
- - (sym (string ,string->symbol)
- - (char ,(lambda (c) (string->symbol (string c)))))
- -
- - (int (char ,(lambda (c . args) (char->ascii c)))
- - (num ,(lambda (x . args) (iround x)))
- - (string ,(lambda (x . args)
- - (let ((n (apply string->number x args)))
- - (if n (iround n)
- - (err "Can't coerce " x 'int))))))
- -
- - (num (string ,(lambda (x . args)
- - (or (apply string->number x args)
- - (err "Can't coerce " x 'num))))
- - (int ,(lambda (x) x)))
- -
- - (cons (string ,(lambda (x) (ac-niltree (string->list x)))))
- -
- - (char (int ,ascii->char)
- - (num ,(lambda (x) (ascii->char (iround x)))))))
- -
- (define (ar-coerce x type . args)
- - (let ((x-type (ar-type x)))
- - (if (eqv? type x-type) x
- - (let* ((fail (lambda () (err "Can't coerce " x type)))
- - (conversions (hash-table-get coercions type fail))
- - (converter (hash-table-get conversions x-type fail)))
- - (ar-apply converter (cons x args))))))
- + (cond
- + ((ar-tagged? x) (err "Can't coerce annotated object"))
- + ((eqv? type (ar-type x)) x)
- + ((char? x) (case type
- + ((int) (char->ascii x))
- + ((string) (string x))
- + ((sym) (string->symbol (string x)))
- + (else (err "Can't coerce" x type))))
- + ((exint? x) (case type
- + ((num) x)
- + ((char) (ascii->char x))
- + ((string) (apply number->string x args))
- + (else (err "Can't coerce" x type))))
- + ((number? x) (case type
- + ((int) (iround x))
- + ((char) (ascii->char (iround x)))
- + ((string) (apply number->string x args))
- + (else (err "Can't coerce" x type))))
- + ((string? x) (case type
- + ((sym) (string->symbol x))
- + ((cons) (ac-niltree (string->list x)))
- + ((num) (or (apply string->number x args)
- + (err "Can't coerce" x type)))
- + ((int) (let ((n (apply string->number x args)))
- + (if n
- + (iround n)
- + (err "Can't coerce" x type))))
- + (else (err "Can't coerce" x type))))
- + ((pair? x) (case type
- + ((string) (apply string-append
- + (map (lambda (y) (ar-coerce y 'string))
- + (ar-nil-terminate x))))
- + (else (err "Can't coerce" x type))))
- + ((eqv? x 'nil) (case type
- + ((string) "")
- + (else (err "Can't coerce" x type))))
- + ((null? x) (case type
- + ((string) "")
- + (else (err "Can't coerce" x type))))
- + ((symbol? x) (case type
- + ((string) (symbol->string x))
- + (else (err "Can't coerce" x type))))
- + (#t x)))
- (xdef coerce ar-coerce)
- -(xdef coerce* coercions)
- -(xdef parameter make-parameter)
- -(xdef parameterize-sub
- - (lambda (var val thunk)
- - (parameterize ((var val)) (thunk))))
- -
- -(xdef open-socket (lambda (num) (tcp-listen num 50 #t)))
- -
- -(define (ar-init-socket init-fn . args)
- - (let ((oc (current-custodian))
- - (nc (make-custodian)))
- - (current-custodian nc)
- - (apply
- - (lambda (in out . tail)
- - (current-custodian oc)
- - (associate-custodian nc in out)
- - (list* in out tail))
- - (call-with-values
- - init-fn
- - (if (pair? args)
- - (car args)
- - list)))))
- +(xdef open-socket (lambda (num) (tcp-listen num 50 #t)))
- ; the 2050 means http requests currently capped at 2 meg
- ; http://list.cs.brown.edu/pipermail/plt-scheme/2005-August/009414.html
- (xdef socket-accept (lambda (s)
- - (ar-init-socket
- - (lambda () (tcp-accept s))
- - (lambda (in out)
- - (list (make-limited-input-port in 100000 #t)
- - out
- - (let-values (((us them) (tcp-addresses out)))
- - them))))))
- -
- -(xdef socket-connect (lambda (host port)
- - (ar-init-socket
- - (lambda () (tcp-connect host port)))))
- + (let ((oc (current-custodian))
- + (nc (make-custodian)))
- + (current-custodian nc)
- + (call-with-values
- + (lambda () (tcp-accept s))
- + (lambda (in out)
- + (let ((in1 (make-limited-input-port in 100000 #t)))
- + (current-custodian oc)
- + (associate-custodian nc in1 out)
- + (list in1
- + out
- + (let-values (((us them) (tcp-addresses out)))
- + them))))))))
- ; allow Arc to give up root privileges after it
- ; calls open-socket. thanks, Eli!
- -(define setuid (get-ffi-obj 'setuid #f (_fun _int -> _int)
- - ; If we're on Windows, there is no setuid, so we make
- - ; a dummy version. See "Arc 3.1 setuid problem on
- - ; Windows," http://arclanguage.org/item?id=10625.
- - (lambda () (lambda (x) 'nil))))
- +(define setuid (get-ffi-obj 'setuid #f (_fun _int -> _int)))
- (xdef setuid setuid)
- (xdef new-thread thread)
- +(xdef kill-thread kill-thread)
- +(xdef break-thread break-thread)
- (xdef current-thread current-thread)
- (define (wrapnil f) (lambda args (apply f args) 'nil))
- @@ -1068,9 +1033,9 @@
- (xdef sleep (wrapnil sleep))
- ; Will system "execute" a half-finished string if thread killed
- -; in the middle of generating it?
- +; in the middle of generating it?
- -(xdef system (lambda (s) (tnil (system s))))
- +(xdef system (wrapnil system))
- (xdef pipe-from (lambda (cmd)
- (let ((tf (ar-tmpname)))
- @@ -1078,7 +1043,7 @@
- (let ((str (open-input-file tf)))
- (system (string-append "rm -f " tf))
- str))))
- -
- +
- (define (ar-tmpname)
- (call-with-input-file "/dev/urandom"
- (lambda (rstr)
- @@ -1103,9 +1068,9 @@
- h)))
- ;(xdef table (lambda args
- -; (fill-table (make-hash-table 'equal)
- +; (fill-table (make-hash-table 'equal)
- ; (if (pair? args) (ac-denil (car args)) '()))))
- -
- +
- (define (fill-table h pairs)
- (if (eq? pairs '())
- h
- @@ -1148,39 +1113,8 @@
- ; top level read-eval-print
- ; tle kept as a way to get a break loop when a scheme err
- -; To make namespace and module handling more seamless (see
- -; lib/ns.arc), we use Racket's 'set! even for undefined variables,
- -; rather than using 'namespace-set-variable-value! for all Arc
- -; globals. This makes it possible to parameterize the value of
- -; 'current-namespace without getting odd behavior, and it makes it
- -; possible to assign to imported module variables and use
- -; assignment-aware syntax transformers (particularly those made with
- -; Racket's 'make-set!-transformer and 'make-rename-transformer).
- -;
- -; However, by default 'set! is disallowed when the variable is
- -; undefined, and we have to use the 'compile-allow-set!-undefined
- -; parameter to go against that default. Rather than sprinkling
- -; (parameterize ...) forms all over the code and trying to keep them
- -; in sync, we put them all in this function, and we use this function
- -; instead of 'eval when executing the output of 'ac.
- -;
- -; In the same spirit, several other uses of 'namespace-variable-value
- -; and 'namespace-set-variable-value! have been changed to more direct
- -; versions ((set! ...) forms and direct variable references) or less
- -; direct versions (uses of full 'arc-eval) depending on how their
- -; behavior should change when a module import or syntax obstructs the
- -; original meaning of the variable. Some have instead been kept
- -; around, but surrounded by (parameterize ...) forms so they're tied
- -; the main namespace. Another utility changed in this spirit is
- -; 'bound?, which should now be able to see variables which are bound
- -; as Racket syntax.
- -;
- -(define (arc-exec racket-expr)
- - (eval (parameterize ((compile-allow-set!-undefined #t))
- - (compile racket-expr))))
- -
- -(define (arc-eval expr)
- - (arc-exec (ac expr '())))
- +(define (arc-eval expr)
- + (eval (ac expr '())))
- (define (tle)
- (display "Arc> ")
- @@ -1193,39 +1127,27 @@
- (define last-condition* #f)
- (define (tl)
- - (let ((interactive? (terminal-port? (current-input-port))))
- - (when interactive?
- - (display "Use (quit) or ^D to quit, (tl) to return here after an interrupt.\n"))
- - (tl2 interactive?)))
- -
- -(define (tl2 interactive?)
- - (when interactive? (display "arc> "))
- - (on-err (lambda (c)
- + (display "Use (quit) to quit, (tl) to return here after an interrupt.\n")
- + (tl2))
- +
- +(define (tl2)
- + (display "arc> ")
- + (on-err (lambda (c)
- (set! last-condition* c)
- - (parameterize ((current-output-port (current-error-port)))
- - (display "Error: ")
- - (write (exn-message c))
- - (newline)
- - (tl2 interactive?)))
- + (display "Error: ")
- + (write (exn-message c))
- + (newline)
- + (tl2))
- (lambda ()
- (let ((expr (read)))
- - (if (eof-object? expr)
- - (begin (when interactive? (newline))
- - (exit)))
- (if (eqv? expr ':a)
- 'done
- (let ((val (arc-eval expr)))
- - (when interactive?
- - (arc-write (ac-denil val))
- - (newline))
- -
- - ; The following 'parameterize has been added. See the
- - ; note at 'arc-exec, above.
- - ;
- - (parameterize ((current-namespace main-namespace))
- - (namespace-set-variable-value! '_that val)
- - (namespace-set-variable-value! '_thatexpr expr))
- - (tl2 interactive?)))))))
- + (write (ac-denil val))
- + (namespace-set-variable-value! '_that val)
- + (namespace-set-variable-value! '_thatexpr expr)
- + (newline)
- + (tl2)))))))
- (define (aload1 p)
- (let ((x (read p)))
- @@ -1260,7 +1182,7 @@
- (if (eof-object? x)
- #t
- (let ((scm (ac x '())))
- - (arc-exec scm)
- + (eval scm)
- (pretty-print scm op)
- (newline op)
- (newline op)
- @@ -1274,7 +1196,7 @@
- (delete-file outname))
- (call-with-input-file inname
- (lambda (ip)
- - (call-with-output-file outname
- + (call-with-output-file outname
- (lambda (op)
- (acompile1 ip op)))))))
- @@ -1283,17 +1205,17 @@
- (xdef macex1 (lambda (e) (ac-macex (ac-denil e) 'once)))
- (xdef eval (lambda (e)
- - (arc-eval (ac-denil e))))
- + (eval (ac (ac-denil e) '()))))
- ; If an err occurs in an on-err expr, no val is returned and code
- ; after it doesn't get executed. Not quite what I had in mind.
- (define (on-err errfn f)
- - ((call-with-current-continuation
- - (lambda (k)
- - (lambda ()
- - (with-handlers ((exn:fail? (lambda (c)
- - (k (lambda () (errfn c))))))
- + ((call-with-current-continuation
- + (lambda (k)
- + (lambda ()
- + (with-handlers ((exn:fail? (lambda (c)
- + (k (lambda () (errfn c))))))
- (f)))))))
- (xdef on-err on-err)
- @@ -1306,39 +1228,54 @@
- (xdef details (lambda (c)
- (disp-to-string (exn-message c))))
- -(xdef scar (lambda (x val)
- - (if (string? x)
- +(xdef scar (lambda (x val)
- + (if (string? x)
- (string-set! x 0 val)
- (x-set-car! x val))
- val))
- -(xdef scdr (lambda (x val)
- +(xdef scdr (lambda (x val)
- (if (string? x)
- (err "Can't set cdr of a string" x)
- (x-set-cdr! x val))
- val))
- -; waterhouse's code to modify mzscheme-4's immutable pairs.
- -; http://arclanguage.org/item?id=13616
- -(require racket/unsafe/ops)
- +; decide at run-time whether the underlying mzscheme supports
- +; set-car! and set-cdr!, since I can't figure out how to do it
- +; at compile time.
- -(define x-set-car!
- +(define (x-set-car! p v)
- (let ((fn (namespace-variable-value 'set-car! #t (lambda () #f))))
- (if (procedure? fn)
- - fn
- - (lambda (p x)
- - (if (pair? p)
- - (unsafe-set-mcar! p x)
- - (raise-type-error 'set-car! "pair" p))))))
- + (fn p v)
- + (n-set-car! p v))))
- -(define x-set-cdr!
- +(define (x-set-cdr! p v)
- (let ((fn (namespace-variable-value 'set-cdr! #t (lambda () #f))))
- (if (procedure? fn)
- - fn
- - (lambda (p x)
- - (if (pair? p)
- - (unsafe-set-mcdr! p x)
- - (raise-type-error 'set-cdr! "pair" p))))))
- + (fn p v)
- + (n-set-cdr! p v))))
- +
- +; Eli's code to modify mzscheme-4's immutable pairs.
- +
- +;; to avoid a malloc on every call, reuse a single pointer, but make
- +;; it thread-local to avoid races
- +(define ptr (make-thread-cell #f))
- +(define (get-ptr)
- + (or (thread-cell-ref ptr)
- + (let ([p (malloc _scheme 1)]) (thread-cell-set! ptr p) p)))
- +
- +;; set a pointer to the cons cell, then dereference it as a pointer,
- +;; and bang the new value in the given offset
- +(define (set-ca/dr! offset who p x)
- + (if (pair? p)
- + (let ([p* (get-ptr)])
- + (ptr-set! p* _scheme p)
- + (ptr-set! (ptr-ref p* _pointer 0) _scheme offset x))
- + (raise-type-error who "pair" p)))
- +
- +(define (n-set-car! p x) (set-ca/dr! 1 'set-car! p x))
- +(define (n-set-cdr! p x) (set-ca/dr! 2 'set-cdr! p x))
- ; When and if cdr of a string returned an actual (eq) tail, could
- ; say (if (string? x) (string-replace! x val 1) ...) in scdr, but
- @@ -1353,7 +1290,7 @@
- ; Later may want to have multiple indices.
- -(xdef sref
- +(xdef sref
- (lambda (com val ind)
- (cond ((hash-table? com) (if (eqv? val 'nil)
- (hash-table-remove! com ind)
- @@ -1366,11 +1303,12 @@
- (define (nth-set! lst n val)
- (x-set-car! (list-tail lst n) val))
- +; rewrite to pass a (true) gensym instead of #f in case var bound to #f
- +
- (define (bound? arcname)
- - (with-handlers ((exn:fail:syntax? (lambda (e) #t))
- - (exn:fail:contract:variable? (lambda (e) #f)))
- - (namespace-variable-value (ac-global-name arcname))
- - #t))
- + (namespace-variable-value (ac-global-name arcname)
- + #t
- + (lambda () #f)))
- (xdef bound (lambda (x) (tnil (bound? x))))
- @@ -1390,7 +1328,7 @@
- (print-hash-table #t)
- -(xdef client-ip (lambda (port)
- +(xdef client-ip (lambda (port)
- (let-values (((x y) (tcp-addresses port)))
- y)))
- @@ -1399,30 +1337,29 @@
- ; nest within a thread; the thread-cell keeps track of
- ; whether this thread already holds the lock.
- -(define ar-atomic-sema (make-semaphore 1))
- -(define ar-atomic-cell (make-thread-cell #f))
- +(define ar-the-sema (make-semaphore 1))
- +
- +(define ar-sema-cell (make-thread-cell #f))
- +
- (xdef atomic-invoke (lambda (f)
- - (if (thread-cell-ref ar-atomic-cell)
- + (if (thread-cell-ref ar-sema-cell)
- (ar-apply f '())
- (begin
- - (thread-cell-set! ar-atomic-cell #t)
- - (protect
- - (lambda ()
- - (call-with-semaphore
- - ar-atomic-sema
- - (lambda () (ar-apply f '()))))
- - (lambda ()
- - (thread-cell-set! ar-atomic-cell #f)))))))
- + (thread-cell-set! ar-sema-cell #t)
- + (protect
- + (lambda ()
- + (call-with-semaphore
- + ar-the-sema
- + (lambda () (ar-apply f '()))))
- + (lambda ()
- + (thread-cell-set! ar-sema-cell #f)))))))
- (xdef dead (lambda (x) (tnil (thread-dead? x))))
- ; Added because Mzscheme buffers output. Not a permanent part of Arc.
- ; Only need to use when declare explicit-flush optimization.
- -(xdef flushout (lambda args (flush-output (if (pair? args)
- - (car args)
- - (current-output-port)))
- - 't))
- +(xdef flushout (lambda () (flush-output) 't))
- (xdef ssyntax (lambda (x) (tnil (ssyntax? x))))
- @@ -1480,18 +1417,19 @@
- (xdef memory current-memory-use)
- -(define ar-declarations (make-hash-table))
- -
- -(define (ar-bflag key)
- - (not (ar-false? (hash-table-get ar-declarations key 'nil))))
- -
- -(xdef declarations* ar-declarations)
- +(xdef declare (lambda (key val)
- + (let ((flag (not (ar-false? val))))
- + (case key
- + ((atstrings) (set! atstrings flag))
- + ((direct-calls) (set! direct-calls flag))
- + ((explicit-flush) (set! explicit-flush flag)))
- + val)))
- (putenv "TZ" ":GMT")
- (define (gmt-date sec) (seconds->date sec))
- -(xdef timedate
- +(xdef timedate
- (lambda args
- (let ((d (gmt-date (if (pair? args) (car args) (current-seconds)))))
- (ac-niltree (list (date-second d)
- @@ -1501,10 +1439,6 @@
- (date-month d)
- (date-year d))))))
- -(xdef utf-8-bytes
- - (lambda (str)
- - (bytes->list (string->bytes/utf-8 str))))
- -
- (xdef sin sin)
- (xdef cos cos)
- (xdef tan tan)
- @@ -1513,12 +1447,6 @@
- (xdef atan atan)
- (xdef log log)
- -(xdef lor bitwise-ior)
- -(xdef land bitwise-and)
- -(xdef lxor bitwise-xor)
- -(xdef lnot bitwise-not)
- -(xdef shl arithmetic-shift)
- -
- (define (codestring s)
- (let ((i (atpos s 0)))
- (if i
- @@ -1534,27 +1462,28 @@
- ; First unescaped @ in s, if any. Escape by doubling.
- (define (atpos s i)
- - (cond ((eqv? i (string-length s))
- + (cond ((eqv? i (string-length s))
- #f)
- (xdef cos cos)
- (xdef tan tan)
- @@ -1513,12 +1447,6 @@
- (xdef atan atan)
- (xdef log log)
- -(xdef lor bitwise-ior)
- -(xdef land bitwise-and)
- -(xdef lxor bitwise-xor)
- -(xdef lnot bitwise-not)
- -(xdef shl arithmetic-shift)
- -
- (define (codestring s)
- (let ((i (atpos s 0)))
- (if i
- @@ -1534,27 +1462,28 @@
- ; First unescaped @ in s, if any. Escape by doubling.
- (define (atpos s i)
- - (cond ((eqv? i (string-length s))
- + (cond ((eqv? i (string-length s))
- #f)
- ((eqv? (string-ref s i) #\@)
- (if (and (< (+ i 1) (string-length s))
- (not (eqv? (string-ref s (+ i 1)) #\@)))
- i
- (atpos s (+ i 2))))
- - (#t
- + (#t
- (atpos s (+ i 1)))))
- (define (unescape-ats s)
- (list->string (letrec ((unesc (lambda (cs)
- - (cond
- - ((null? cs)
- + (cond
- + ((null? cs)
- '())
- - ((and (eqv? (car cs) #\@)
- + ((and (eqv? (car cs) #\@)
- (not (null? (cdr cs)))
- (eqv? (cadr cs) #\@))
- (unesc (cdr cs)))
- (#t
- (cons (car cs) (unesc (cdr cs))))))))
- (unesc (string->list s)))))
- -
- +
- )
- +
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement