tala-core-0.1.0: src/Progmasoft/Tala/Desugarer/Workers.hs
-- SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com>
-- SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-1.1
{- | Giving a second lowering of a method body symbols of its own.
A method whose parameters may be passed by need is lowered twice: once as
the method itself, which receives values, and once as the function that
receives suspended computations, for the callers that hand them on. Both
come from the same source statements, whose locals carry the symbols the
renamer gave them. Symbols are unique in a module, so the second lowering
takes fresh ones for everything it defines.
-}
module Progmasoft.Tala.Desugarer.Workers
( definedNames
, renameSymbols
) where
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Progmasoft.Tala.AST
import Progmasoft.Tala.Core
{- | Every name the statements define, at any depth: bindings, expression
bindings, and the parameters of closures. A capture is not listed: it is
the name it captures.
-}
definedNames :: [CoreStatement] -> [ResolvedName]
definedNames = concatMap statement
where
statement value = case value of
CoreBind binding -> coreBindingName binding : expression (coreBindingValue binding)
CoreAssign _ assigned -> expression assigned
CoreReturn returned -> expression returned
CoreEvaluate evaluated -> expression evaluated
CoreIf condition whenTrue whenFalse -> expression condition ++ definedNames whenTrue ++ definedNames whenFalse
CoreWhile condition body -> expression condition ++ definedNames body
CoreDoWhile body condition -> definedNames body ++ expression condition
CoreFor condition body update -> expression condition ++ definedNames body ++ definedNames update
CoreBreak -> []
CoreContinue -> []
expression value = case value of
CoreVariable {} -> []
CoreLiteral {} -> []
CoreApply callee arguments _ -> concatMap expression (callee : arguments)
CorePrimitive _ arguments _ -> concatMap expression arguments
CoreLet name _ bound body _ -> name : expression bound ++ expression body
CoreConditional condition whenTrue whenFalse _ -> concatMap expression [condition, whenTrue, whenFalse]
CoreClosure captures parameters _ body _ ->
map fst parameters
++ concatMap (expression . coreCaptureValue) captures
++ definedNames body
{- | Replace every occurrence of the given symbols, where they are defined and
where they are used. A symbol without a replacement is kept: the functions
of the module, and whatever the statements read from outside.
-}
renameSymbols :: Map SymbolId ResolvedName -> [CoreStatement] -> [CoreStatement]
renameSymbols replacements = map statement
where
name original = Map.findWithDefault original (resolvedSymbol original) replacements
statement value = case value of
CoreBind binding ->
CoreBind
binding
{ coreBindingName = name (coreBindingName binding)
, coreBindingValue = expression (coreBindingValue binding)
}
CoreAssign target assigned -> CoreAssign (name target) (expression assigned)
CoreReturn returned -> CoreReturn (expression returned)
CoreEvaluate evaluated -> CoreEvaluate (expression evaluated)
CoreIf condition whenTrue whenFalse ->
CoreIf (expression condition) (map statement whenTrue) (map statement whenFalse)
CoreWhile condition body -> CoreWhile (expression condition) (map statement body)
CoreDoWhile body condition -> CoreDoWhile (map statement body) (expression condition)
CoreFor condition body update ->
CoreFor (expression condition) (map statement body) (map statement update)
CoreBreak -> CoreBreak
CoreContinue -> CoreContinue
expression value = case value of
CoreVariable variable valueType -> CoreVariable (name variable) valueType
CoreLiteral {} -> value
CoreApply callee arguments valueType ->
CoreApply (expression callee) (map expression arguments) valueType
CorePrimitive primitive arguments valueType ->
CorePrimitive primitive (map expression arguments) valueType
CoreLet bound bindingType boundValue body valueType ->
CoreLet (name bound) bindingType (expression boundValue) (expression body) valueType
CoreConditional condition whenTrue whenFalse valueType ->
CoreConditional (expression condition) (expression whenTrue) (expression whenFalse) valueType
CoreClosure captures parameters returnType body valueType ->
CoreClosure
[ capture
{ coreCaptureName = name (coreCaptureName capture)
, coreCaptureValue = expression (coreCaptureValue capture)
}
| capture <- captures
]
[(name parameter, parameterType) | (parameter, parameterType) <- parameters]
returnType
(map statement body)
valueType