;; marmalade3000i version 1.0 ;; marmalade3000 interpreter ;; John Joseph Bachir jb@rice.edu ;; last modified 22012002 #| This interpreter uses scheme's 'read' to do tokenizing. read is very handy but a bit more clever than what we need and identifies s-expressions, etc. this is why marmalade3000 uses < and > as expression delimiters, so that we can use read as a tokenizer only. Also since we are using read we can use scheme style commenting in .m3 files! There's not much testing included here... what testing i did have was scattered and confusing so i wiped it. note to students: 'let' and 'let*' have similar (usualy identical) use as the 'local' that you are used to. (... (let( [thing 5] ) ...)) ~= (... (local( [define thing 5] ) ...)) |# ;; ABSTRACT SYNTAX GENERATION ----------------------------- ;; abstract syntax structures (define-struct number_as (value));;value = 0-9 (define-struct boolean_as (value));; #t or #f (define-struct binary_operator_as (value));; + or - or * or / or & or || (define-struct definition_as (name value));; name is a symbol (define-struct application_as (operator operand1 operand2)) (define-struct imperative_series_as (the_list)) (define-struct reference_as (name)) (define (imperative_series_asg) (make-imperative_series_as (imperative_series_asg_helper))) (define (imperative_series_asg_helper) (let*( [next (expression_asg)] ) (if (eq? null next) null (cons next (imperative_series_asg_helper))))) (define (expression_asg) (let ( [next (read CODE)] ) (cond [(eq? next 'define) (definition_asg)] [(or (eq? next 'true) (eq? next 'false)) (boolean_asg next)];next is boolean_asg's 'value' [(number? next) (number_asg next)] [(eq? eof next) null] [(> (string-length(symbol->string next)) 1) (reference_asg next)] [else (application_asg)]))) (define (reference_asg value) (make-reference_as value)) (define (number_asg value) (make-number_as value)) (define (boolean_asg value) (make-boolean_as (equal? value 'true))) (define (application_asg) (let ( [operand1 (expression_asg)] [operator (binary_operator_asg)] [operand2 (expression_asg)]) (rp_eater (make-application_as operator operand1 operand2)))) (define (rp_eater return) (begin (read CODE) return)) (define (definition_asg) (make-definition_as (read CODE);;variable name (expression_asg))) (define (binary_operator_asg) (make-binary_operator_as (read CODE))) ;; EVALUATION ------------------------------------- (define-struct binding (name value)) (define ENVIRONMENT null) ;list of bindings (define (imperative_series_eval as) (let([the_list (imperative_series_as-the_list as)]) (if (null? (cdr the_list)) (output (expression_eval (car the_list))) (begin (output (expression_eval (car the_list))) (imperative_series_eval (make-imperative_series_as (cdr the_list))))))) (define (output value) (begin (display value) (display (list->string (list #\newline))))) (define (expression_eval as) (cond [(number_as? as) (number_eval as)] [(boolean_as? as) (boolean_eval as)] [(application_as? as) (application_as_eval as)] [(definition_as? as) (definition_eval as)] [(reference_as? as) (reference_eval as)] [else "error in expression_eval"])) (define (number_eval as) (number_as-value as)) (define (boolean_eval as) (boolean_as-value as)) (define (application_as_eval as) ((binary_operator_eval (application_as-operator as)) (expression_eval (application_as-operand1 as)) (expression_eval (application_as-operand2 as)))) (define (binary_operator_eval as) (let( [operator (binary_operator_as-value as)] ) (case operator [(+) (lambda (a b) (+ a b))] [(-) (lambda (a b) (- a b))] [(*) (lambda (a b) (* a b))] [(/) (lambda (a b) (/ a b))] [(&) (lambda (a b) (and a b))] [(||) (lambda (a b) (or a b))] [else (print "error in binary_operator_eval")] ))) (define (definition_eval as) (set! ENVIRONMENT (cons (make-binding (definition_as-name as); name (definition_as-value as); value ) ENVIRONMENT))) (define (reference_eval as) (lookup_reference_value (reference_as-name as) ENVIRONMENT )) (define (lookup_reference_value name environment) (if (eq? name (binding-name (car environment))) (expression_eval (binding-value (car environment))) (lookup_reference_value name (cdr environment)) )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define CODE 'THIS_WILL_BE_SET_BANGED_TO_THE_PATH_TO_YOUR_CODE_FILE) (define (marmalade3000i path) (begin (set! CODE (open-input-file path)) (let( [as (imperative_series_asg)];as==abstract syntax ) (imperative_series_eval as)))) ;;change this path as appropriate (marmalade3000i "~/comp210/Labs/challenge/challenge03/code.m3")