; To make a mooix file, wrap a single procedure of one argument in (mooix ...). ; mooix coerces the values returned into the correct form. It accepts the following return values: ; A number - converted to a string ; A string - left alone ; A mooix object reference - converted to its ID string ; A list of any of the above - each element converted, elements seperated by newlines ; ; The first argument passed in by mooix is the mooix object the code is on, the second is the parameters the method was called with, as a list. ; The input parameter code coerces mooix objects and numbers into their Scheme types ; NB: all code that is passed or returns values used as booleans must respect Perl boolean conventions, to wit: FILL IN ; Need to be able to distinguish built-in methods from actual mooix object methods, so need both dispatch and can-dispatch funcs ; dispatch on strings, not idents, since files can start with . and so on (define (mooix code) ; The core bit: get inbound args, pass them to the given code, process the outbound args (process-return (code ; TODO: $this should be passed here (process-args) ) ) ; mooix objects are largely glorified wrappers to dispatch ; TODO: is dir the right internal data bit?? (define (mooix-obj dir) (letrec ((this ; NB: we use "this" in this def'n; I believe this to be legal due to the lambda, but not sure until actually run (lambda (method . args) ; base data selectors (cond ((string=? method "dir") dir) (else (dispatch this method args)) ) ))) this ) ) (define (dispatch this method args) (display ("In dispatch: " (this "dir") method args) (current-error-port)) (cond ; built-in methods ((assoc method dispatch-table) => (lambda (meth) (meth this args))) ; file methods/fields (else (file-dispatch this method args)) ) ) ; Call on-disk method or retrieve/set field value (define (file-dispatch this method args) (let ((file (this "fieldfile" (list method)))) (if (and file (file-exists? file)) (if (regular-file? file) ; Regular on-disk field or method call (if (file-execute-access? method) (file-field this method args) (file-method this method args) ) ; File is dir or symlink - return associated mooix object (if (and (directory? file) (file-exists? (make-absolute-path file ".mooix"))) ; "file" is mooix dir (mooix-obj file) (if (and (symbolic-link? file) (file-exists? (make-absolute-path (read-symbolic-link file) ".mooix"))) ; "file" is mooix dir (mooix-obj (read-symbolic-link file)) ; Not regular file, not mooix obj - badness (and (display ("Object " (obj "fieldget_lang" "name") " has no regular field or method or mooix object pointer named " file ".") (current-error-port)) #f) ) ) ) ; No such file - might be setting a new field (if (= (length args) 1) (obj "setfield" file (car args)) (and (display ("Object " (obj "fieldget_lang" "name") " has no field or method named " file " at all.") (current-error-port)) #f) ) ) ) ) ; Call a method from a file (define (file-method this method args) (let ((file (this "fieldfile" (list method)))) (let-values ( ((fromport toport pid) ; We pass the empty argument string just to avoid the shell (process file "")) ) (display (scheme->mooix-string this) toport) (display (scheme->mooix-string args) toport) (mooix-string->scheme (read-string from-port)) ) ) ) ; TODO: inline this? (define (process-return list) (scheme->mooix-string list) ) ; TODO: inline this? (define (process-args) (mooix-string->scheme (read-string)) )