indigo-0.6.0: Convenient imperative eDSL over Lorentz.
Safe HaskellSafe-Inferred
LanguageHaskell2010

Indigo.Backend.Scope

Description

Machinery that provides the ability to return values from Indigo statements (like if, case, while, etc). You are allowed to return unit, one expression or a tuple of expressions. For instance:

(a, b) <- if flag
          then do
                 anotherFlag <- newVar True
                 return (5 +. var, anotherFlag ||. True)
          else return (0, anotherVar)

is a valid construction. Pay attention to the fact that 5 +. var has the type Expr Integer, but 0 is just an Integer and anotherFlag ||. True has type Expr Bool, but anotherVar has type Var Bool; and this code will compile anyway. This is done intentionally to avoid the burden of manually converting values to expressions (or variables). So you can write the same constructions as in a regular language.

Synopsis

Documentation

data BranchRetKind Source #

To avoid overlapping instances we need to somehow distinguish single values from tuples, because the instances:

  instance Something a
  instance Something (a, b)

overlap and adding {-# OVERLAPPING #-} doesn't rescue in some cases, especially for type families defined in Something.

Constructors

Unit

If value is unit (don't return anything)

SingleVal

If it's a single value (not tuple)

Tuple

If it's tuple (we don't care how many elements are in)

class ReturnableValue' retKind ret => ScopeCodeGen' (retKind :: BranchRetKind) (ret :: Type) where Source #

Type class which unions all related management of computations in a scope, like in if branch, in case body, etc.

Particularly, it takes care of the computation of expressions returning from a scope to leave it safely. Basically, this type class encapsulates the generation of Lorentz code that looks like:

  branch_code #
    -- we get some arbitrary type of a stack here, lets call it xs
  compute_returning_expressions #
    -- we get type of stack [e1, e2, ... ek] ++ xs
  cleanup_xs_to_inp
    -- we get [e1, e2, e3, ..., ek] ++ inp

Methods

compileScopeReturn' :: ret -> IndigoState xs (RetOutStack' retKind ret ++ xs) Source #

Produces an Indigo computation that puts on the stack the evaluated returned expressions from the leaving scope.

liftClear' :: (xs :-> inp) -> (RetOutStack' retKind ret ++ xs) :-> (RetOutStack' retKind ret ++ inp) Source #

Drop the stack cells that were produced in the leaving scope, apart from ones corresponding to the returning expressions.

genGcClear' :: (RetOutStack' retKind ret ++ inp) :-> inp Source #

Generate gcClear for the whole statement

Instances

Instances details
KnownValueExpr single => ScopeCodeGen' 'SingleVal single Source # 
Instance details

Defined in Indigo.Backend.Scope

Methods

compileScopeReturn' :: forall (xs :: [Type]). single -> IndigoState xs (RetOutStack' 'SingleVal single ++ xs) Source #

liftClear' :: forall (xs :: [Type]) (inp :: [Type]). (xs :-> inp) -> (RetOutStack' 'SingleVal single ++ xs) :-> (RetOutStack' 'SingleVal single ++ inp) Source #

genGcClear' :: forall (inp :: [Type]). (RetOutStack' 'SingleVal single ++ inp) :-> inp Source #

ScopeCodeGen' 'Unit () Source # 
Instance details

Defined in Indigo.Backend.Scope

Methods

compileScopeReturn' :: forall (xs :: [Type]). () -> IndigoState xs (RetOutStack' 'Unit () ++ xs) Source #

liftClear' :: forall (xs :: [Type]) (inp :: [Type]). (xs :-> inp) -> (RetOutStack' 'Unit () ++ xs) :-> (RetOutStack' 'Unit () ++ inp) Source #

genGcClear' :: forall (inp :: [Type]). (RetOutStack' 'Unit () ++ inp) :-> inp Source #

(KnownValueExpr x, KnownValueExpr y, Buildable (RetVars' 'Tuple (x, y))) => ScopeCodeGen' 'Tuple (x, y) Source # 
Instance details

Defined in Indigo.Backend.Scope

Methods

compileScopeReturn' :: forall (xs :: [Type]). (x, y) -> IndigoState xs (RetOutStack' 'Tuple (x, y) ++ xs) Source #

liftClear' :: forall (xs :: [Type]) (inp :: [Type]). (xs :-> inp) -> (RetOutStack' 'Tuple (x, y) ++ xs) :-> (RetOutStack' 'Tuple (x, y) ++ inp) Source #

genGcClear' :: forall (inp :: [Type]). (RetOutStack' 'Tuple (x, y) ++ inp) :-> inp Source #

(KnownValueExpr x, KnownValueExpr y, KnownValueExpr z, Buildable (RetVars' 'Tuple (x, y, z))) => ScopeCodeGen' 'Tuple (x, y, z) Source # 
Instance details

Defined in Indigo.Backend.Scope

Methods

compileScopeReturn' :: forall (xs :: [Type]). (x, y, z) -> IndigoState xs (RetOutStack' 'Tuple (x, y, z) ++ xs) Source #

liftClear' :: forall (xs :: [Type]) (inp :: [Type]). (xs :-> inp) -> (RetOutStack' 'Tuple (x, y, z) ++ xs) :-> (RetOutStack' 'Tuple (x, y, z) ++ inp) Source #

genGcClear' :: forall (inp :: [Type]). (RetOutStack' 'Tuple (x, y, z) ++ inp) :-> inp Source #

class ReturnableValue' (retKind :: BranchRetKind) (ret :: Type) where Source #

Class for values that can be returned from Indigo statements. They include () and tuples.

Associated Types

type RetOutStack' retKind ret :: [Type] Source #

Type family reflecting the top elements of stack produced by a statement returning the value.

type RetVars' retKind ret :: Type Source #

Type family reflecting the returning value from a statement.

type RetExprs' retKind ret :: Type Source #

Tuple looking like (Expr x, Expr y, ..) that corresponds to expressions returning from the scope. 'RetVars'' and 'RetExprs'' are twin types because the former just adds Var over each expression of the latter.

Methods

allocateVars' :: Monad m => (forall (x :: Type). m (Var x)) -> m (RetVars' retKind ret) Source #

Allocate variables referring to result of the statement. Requires an allocator operating in a Monad.

assignVars' :: RetVars' retKind ret -> StackVars inp -> StackVars (RetOutStack' retKind ret ++ inp) Source #

Push the variables referring to the result of the statement on top of the stack of the given StackVars.

prettyAssign' :: RetVars' retKind ret -> Text -> Text Source #

Pretty printing of statements like "var := statement"

prettyRet' :: ret -> Text Source #

Prettify ret value

Instances

Instances details
KnownValueExpr single => ReturnableValue' 'SingleVal single Source # 
Instance details

Defined in Indigo.Backend.Scope

Associated Types

type RetOutStack' 'SingleVal single :: [Type] Source #

type RetVars' 'SingleVal single Source #

type RetExprs' 'SingleVal single Source #

Methods

allocateVars' :: Monad m => (forall x. m (Var x)) -> m (RetVars' 'SingleVal single) Source #

assignVars' :: forall (inp :: [Type]). RetVars' 'SingleVal single -> StackVars inp -> StackVars (RetOutStack' 'SingleVal single ++ inp) Source #

prettyAssign' :: RetVars' 'SingleVal single -> Text -> Text Source #

prettyRet' :: single -> Text Source #

ReturnableValue' 'Unit () Source # 
Instance details

Defined in Indigo.Backend.Scope

Associated Types

type RetOutStack' 'Unit () :: [Type] Source #

type RetVars' 'Unit () Source #

type RetExprs' 'Unit () Source #

Methods

allocateVars' :: Monad m => (forall x. m (Var x)) -> m (RetVars' 'Unit ()) Source #

assignVars' :: forall (inp :: [Type]). RetVars' 'Unit () -> StackVars inp -> StackVars (RetOutStack' 'Unit () ++ inp) Source #

prettyAssign' :: RetVars' 'Unit () -> Text -> Text Source #

prettyRet' :: () -> Text Source #

(KnownValueExpr x, KnownValueExpr y, Buildable (RetVars' 'Tuple (x, y))) => ReturnableValue' 'Tuple (x, y) Source # 
Instance details

Defined in Indigo.Backend.Scope

Associated Types

type RetOutStack' 'Tuple (x, y) :: [Type] Source #

type RetVars' 'Tuple (x, y) Source #

type RetExprs' 'Tuple (x, y) Source #

Methods

allocateVars' :: Monad m => (forall x0. m (Var x0)) -> m (RetVars' 'Tuple (x, y)) Source #

assignVars' :: forall (inp :: [Type]). RetVars' 'Tuple (x, y) -> StackVars inp -> StackVars (RetOutStack' 'Tuple (x, y) ++ inp) Source #

prettyAssign' :: RetVars' 'Tuple (x, y) -> Text -> Text Source #

prettyRet' :: (x, y) -> Text Source #

(KnownValueExpr x, KnownValueExpr y, KnownValueExpr z, Buildable (RetVars' 'Tuple (x, y, z))) => ReturnableValue' 'Tuple (x, y, z) Source # 
Instance details

Defined in Indigo.Backend.Scope

Associated Types

type RetOutStack' 'Tuple (x, y, z) :: [Type] Source #

type RetVars' 'Tuple (x, y, z) Source #

type RetExprs' 'Tuple (x, y, z) Source #

Methods

allocateVars' :: Monad m => (forall x0. m (Var x0)) -> m (RetVars' 'Tuple (x, y, z)) Source #

assignVars' :: forall (inp :: [Type]). RetVars' 'Tuple (x, y, z) -> StackVars inp -> StackVars (RetOutStack' 'Tuple (x, y, z) ++ inp) Source #

prettyAssign' :: RetVars' 'Tuple (x, y, z) -> Text -> Text Source #

prettyRet' :: (x, y, z) -> Text Source #

type family ClassifyReturnValue (ret :: Type) where ... Source #

This type family returns a promoted value of type BranchRetKind or causes a compilation error if a tuple with too many elements is used.

Equations

ClassifyReturnValue () = 'Unit 
ClassifyReturnValue (_, _) = 'Tuple 
ClassifyReturnValue (_, _, _) = 'Tuple 
ClassifyReturnValue (_, _, _, _) = TypeError ('Text "Tuple with 4 elements is not supported yet as returning value") 
ClassifyReturnValue (_, _, _, _, _) = TypeError ('Text "Tuple with 5 elements is not supported yet as returning value") 
ClassifyReturnValue (_, _, _, _, _, _) = TypeError ('Text "Tuple with 6 elements is not supported yet as returning value") 
ClassifyReturnValue _ = 'SingleVal 

liftClear :: forall ret inp xs. ScopeCodeGen ret => (xs :-> inp) -> (RetOutStack ret ++ xs) :-> (RetOutStack ret ++ inp) Source #

Specific version of 'liftClear''

compileScope Source #

Arguments

:: forall ret inp xs. ScopeCodeGen ret 
=> (StackVars xs -> MetaData xs)

Partially applied constructor of MetaData (without passed StackVars). compileScope function is usually being called from another function which is in IndigoState and, consequently, holding MetaData with all fields.

-> GenCode inp xs

Code (and clear) of a wrapping scope

-> ret

Return value of a scope (either primitives or expressions or variables)

-> inp :-> (RetOutStack ret ++ inp) 

Concatenate a scoped code, generation of returning expressions, and clean up of redundant cells from the stack.

allocateVars :: forall ret m. (ReturnableValue ret, Monad m) => (forall (x :: Type). m (Var x)) -> m (RetVars ret) Source #

Specific version of 'allocateVars''

finalizeStatement :: forall ret inp. ScopeCodeGen ret => StackVars inp -> RetVars ret -> (inp :-> (RetOutStack ret ++ inp)) -> GenCode inp (RetOutStack ret ++ inp) Source #

Push variables in the StackVars, referring to the generated expressions, and generate gcClear for the whole statement.

prettyAssign :: forall ret. ReturnableValue ret => RetVars ret -> Text -> Text Source #

condStmtPretty :: forall ret x. ReturnableValue ret => RetVars ret -> Text -> Expr x -> Text Source #

prettyRet :: forall ret. ReturnableValue ret => ret -> Text Source #