ssm-lang / sslang

A language built atop the Sparse Synchronous Model
BSD 3-Clause "New" or "Revised" License
18 stars 0 forks source link

Add String Literals #118

Closed anjalismith closed 1 year ago

anjalismith commented 1 year ago

I'm currently working on editing the parser to handle our desired syntax for string literals. I made a new test file called hello-new-string.ssl that will print "Hello". I also edited the Scanner.x file to update the string literals action and import the reverse Kleisli arrow from Control.Monad.

EmilySillars commented 1 year ago

Hi Anjali, I wrote up some notes for Max on lowering, and I think they may help you with your next steps as well. Restating compiler pipeline for clarity: Scanner --> Parser --> Lowering --> Type Inference --> Optimization --> Code Generation --> C code

Lowering Stage: The ouput of the parser gives us a representation of our input sslang program as a tree. Nodes in the tree represents parts of the input program. The "lowering" pass implemented in LowerAst.hs transforms every AST node into an equivalient IR node. After performing lowering, we are still representing our input sslang program as a tree in the compiler. The difference is that after lowering, there are fewer kinds of nodes in our tree, and each node is augmented with space for a type, t.

// an AST Expr Node     ----- LowerAst.hs ---->     // an IR Expr Node

data Expr                                            data Expr t              
  = Id Identifier                                      = Var VarId t
  | Lit Literal                                        | Data DConId t
  | Apply Expr Expr                                    | Lit Literal t
  | Lambda [Pat] Expr                                  | App (Expr t) (Expr t) t
  | OpRegion Expr OpRegion                             | Let [(Binder, Expr t)] (Expr t) t
  | NoExpr                                             | Lambda Binder (Expr t) t
  | Let [Definition] Expr                              | Match (Expr t) [(Alt, Expr t)] t
  | While Expr Expr                                    | Prim Primitive [Expr t] t
  | Loop Expr                                          deriving (Eq, Show, Typeable, Data, Functor, Foldable, Traversable)
  | Par [Expr]
  | IfElse Expr Expr Expr
  | After Expr Expr Expr
  | Assign Expr Expr
  | Constraint Expr TypAnn
  | Wait [Expr]
  | Seq Expr Expr
  | Break
  | Match Expr [(Pat, Expr)]
  | CQuote String
  | CCall Identifier [Expr]
  deriving (Eq, Show)

-- | A literal
data Literal
  = LitInt Integer
  | LitString String
  | LitRat Rational
  | LitChar Char
  | LitEvent
  deriving (Eq, Show)

The function lowerExpr inside lowerAst.hs has the type signature lowerExpr :: A.Expr -> Compiler.Pass (I.Expr I.Annotations) which means it transforms something of type A.Expr to into a monadic I.Expr. Compiler.Pass is the monad that wraps most all our compiler computations on/transformations of our representation of a sslang prorgam.

Your next steps: When the AST nodes are getting transformed into IR nodes (during the lowering pass), you need to change the representation of a string from a literal to a nested application of data constructors. This means you need to add a case to LowerExpr that transforms a Lit instance of A.Expr into an App instance of I.Expr, when Literal is an instance of LitString.

Lit Literal ---- needs to turn into ----> App (Expr t) (Expr t) t or more specifically, Lit (LitString s) ---- needs to turn into ----> App (Expr t) (Expr t) t

How to do this???

Here is an exercise to get you started thinking about this. Write down your answers and comment them on this draft PR before our next meeting. Also comment any questions you have (or slack message me, whichever you prefer) if you get stuck!

Exercise:

  type List
    Cons Int 
    Nil

  main cin cout = 
   let y = (Cons 'a' (Cons 'b' (Cons 'c' Nil)))
   let x = ['a', 'b', 'c']
   ()

1) What does y look like as an AST node? 2) What does x look like as an AST node?

3) What should y look like as an IR node? 4) What should x look like as an IR node?

I'm writing up a worked example + solution for a similar exercise, and will post that here as soon as I'm finished with it.

EmilySillars commented 1 year ago

Here is a similar exercise with solutions: https://github.com/ssm-lang/sslang/blob/9604ebd88607152fd36c154dcd532b9f43f2bcd9/doc/lang-design/lowering-example.md

anjalismith commented 1 year ago

Hi Emily,

Thank you so much for the notes!

Let [DefPat (PatId "y") (...)] ()
where ... = App ( App (Id "Cons") (Lit 'a' )) (App (App (Id "Cons") (Lit 'b')) (App (App (Id "Cons") (Lit 'c')) (id "Nill")))

2.

Let [DefPat (PatId "x") (...)] ()
where ... = App ( App (Id "Cons") (Lit 'a' )) (App (App (Id "Cons") (Lit 'b')) (App (App (Id "Cons") (Lit 'c')) (id "Nill")))
  1. Let [(Just "y", ...)] (() t)
    where ... = (App ( App (Id "Cons" t) (lit 'a' t) t) (App (App (Id "Cons" t) (Lit 'b' t) t) (App (App (Id "Cons" t ) (lit 'c' t) t) (Id "Nill" t) t) t) t)
    t = (Annotation [])
  2. 
    Let [(Just "x", ...)] (() t)
    where ... = (App ( App (Id "Cons" t) (lit 'a' t) t) (App (App (Id "Cons" t) (Lit 'b' t) t) (App (App (Id "Cons" t ) (lit 'c' t) t) (Id "Nill" t) t) t) t)
    t = (Annotation [])
anjalismith commented 1 year ago

Sounds great, I just committed my changes. Thanks for all your help!