Itty Bitty Programming Language Functions And Macros Assignment

From CSE425S Wiki
Jump to navigation Jump to search

In a series of assignments, we will build the Itty Bitty Programming Language (IBPL). The inspiration for these assignments is MUPL by Dan Grossman and his team at UW.

One can build an IBPL Abstract Syntax Tree (AST) with the following expressions:

Expressions

(struct IdentifierExp (name)                                           #:transparent)
(struct IntExp        (value)                                          #:transparent)
(struct AddExp        (left_exp right_exp)                             #:transparent)
(struct IfGreaterExp  (left_exp right_exp then_body_exp else_body_exp) #:transparent)
(struct NilExp        ()                                               #:transparent)
(struct IsNilExp      (exp)                                            #:transparent)
(struct ConsExp       (car_exp cdr_exp)                                #:transparent)
(struct CarOfConsExp  (cons_exp)                                       #:transparent)
(struct CdrOfConsExp  (cons_exp)                                       #:transparent)
(struct LetExp        (binding_name binding_exp body_exp)              #:transparent)
(struct FunctionExp   (name_option parameter_name body_exp)            #:transparent)
(struct CallExp       (function_exp argument_exp)                      #:transparent)

Code To Implement

Note: the syntax descriptions below are adapted from Prof. Grossman's MUPL syntax descriptions.

Macros

Expanding the Language

IBPL is a small language, but we can write Racket functions that act like IBPL macros so that users of these functions feel like IBPL is larger. The Racket functions produce IBPL expressions that could then be put inside larger IBPL expressions or passed to evaluate. Also do not use evaluate (we are creating a program, not running it).

file: src/main/racket/ibpl/functions_and_macros/macros.rkt Racket-logo.svg
functions: IbIfNil
IbLet*
IbIfEq

IbIfNil

Write a Racket function IbIfNil that takes three IBPL expressions e1, e2, and e3. It returns a IBPL expression that when run evaluates e1 and if the result is IBPL’s NilExp then it evaluates e2 and that is the overall result, else it evaluates e3 and that is the overall result.

(define (IbIfNil exp then_body_exp else_body_exp)
        (error 'not-yet-implemented))

IbLet*

Write a Racket function IbLet* that takes a Racket list of bindings (list (binding s1 e1) ... (binding si ei) ... (binding sn en)) and a final IBPL expression en+1. In each pair, assume si is a Racket string and ei is an IBPL expression. IbLet* returns a IBPL expression whose value is en+1 evaluated in an environment where each si is a variable bound to the result of evaluating the corresponding ei for 1 ≤ i ≤ n. The bindings are done sequentially, so that each ei is evaluated in an environment where s1 through si−1 have been previously bound to the values e1 through ei−1.

(struct binding (name exp) #:transparent)

(define (IbLet* bindings body_exp) 
        (error 'not-yet-implemented))

IbIfEq

Write a Racket function IbIfEq that takes four IBPL expressions e1, e2, e3, and e4 and returns a IBPL expression that acts like IfGreaterExp except e3 is evaluated if and only if e1 and e2 are equal integers. Assume none of the arguments to IbIfEq use the IBPL variables _x or _y. Use this assumption so that when an expression returned from IbIfEq is evaluated, e1 and e2 are evaluated exactly once each.

(define (IbIfEq left_exp right_exp then_body_exp else_body_exp) 
        (error 'not-yet-implemented))

Functions

file: src/main/racket/ib-map-add-n/functions_and_macros/functions.rkt Racket-logo.svg
functions: ib-double
ib-sum-curry
ib-call-with-one
ib-map
ib-call-with-one

ib-double

(define ib-double 
        'not-yet-implemented)

ib-sum-curry

(define ib-sum-curry
        'not-yet-implemented)

ib-call-with-one

(define ib-call-with-one
        'not-yet-implemented)

ib-map

Bind to the Racket variable ib-map a IBPL FunctionExp that acts like map (as we used extensively in ML). Your function should be curried: it should take a IBPL FunctionExp and return a IBPL function that takes a IBPL list and applies the function to every element of the list returning a new IBPL list. Recall a IBPL list is NilExp or a ConsExp where the second component is a IBPL list.

(define ib-map
        'not-yet-implemented)

ib-map-add-n

Bind to the Racket variable ib-map-add-n a IBPL function that takes an IBPL integer i and returns a IBPL function that takes a IBPL list of IBPL IntExps and returns a new IBPL list of IBPL integers that adds i to every element of the list. Use ib-map (a use of LetExp is given to you to make this easier).

(define ib-map-add-n 
  (LetExp "map" ib-map
                'not-yet-implemented-notice-map-is-now-in-IBPL-scope))

Test

file: test_functions_and_macros.rkt Racket-logo.svg Test
source folder: src/test/racket/ibpl/functions_and_macros

note: ensure that you have removed all printing to receive credit for any assignment.