Safe Haskell | None |
---|---|
Language | Haskell2010 |
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
- data BranchRetKind
- type ScopeCodeGen ret = ScopeCodeGen' (ClassifyReturnValue ret) ret
- class ReturnableValue' retKind ret => ScopeCodeGen' (retKind :: BranchRetKind) (ret :: Type) where
- compileScopeReturn' :: ret -> IndigoState xs (RetOutStack' retKind ret ++ xs) ()
- liftClear' :: (xs :-> inp) -> (RetOutStack' retKind ret ++ xs) :-> (RetOutStack' retKind ret ++ inp)
- genGcClear' :: (RetOutStack' retKind ret ++ inp) :-> inp
- type ReturnableValue ret = ReturnableValue' (ClassifyReturnValue ret) ret
- class ReturnableValue' (retKind :: BranchRetKind) (ret :: Type) where
- type RetOutStack' retKind ret :: [Type]
- type RetVars' retKind ret :: Type
- type RetExprs' retKind ret :: Type
- allocateVars' :: (forall inpt x. KnownValue x => MetaData inpt -> (Var x, MetaData (x & inpt))) -> MetaData inp -> (RetVars' retKind ret, MetaData (RetOutStack' retKind ret ++ inp))
- type RetOutStack ret = RetOutStack' (ClassifyReturnValue ret) ret
- type RetVars ret = RetVars' (ClassifyReturnValue ret) ret
- type RetExprs ret = RetExprs' (ClassifyReturnValue ret) ret
- type family ClassifyReturnValue (ret :: Type) where ...
- liftClear :: forall ret inp xs. ScopeCodeGen ret => (xs :-> inp) -> (RetOutStack ret ++ xs) :-> (RetOutStack ret ++ inp)
- compileScope :: forall ret inp xs. ScopeCodeGen ret => GenCode inp xs ret -> inp :-> (RetOutStack ret ++ inp)
- 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))
- finalizeStatement :: forall ret inp. ScopeCodeGen ret => MetaData inp -> (inp :-> (RetOutStack ret ++ inp)) -> GenCode inp (RetOutStack ret ++ inp) (RetVars ret)
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
.
type ScopeCodeGen ret = ScopeCodeGen' (ClassifyReturnValue ret) ret Source #
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
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
ScopeCodeGen' 'Unit () Source # | |
Defined in Indigo.Backend.Scope 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 # | |
Defined in Indigo.Backend.Scope 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 # | |
Defined in Indigo.Backend.Scope 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 # | |
Defined in Indigo.Backend.Scope 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 # |
type ReturnableValue ret = ReturnableValue' (ClassifyReturnValue ret) ret Source #
class ReturnableValue' (retKind :: BranchRetKind) (ret :: Type) where Source #
Class for values that can be returned from Indigo statements.
They include ()
and tuples.
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.
:: (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
ReturnableValue' 'Unit () Source # | |
Defined in Indigo.Backend.Scope | |
KnownValueExpr single => ReturnableValue' 'SingleVal single Source # | |
Defined in Indigo.Backend.Scope | |
(KnownValueExpr x, KnownValueExpr y) => ReturnableValue' 'Tuple (x, y) Source # | |
Defined in Indigo.Backend.Scope | |
(KnownValueExpr x, KnownValueExpr y, KnownValueExpr z) => ReturnableValue' 'Tuple (x, y, z) Source # | |
Defined in Indigo.Backend.Scope |
type RetOutStack ret = RetOutStack' (ClassifyReturnValue ret) ret Source #
type RetVars ret = RetVars' (ClassifyReturnValue ret) ret Source #
type RetExprs ret = RetExprs' (ClassifyReturnValue ret) ret 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.
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 #