LMU ☀️ CMSI 585
PROGRAMMING LANGUAGE FOUNDATIONS
HOMEWORK #5 Due: 2024-06-21

Learning Objectives

With this assignment you will demonstrate:

Readings and Videos

Please:

Instructions

Submit, to BrightSpace, a neatly typeset answer to Problem 1, and a link to a GitHub repo or Replit for Problem 2. Please make a best effort for typesetting. Handwritten answers are okay if you are short on time, but pay extra attention to neatness if you go that route.

Problems to Submit

  1. Give a Denotational Semantics for a small extension to Bella with arrays, booleans, and lists, that is strongly-typed and dynamically typed. Here is the abstract syntax:

    $ \begin{array}{l} n\!: \mathsf{Numeral} \\ i\!: \mathsf{Identifier} \\ uop\!: \mathsf{UnaryOp} = \mathtt{!} \;|\; \mathtt{-} \\ bop\!: \mathsf{BinaryOp} = \mathtt{<} \;|\; \mathtt{<=} \;|\; \mathtt{==} \;|\; \mathtt{!=} \;|\; \mathtt{>=} \;|\; \mathtt{>}\\ e\!: \mathsf{Expression} = n \;|\; i \;|\; \mathtt{true} \;|\; \mathtt{false} \;|\; \mathit{uop} \; e \;|\; e_1 \; \mathit{bop} \; e_2 \;|\; i \; e^* \;|\; e \; \mathtt{?} \; e_1 \; \mathtt{:} \; e_2 \;|\; \mathtt{[} \; e^* \; \mathtt{]} \;|\; e \mathtt{[} e \mathtt{]} \\ s\!: \mathsf{Statement} = \mathtt{let}\;i = e \;|\; \mathtt{func}\;i\;i^*=e \;|\; i = e \;|\; \mathtt{print}\;e \;|\; \mathtt{while}\;e\;b \\ b\!: \mathsf{Block} = \mathtt{block}\; s^* \\ p\!: \mathsf{Program} = \mathtt{program}\; b \end{array} $

    The standard library is as we saw in class.

    Hint: This is exactly the extension of Bella that we saw in class when we began our study of types in operational semantics. The entire operational semantics for this language extension is provided in the course notes; you are encouraged to build your denotational semantics by simply “translating” the operational semantics to denotational semantics. (This helps to achieve the learning objective of gaining comfort with the similarities and differences between the two forms of semantic description.)

  2. Write, in TypeScript, an interpreter for Bella, using the semantic rules you gave in the previous problem. The input to the interpret function can be a Bella structured program representation (an abstract syntax “tree” object). As this is not a compiler writing class, there is no need to write a parser. If you wish to write a parser, I won’t stop you, but I will not be awarding any extra credit for doing so.

    To get you started, here is a portion of the abstract syntax representation:

    class Program {
      constructor(public body: Block) {}
    }
    
    class Block {
      constructor(public statements: Statement[]) {}
    }
    
    interface Statement {
    
    }
    
    class Assignment implements Statement {
      constructor(public target: Identifier, public source: Expression) {}
    }
    
    class VariableDeclaration implements Statement {
      constructor(public id: Identifier, public initializer: Expression) {}
    }
    
    interface Expression {
    
    }
    
    // Build the rest of the classes and interfaces here: PrintStatement,
    // BinaryExpression, UnaryExpression, ConditionalExpression, Numeral,
    // Identifier, etc.
    

    Your interpreter will be function set up like this:

    function interpret(program: Program): void {
      // your code here
    }
    
  3. An invocation of the interpreter might look like this:

    const sample: Program = new Program(
      new Block([new PrintStatement(new Numeral(5))])
    )
    
    interpret(sample)