提前道歉,因为这里会有大量代码。我将首先发布代码,然后是问题。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; UTILITY FUNCTIONS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Converts a scheme-expression into a string
;; INPUT: a scheme-expression EXP
;; OUTPUT: a SCHEME String corresponding to EXP
(define (exp->string exp)
(cond ((number? exp) (number->string exp))
((symbol? exp) (symbol->string exp))
((list? exp) (exp->string (car exp)))))
;; INPUT: a list of lists
;; OUTPUT: a list containing all elements of the first-level lists
(define (flatten list-of-lists)
(cond ((null? list-of-lists) '())
(else (append (car list-of-lists) (flatten (cdr list-of-lists))))))
;; this is for all error handling.
;; programmers don't use this function but
;; the interpreter calls this function to
;; signal some type of programmer error
(define (error msg)
(display "ERROR: ")
(display msg)
(newline))
;; THERE ARE TWO SUPPORTED TYPES: 'int and 'boolean
;; INPUT: an element of the ART-C language
;; OUTPUT: the type of that element
(define (type-of val)
(cond ((number? val) 'int)
((boolean? val) 'boolean)))
;; A MAP is a list of key-value pairs
;; INPUT: a MAP and a KEY
;; OUTPUT: The value associated with the key or 'error
(define (map-get map x)
(cond ((null? map) 'error)
((equal? (car (car map)) x) (cadr (car map)))
(else (map-get (cdr map) x))))
;; INPUT : A MAP AND KEY
;; OUTPUT : true if the key is in the map and false otherwise
(define (map-contains map x)
(cond ((null? map) #f)
((equal? (car (car map)) x) #t)
(else (map-contains (cdr map) x))))
;; INPUT : A MAP, KEY and VALUE
;; OUTPUT: The map that results from replacing the key with the new value. If
;; the map doesn't contain KEY, then 'error is returned
(define (map-replace map key val)
(cond ((null? map) 'error)
((equal? (car (car map)) key)
(cons (list key val) (cdr map)))
(else
(cons (car map) (map-replace (cdr map) key val)))))
;; INPUT : A MAP, Key and Value
;; OUTPUT : The map that results from adding a key-value pair. This
;; allows for duplicate keys (the most-recently added is nearer the front of the list
(define (map-add map key val)
(cons (list key val) map))
;; INPUT: A MAP and KEY
;; OUTPUT: The map that results from deleting the key. No errors occur if the map
;; doesn't contain the key
(define (map-delete map key)
(cond ((null? map) map)
((equal? (car (car map)) key) (cdr map))
(else (cons (car map)
(map-delete (cdr map) key)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; TYPEMAP : A SEMANTIC DOMAIN DATA TYPE
;; A typemap is a list of block-level declarations.
;; FORM: ((var1 type1) (var2 type2) (var3 type3) ... )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; INPUT: NONE
;; OUTPUT: AN empty typemap
(define (typemap-create-empty) '())
;; INPUT: A TYPEMAP
;; OUTPUT: The type of variable x
(define (typemap-type-of tm x)
(map-get tm x))
;; INPUT: A TYPEMAP
;; OUTPUT: THE TYPEMAP THAT RESULTS FROM INSERTING A DECLARATIONS
(define (typemap-add tm decl)
(map-add tm (car decl) (cadr decl)))
(define (typemap-delete tm key)
(map-delete tm key))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; STATE : A SEMANTIC DOMAIN DATA TYPE
;; A LIST OF (VAR, VALUE) pairs
;; FORM : ( (var1 val1) (var2 val2) ... )
;; NOTE: A map can contain duplicate keys but innermost KEYS occur
;; before outermost KEYS and hide them
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; INPUT : NONE
;; OUTPUT: AN EMPTY STATE
(define (state-create-empty) '())
;; INPUT: STATE and ID
;; OUTPUT: a new state such that the innermost scope now contains a
;; new binding for the specified ID. The bindings value is 'undefined.
(define (state-add state id)
(map-add state id 'undefined))
;; INPUT : STATE and ID
;; OUTPUT: A new state such that the innermost id is removed
(define (state-delete state id)
(map-delete state id))
;; INPUT: STATE and ID
;; OUTPUT: The value associated with the specified ID in the given state
(define (state-get-value state id)
(map-get state id))
;; INPUT: STATE and ID
;; OUTPUT: A new state that results from changing the mapping from id->value in
;; the specified state
(define (state-update state id value)
(map-replace state id value))
;; INPUT: STATE and LIST-OF-IDS (VARIABLES)
;; OUTPUT: A new state that results from deleting all ids (the variables) from
;; the specified state
(define (state-delete-all state variables)
(cond ((null? variables) state)
(else (state-delete-all (state-delete state (car variables)) (cdr variables)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; THESE CLASSES CORRESPOND TO THE ABSTRACT SYNTAX SUCH THAT A "PROGRAM"
;; REPRESENTS A PARSE-TREE. THESE FUNCTIONS OPERATE AT THE 'SYNTACTIC' LEVEL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (PROGRAM BODY)
(define (program-get-body stmt)
(cadr stmt))
;; (BLOCK S1...SN)
(define (block-get-body stmt)
(filter (lambda (x) (not (is-declaration? x))) (cdr stmt)))
(define (block-get-declarations stmt)
(filter (lambda (x) (is-declaration? x)) (cdr stmt)))
;; (DECLARE TYPE VAR)
(define (declaration-get-type stmt)
(cadr stmt))
(define (declaration-get-var stmt)
(caddr stmt))
(define (is-declaration? stmt)
(and (list? stmt)
(equal? (car stmt) 'declare)))
;; (:= VAR EXP)
(define (assignment-get-var stmt)
(cadr stmt))
(define (assignment-get-exp stmt)
(caddr stmt))
;; (IF TEST THEN [ELSE])
(define (if-get-test stmt)
(cadr stmt))
(define (if-get-then stmt)
(caddr stmt))
(define (if-has-else? stmt)
(= (length stmt) 4))
(define (if-get-else stmt)
(cadddr stmt))
;; (WHILE TEST BODY)
(define (while-get-test stmt)
(cadr stmt))
(define (while-get-body stmt)
(caddr stmt))
;; (SPRINT LABEL EXP)
(define (sprint-has-exp? stmt)
(and (list? stmt)
(= (length stmt) 3)))
(define (sprint-get-label? stmt)
(cadr stmt))
(define (sprint-get-exp stmt)
(caddr stmt))
;; INPUT: an expression EXP
;; OUTPUT: the operator of EXP (an element of ART-C)
(define (exp-get-operator exp)
(car exp))
;; INPUT: an expression EXP
;; OUTPUT: the left-operand (an expression) of EXP
(define (exp-get-left-operand exp)
(car (cdr exp)))
;; INPUT: an expression EXP
;; OUTPUT: the exp-get-right-operand (an expression) of EXP
(define (exp-get-right-operand exp)
(car (cdr (cdr exp))))
;; INPUT: an expression EXP
;; OUTPUT: #t if the expression is a boolean literal and #f otherwise
(define (bool? exp)
(or (equal? exp 'true)
(equal? exp 'false)))
;; INPUT: a symbol
;; OUTPUT: #t if the symbol is 'true and #f if it is 'false and 'void' if neither
(define (symbol->bool sym)
(cond ((equal? sym 'true) #t)
((equal? sym 'false) #f)))
;; INPUT: A PROGRAM
;; A PROGRAM has syntactic structure (program stmt)
;; OUTPUT: THE STATE that results from executing the program
;; in an empty state.
(define (interpret-program pgm)
(interpret (program-get-body pgm) (state-create-empty)))
对于这项任务,我们已经将这个函数库作为起点,并且我在所有代码之后只有一些理解问题。使用这个函数库,我们的任务是在以下解释函数中实现函数:
(define (interpret stmt state)
(display stmt) (newline) (display state) (newline)
(let ((kind (car stmt)))
(cond ((equal? kind 'block) (interpret-block stmt state))
((equal? kind 'declare) (interpret-declaration stmt state))
((equal? kind ':=) (interpret-assignment stmt state))
((equal? kind 'if) (interpret-if stmt state))
((equal? kind 'sprint) (interpret-sprint stmt state))
((equal? kind 'while) (interpret-while stmt state))
(else (error (string-append "statement expected but saw (" (exp->string stmt) "...) instead."))))))
我目前正致力于解释 - 阻止功能,但我还没有完全看到此功能的用途或如何实现它。在我看来,解释块只会用于调用interpert-declaration,interpre-assignment等,但那么解释是什么呢?所以我想我所问的是,什么是解释块应该实际完成的?
下面我已经提供了一个示例程序,该代码旨在解释。
(define pgm '(program
(block
(declare int n)
(declare boolean error)
(declare int result)
(:= error false)
(:= result 1)
(block
(declare int local)
(:= n 5)
(:= local n)
(while (> local 0)
(block
(:= result (* result local))
(:= local (- local 1)))))
(sprint "result: " result)
(if (! error) (sprint "a") (sprint "b")))))
答案 0 :(得分:1)
没有详细阅读你的所有代码(或你的作业),我可以告诉你:是的,你的解释块函数将调用其他函数:解释赋值,赋值声明等。解释 - 块函数需要以对您的语言有意义的方式组合这些函数的结果。
看起来你的语言完全是关于状态及其操作,所以我猜这些函数的结果将包含有关状态的信息 机器,我可以看到状态被用作这些函数的参数。
您需要说明州需要代表什么。我会推荐 制定数据定义(How To Design Programs意义上的)。
答案 1 :(得分:1)
有区别:
intepret
解释一个单独的表达式。
interpret-block
获取一个块表达式中的几个语句,并在每个语句表达式中使用interpret
。 interpret
将根据表达式的类型执行“正确的事情”,例如调用interpret-declaration
。 interpret-block
将在国家处理中发挥至关重要的作用。例如。 declare
将返回一个新状态,下一个语句需要作为参数获取。我猜所有对interpret
的调用都会返回一个状态,并且在interpret-block
中总会返回通过的状态以清除新的绑定。