Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tuple return values for par exprs in codegen #157

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

EmilySillars
Copy link
Contributor

@EmilySillars EmilySillars commented Apr 28, 2023

This PR modifies code generation so that the return values of par expressions are saved in a 2-tuple.

  • tests/par-ret-vals.ssl tests this functionality.
  • type error thrown when a par expression takes more than two arguments (which is good because codegen does not support par expressions with more than 2 args)
  • I believe this PR is ready to merge, but any feedback would be greatly appreciated!

Comment on lines +814 to +832
-- given a list of par return vals and their types, wrap the return vals in a tuple
genParRetVal :: [C.Exp] -> [I.Type] -> GenFn (C.Exp, [C.BlockItem])
genParRetVal [] _ = fail "par should have 2 or more return values"
genParRetVal [_] _ = fail "par should have 2 or more return values"
genParRetVal rets@(ret0 : ret1 : _) retTys = do
-- TODO: given n ret vals, return an n-ary tuple
when (length rets /= length retTys) $ do fail "lists of return vals and types must be same length"
let dcon = I.tempTupleId (length rets)
let dty = I.tempTuple retTys
onHeap <- getsDCon dconOnHeap dcon
unless onHeap $ do
fail $ "Cannot handle packed fields yet, for: " ++ show dcon
construct <- getsDCon dconConstruct dcon
destruct <- getsDCon dconDestruct dcon
tmp <- genTmp dty
let alloc = [[citem|$exp:tmp = $exp:construct;|]]
initField y i = [citem|$exp:(destruct i tmp) = $exp:y;|]
initFields = zipWith initField [ret0, ret1] [0 ..] -- puts first two return vals in a 2-tuple for now
return (tmp, alloc ++ initFields)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

creates a 2-tuple with the first two ret vals of par as its arguments

@EmilySillars EmilySillars requested review from j-hui and leoqiao18 April 28, 2023 23:46
@EmilySillars EmilySillars marked this pull request as ready for review April 28, 2023 23:46
Copy link
Contributor

@j-hui j-hui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a quick review! But I have the following questions:

  • Why isn't codegen for more than 2 tuples supported? It doesn't seem like the logic is any different from regular tuples.
  • Why do we need to define type Pair2 a b in the source code, and why is it written as that (instead of (a, b))?

Otherwise, the code looks really good, but those questions need to be answered/addressed before we can merge this in.

@@ -1,3 +1,6 @@
type Pair2 a b
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this not there before? And is it being used?

import Control.Monad (foldM, unless)
import Control.Monad (foldM, unless, when)

-- import Control.Monad (foldM, unless)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the commented-out import

@@ -809,12 +811,31 @@ genPrim I.Par procs _ = do
return (ret, fnStms ++ argStms, appStms)
apply (e, _) = do
fail $ "Cannot compile par with non-application expression: " ++ show e
-- given a list of par return vals and their types, wrap the return vals in a tuple
genParRetVal :: [C.Exp] -> [I.Type] -> GenFn (C.Exp, [C.BlockItem])
genParRetVal [] _ = fail "par should have 2 or more return values"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: You can just put this as a _ wildcard case after the rets@(ret0:ret1:_) case, to consolidate them

genParRetVal [_] _ = fail "par should have 2 or more return values"
genParRetVal rets@(ret0 : ret1 : _) retTys = do
-- TODO: given n ret vals, return an n-ary tuple
when (length rets /= length retTys) $ do fail "lists of return vals and types must be same length"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put the fail statement on the line after the do, i.e.,

when (length rets /= length retTys) $ do
  fail "lists of return vals and types must be same length"

-- TODO: given n ret vals, return an n-ary tuple
when (length rets /= length retTys) $ do fail "lists of return vals and types must be same length"
let dcon = I.tempTupleId (length rets)
let dty = I.tempTuple retTys
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the redundant let here, should just be:

let dcon = ...
    dty = ...

tmp <- genTmp dty
let alloc = [[citem|$exp:tmp = $exp:construct;|]]
initField y i = [citem|$exp:(destruct i tmp) = $exp:y;|]
initFields = zipWith initField [ret0, ret1] [0 ..] -- puts first two return vals in a 2-tuple for now
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why only the first two values? Why not zipWith initField rets [0..]?

@j-hui
Copy link
Contributor

j-hui commented May 19, 2023

FYI 8d50b53 merged in support for tuples without having to define the PairN type. If you'd like, I can take are of integrating this and merging this in!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants