indigo-0.2.2: Convenient imperative eDSL over Lorentz.
Safe HaskellNone
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
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 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 #

(KnownValueExpr x, KnownValueExpr 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) => 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' Source #

Arguments

:: (forall inpt x. KnownValue x => MetaData inpt -> (Var x, MetaData (x & inpt)))

Single variable allocator

-> MetaData inp 
-> (RetVars' retKind ret, MetaData (RetOutStack' retKind ret ++ inp)) 

Allocate variables referring to result of the statement.

Instances

Instances details
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' :: forall (inp :: [Type]). (forall (inpt :: [Type]) x. KnownValue x => MetaData inpt -> (Var x, MetaData (x & inpt))) -> MetaData inp -> (RetVars' 'Unit (), MetaData (RetOutStack' 'Unit () ++ inp)) Source #

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' :: forall (inp :: [Type]). (forall (inpt :: [Type]) x. KnownValue x => MetaData inpt -> (Var x, MetaData (x & inpt))) -> MetaData inp -> (RetVars' 'SingleVal single, MetaData (RetOutStack' 'SingleVal single ++ inp)) Source #

(KnownValueExpr x, KnownValueExpr 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' :: forall (inp :: [Type]). (forall (inpt :: [Type]) x0. KnownValue x0 => MetaData inpt -> (Var x0, MetaData (x0 & inpt))) -> MetaData inp -> (RetVars' 'Tuple (x, y), MetaData (RetOutStack' 'Tuple (x, y) ++ inp)) Source #

(KnownValueExpr x, KnownValueExpr y, KnownValueExpr 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' :: forall (inp :: [Type]). (forall (inpt :: [Type]) x0. KnownValue x0 => MetaData inpt -> (Var x0, MetaData (x0 & inpt))) -> MetaData inp -> (RetVars' 'Tuple (x, y, z), MetaData (RetOutStack' 'Tuple (x, y, z) ++ inp)) 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 :: forall ret inp xs. ScopeCodeGen ret => GenCode inp xs ret -> inp :-> (RetOutStack ret ++ inp) Source #

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

allocateVars :: forall ret inp. ReturnableValue ret => (forall inpt x. KnownValue x => MetaData inpt -> (Var x, MetaData (x & inpt))) -> MetaData inp -> (RetVars ret, MetaData (RetOutStack ret ++ inp)) Source #

Specific version of 'allocateVars''

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

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