Skip to content
Draft
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0dea01a
Merge pull request #28 from felixwiemuth/dev-master-merged
aslanix Feb 19, 2024
c15e976
Atoms are now converted to tagged records in AtomFolding.hs
AStenbaek Aug 7, 2025
d2ea71f
added ADTTag to records in the compiler
AStenbaek Aug 8, 2025
722c85c
Records now have tags of whether or not they are ADTs
AStenbaek Aug 8, 2025
84aef99
updated IR2Raw test to have the ADTTag
AStenbaek Aug 8, 2025
b8b6623
Added support for ADT naming
AStenbaek Aug 8, 2025
36f8058
Added tests for named datatypes
AStenbaek Aug 8, 2025
4c51524
Added tests for custom named atomic datatypes
AStenbaek Aug 8, 2025
739ca5f
Added support for datatypes with constructors
AStenbaek Aug 12, 2025
eac4175
Added printing support for ADT representation
AStenbaek Aug 13, 2025
3946cc1
Made the printing code for ADTs a tiny bit more readable
AStenbaek Aug 13, 2025
d1a5c75
Matching added for type constructors
AStenbaek Aug 13, 2025
d454c79
ADT constructors have been added
AStenbaek Aug 13, 2025
c573aa3
fixed some printing for adt constructors
AStenbaek Aug 13, 2025
4b1f2e0
Added missing case for pretty-printing in Direct.hs
AStenbaek Aug 20, 2025
9a51a78
cc-based analysis
aslanix Sep 20, 2025
8945a4a
checkpoint
AStenbaek Sep 19, 2025
1ba80b8
Refactored implementation of ADTs to use tuples instead of records.
AStenbaek Sep 21, 2025
906dc93
Changed the name of ADTTag datatype to SynVariantTag in the compiler
AStenbaek Sep 28, 2025
901044d
updated runtime to use SynVariant naming instead of ADT.
AStenbaek Sep 28, 2025
cc89735
Renamed DataType to SyntacticVariant
AStenbaek Sep 28, 2025
94d3055
renaming from Atom SyntacticVariant
AStenbaek Oct 12, 2025
c753e9f
Removed the Atom leftovers from much of the compiler
AStenbaek Oct 12, 2025
e342e53
Further removing of atoms
AStenbaek Oct 12, 2025
62af7cb
Eliminated atoms from runtime
AStenbaek Oct 12, 2025
ca0a701
Merge branch 'TroupeLang:master' into ADT-frontend
AStenbaek Oct 12, 2025
50495d4
Merge branch 'dev-integrity' into ADT-frontend
AStenbaek Oct 12, 2025
62a6282
Added a negative test
AStenbaek Oct 13, 2025
3e3ca7c
added another negative test
AStenbaek Oct 13, 2025
edfc383
cleaned some code and fixed missing match case warnings
AStenbaek Oct 13, 2025
5b9c548
fixed some formatter silliness
AStenbaek Oct 13, 2025
2df8fb6
More cleaning of SynVarFolding.hs
AStenbaek Oct 13, 2025
83210bf
checkpoint
AStenbaek Oct 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions compiler/src/AddAmbientMethods.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,27 @@ printDecl :: FunDecl
printDecl = FunDecl "print"
[Lambda [VarPattern "x"] $
Let [ValDecl (VarPattern "out") (App (Var "getStdout") [Var "authority"]) NoPos]
(App (Var "fprintln") [Tuple [Var "out", Var "x"]])
(App (Var "fprintln") [Tuple [Var "out", Var "x"] False])
] NoPos

printWithLabelsDecl :: FunDecl
printWithLabelsDecl = FunDecl "printWithLabels"
[Lambda [VarPattern "x"] $
Let [ValDecl (VarPattern "out") (App (Var "getStdout") [Var "authority"]) NoPos]
(App (Var "fprintlnWithLabels") [Tuple [Var "out", Var "x"]])
(App (Var "fprintlnWithLabels") [Tuple [Var "out", Var "x"] False])
] NoPos


printStringDecl :: FunDecl
printStringDecl = FunDecl "printString"
[Lambda [VarPattern "x"] $
Let [ValDecl (VarPattern "out") (App (Var "getStdout") [Var "authority"]) NoPos]
(App (Var "fwrite") [Tuple [Var "out", Bin Concat (Var "x") (Lit (LString "\\n"))]])
(App (Var "fwrite") [Tuple [Var "out", Bin Concat (Var "x") (Lit (LString "\\n"))] False])
] NoPos



addAmbientMethods :: Prog -> Prog
addAmbientMethods (Prog imports atoms t) =
let t' = Let [FunDecs [printDecl,printWithLabelsDecl,printStringDecl]] t
in Prog imports atoms t'
in Prog imports atoms t'
40 changes: 26 additions & 14 deletions compiler/src/AtomFolding.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@ module AtomFolding ( visitProg )
where
import Basics
import Direct
import Data.Maybe
import Control.Monad
import Data.List (find, any)

visitProg :: Prog -> Prog
visitProg (Prog imports (Atoms atms) tm) =
Prog imports (Atoms atms) (visitTerm atms tm)
visitProg (Prog imports (DataTypes datatypes) tm) =
let tcs = concat $ map snd datatypes
in Prog imports (DataTypes datatypes) (visitTerm tcs tm)

visitTerm :: [AtomName] -> Term -> Term
visitTerm :: [TypeConstructor] -> Term -> Term
visitTerm atms (Lit lit) = Lit lit
visitTerm atms (Var nm) =
if (elem nm atms)
then Lit (LAtom nm)
else Var nm
let tag = "tag"
value = "value"
var = "v"
in case find (\x -> (fst x) == nm) atms of
Nothing -> Var nm
Just (t, []) -> Tuple [Lit (LString nm)] True -- Convert atom into a tuple
Just (t, _) ->
Abs (Lambda [VarPattern var] (Tuple [ Lit (LString nm)
, Var var
] True))
visitTerm atms (Abs lam) =
Abs (visitLambda atms lam)
visitTerm atms (Hnd (Handler pat maybePat maybeTerm term)) =
Expand All @@ -36,9 +44,9 @@ visitTerm atms (Case t declTermList p) =
p
visitTerm atms (If t1 t2 t3) =
If (visitTerm atms t1) (visitTerm atms t2) (visitTerm atms t3)
visitTerm atms (Tuple terms) =
Tuple (map (visitTerm atms) terms)
visitTerm atms (Record fields) = Record (visitFields atms fields)
visitTerm atms (Tuple terms tag) =
Tuple (map (visitTerm atms) terms) tag
visitTerm atms (Record fields) = Record (visitFields atms fields)
visitTerm atms (WithRecord e fields) =
WithRecord (visitTerm atms e) (visitFields atms fields)
visitTerm atms (ProjField t f) =
Expand All @@ -63,10 +71,10 @@ visitFields atms fs = map visitField fs
where visitField (f, Nothing) = (f, Nothing)
visitField (f, Just t) = (f, Just (visitTerm atms t))

visitPattern :: [AtomName] -> DeclPattern -> DeclPattern
visitPattern :: [TypeConstructor] -> DeclPattern -> DeclPattern
visitPattern atms pat@(VarPattern nm) =
if (elem nm atms)
then ValPattern (LAtom nm)
if any (\x -> x == (nm, [])) atms
then TuplePattern [ValPattern (LString nm)] -- Convert atom match into a record match
else pat
visitPattern _ pat@(ValPattern _) = pat
visitPattern atms (AtPattern p l) = AtPattern (visitPattern atms p) l
Expand All @@ -77,7 +85,11 @@ visitPattern atms (ListPattern pats) = ListPattern (map (visitPattern atms) pats
visitPattern atms (RecordPattern fields mode) = RecordPattern (map visitField fields) mode
where visitField pat@(_, Nothing) = pat
visitField (f, Just p) = (f, Just (visitPattern atms p))
visitPattern atms (DataTypePattern nm pat) =
TuplePattern [ ValPattern (LString nm), visitPattern atms pat]


visitLambda :: [AtomName] -> Lambda -> Lambda
visitLambda :: [TypeConstructor] -> Lambda -> Lambda
visitLambda atms (Lambda pats term) =
(Lambda (map (visitPattern atms) pats) (visitTerm atms term))

5 changes: 5 additions & 0 deletions compiler/src/Basics.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ import Data.Serialize (Serialize)

type VarName = String
type AtomName = String
type DataTypeName = String
type TypeConstructorName = String
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion for naming: TypeConstructorName -> VariantConstructorName

type TypeConstructor = (TypeConstructorName, [VarName])
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar to the above. TypeConstructor -> VariantConstructor, or even better SyntacticVariantConstructor to reflect what is going on in here.

type DataTypeDef = (DataTypeName, [TypeConstructor])
type FieldName = String
type ADTTag = Bool

-- | Eq and Neq: deep equality check on the two parameters, including the types (any type inequality results in false being returned).
data BinOp = Plus | Minus | Mult | Div | Mod | Eq | Neq | Le | Lt | Ge | Gt | And | Or | RaisedTo | FlowsTo | Concat| IntDiv | BinAnd | BinOr | BinXor | BinShiftLeft | BinShiftRight | BinZeroShiftRight | HasField | LatticeJoin | LatticeMeet
Expand Down
26 changes: 13 additions & 13 deletions compiler/src/CPSOpt.hs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ instance Substitutable SimpleTerm where
case simpleTerm of
Bin op v1 v2 -> Bin op (fwd v1) (fwd v2)
Un op v -> Un op (fwd v)
Tuple vs -> Tuple (map fwd vs)
Record fields -> Record $ fwdFields fields
Tuple vs tag -> Tuple (map fwd vs) tag
Record fields -> Record (fwdFields fields)
WithRecord x fields -> WithRecord (fwd x) $ fwdFields fields
ProjField x f -> ProjField (fwd x) f
ProjIdx x idx -> ProjIdx (fwd x) idx
Expand Down Expand Up @@ -145,7 +145,7 @@ instance CensusCollectible SimpleTerm where
Bin _ v1 v2 -> updateCensus [v1,v2]
Un _ v -> updateCensus v
ValSimpleTerm sv -> updateCensus sv
Tuple vs -> updateCensus vs
Tuple vs _ -> updateCensus vs
Record fs -> let (_,vs) = unzip fs in updateCensus vs
WithRecord v fs -> updateCensus v >> (let (_,vs) = unzip fs in updateCensus vs )
ProjField v _ -> updateCensus v
Expand Down Expand Up @@ -326,30 +326,30 @@ simplifySimpleTerm t =
v <- look operand
-- TODO should write out all cases
case (op,v) of
(Basics.IsTuple, St (Tuple _)) -> _ret __trueLit
(Basics.IsTuple, St (Record _)) -> _ret __falseLit
(Basics.IsTuple, St (Tuple _ _)) -> _ret __trueLit
(Basics.IsTuple, St (Record _)) -> _ret __falseLit
(Basics.IsTuple, St (WithRecord _ _)) -> _ret __falseLit
(Basics.IsTuple, St (List _)) -> _ret __falseLit
(Basics.IsTuple, St (ListCons _ _)) -> _ret __falseLit
(Basics.IsTuple, St (ValSimpleTerm _)) -> _ret __falseLit


(Basics.IsRecord, St (Record _)) -> _ret __trueLit
(Basics.IsRecord, St (Record _)) -> _ret __trueLit
(Basics.IsRecord, St (WithRecord _ _)) -> _ret __trueLit
(Basics.IsRecord, St (Tuple _)) -> _ret __falseLit
(Basics.IsRecord, St (Tuple _ _)) -> _ret __falseLit
(Basics.IsRecord, St (List _)) -> _ret __falseLit
(Basics.IsRecord, St (ListCons _ _)) -> _ret __falseLit
(Basics.IsRecord, St (ValSimpleTerm _)) -> _ret __falseLit


(Basics.IsList, St (List _)) -> _ret __trueLit
(Basics.IsList, St (ListCons _ _)) -> _ret __trueLit
(Basics.IsList, St (Record _)) -> _ret __falseLit
(Basics.IsList, St (Record _)) -> _ret __falseLit
(Basics.IsList, St (WithRecord _ _)) -> _ret __falseLit
(Basics.IsList, St (Tuple _)) -> _ret __falseLit
(Basics.IsList, St (Tuple _ _)) -> _ret __falseLit
(Basics.IsList, St (ValSimpleTerm _)) -> _ret __falseLit

(Basics.TupleLength, St (Tuple xs)) ->
(Basics.TupleLength, St (Tuple xs _)) ->
_ret $ lit (C.LInt (fromIntegral (length xs)) NoPos)
-- 2023-08 Revision: Added this case
(Basics.ListLength, St (List xs)) ->
Expand All @@ -366,7 +366,7 @@ simplifySimpleTerm t =
ProjIdx x idx -> do
t <- look x
case t of
St (Tuple vs) | fromIntegral (length vs) > idx ->
St (Tuple vs _) | fromIntegral (length vs) > idx ->
_subst (vs !! fromIntegral idx)
_ -> _nochange

Expand Down Expand Up @@ -409,7 +409,7 @@ failFree st = case st of
Bin op _ _ -> op `elem` [Basics.Eq, Basics.Neq] -- Equality comparisons are safe (return boolean)
Un _ _ -> False -- Unary operations can fail (e.g., head on empty list, arithmetic on non-numbers)
ValSimpleTerm _ -> True
Tuple _ -> True
Tuple _ _ -> True
Record _ -> True
WithRecord _ _ -> True
ProjField _ _ -> False -- Field projection can fail if field doesn't exist
Expand Down Expand Up @@ -546,4 +546,4 @@ iter kt =

rewrite :: Prog -> Prog
rewrite (Prog atoms kterm) =
Prog atoms (iter kterm)
Prog atoms (iter kterm)
18 changes: 9 additions & 9 deletions compiler/src/CaseElimination.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
tm'' <- transTerm tm'
return (T.Prog imports atms' tm'')

transAtoms :: S.Atoms -> Trans T.Atoms
transAtoms (S.Atoms atms) = return (T.Atoms atms)
transAtoms :: S.DataTypes -> Trans T.DataTypes
transAtoms (S.DataTypes atms) = return (T.DataTypes atms)

transLit :: S.Lit -> T.Lit
transLit (S.LInt n pi) = T.LInt n pi
Expand All @@ -41,7 +41,7 @@
transLit (S.LDCLabel dc) = T.LDCLabel dc
transLit (S.LUnit) = T.LUnit
transLit (S.LBool b) = T.LBool b
transLit (S.LAtom a) = T.LAtom a
transLit (S.LDataType a) = T.LDataType a


transLambda_aux :: S.Lambda -> ReaderT T.Term Trans Lambda
Expand Down Expand Up @@ -95,8 +95,8 @@
Just pat2 -> pat2
Nothing -> S.Wildcard
lambdaPats = [S.VarPattern argInput]
callFailure = S.Tuple [S.Lit (S.LInt 1 _srcRT), S.Lit S.LUnit ]
body' = S.Tuple[ S.Lit (S.LInt 0 _srcRT), S.Abs ( S.Lambda [S.Wildcard] body ) ]
callFailure = S.Tuple [S.Lit (S.LInt 1 _srcRT), S.Lit S.LUnit ] False
body' = S.Tuple[ S.Lit (S.LInt 0 _srcRT), S.Abs ( S.Lambda [S.Wildcard] body ) ] False
guardCheck = case guard of
Nothing -> body'
Just g -> S.If g body' callFailure
Expand All @@ -120,7 +120,7 @@
-- v: the term to be assigned to the pattern
-- The Reader monad stores the error term.
compilePattern :: T.Term -> (T.Term, S.DeclPattern) -> ReaderT T.Term Trans T.Term
compilePattern succ (v, (S.AtPattern p l)) = do

Check warning on line 123 in compiler/src/CaseElimination.hs

View workflow job for this annotation

GitHub Actions / build_and_test

Pattern match(es) are non-exhaustive
fail <- ask
succ' <- compilePattern succ (v, p)
return $ ifpat (Bin Eq (Un LevelOf v) (Lit (LLabel l))) succ' fail
Expand Down Expand Up @@ -211,7 +211,7 @@
let lams' = map (transLambda_aux . (\(S.Lambda args e) -> S.Lambda [S.TuplePattern args] e)) lams
names = map (((f ++ "_pat") ++) . show) [1..(length lams)]
args = map (((f ++ "_arg") ++) . show) [1..(argLength lams)]
args' = Tuple (map Var args)
args' = Tuple (map Var args) False
errorMsg = Error (Lit (LString $ "pattern match failure in function " ++ f)) pos
(fst, decls) <- foldr (\(n, l) acc -> do
(fail, decls) <- acc
Expand Down Expand Up @@ -257,9 +257,9 @@
t2' <- transTerm t2
t3' <- transTerm t3
return (If t1' t2' t3')
transTerm (S.Tuple tms) = do
transTerm (S.Tuple tms tag) = do
tms' <- mapM transTerm tms
return (T.Tuple tms')
return (T.Tuple tms' tag)
transTerm (S.Record fields) = do
fields' <- transFields fields
return (T.Record fields')
Expand Down Expand Up @@ -302,4 +302,4 @@
(f, Nothing) -> return (f, T.Var f)
(f, Just t) -> do
t' <- transTerm t
return (f, t')
return (f, t')
4 changes: 2 additions & 2 deletions compiler/src/ClosureConv.hs
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,9 @@ cpsToIR (CPS.LetSimple vname@(VN ident) st kt) = do
CPS.Un unop v -> do
v' <- transVar v
_assign (Un unop v')
CPS.Tuple lst -> do
CPS.Tuple lst tag -> do
lst' <- transVars lst
_assign (Tuple lst')
_assign (Tuple lst' tag)
CPS.Record fields -> do
fields' <- transFields fields
_assign (Record fields')
Expand Down
27 changes: 16 additions & 11 deletions compiler/src/Core.hs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import ShowIndent

import TroupePositionInfo
import DCLabels
import Data.List (find)

--------------------------------------------------
-- AST is the same as Direct, but lambda are unary (or nullary)
Expand All @@ -57,7 +58,7 @@ data Lit
| LDCLabel DCLabelExp
| LUnit
| LBool Bool
| LAtom AtomName
| LAtom TypeConstructorName
Copy link
Contributor

Choose a reason for hiding this comment

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

If Atoms are to be phased out, then shouldn’t we rename them in the codebase as well?

deriving (Show, Generic)
instance Serialize Lit
instance Eq Lit where
Expand Down Expand Up @@ -107,8 +108,8 @@ data Term
| Let Decl Term
| If Term Term Term
| AssertElseError Term Term Term PosInf
| Tuple [Term]
| Record Fields
| Tuple [Term] ADTTag
| Record Fields
| WithRecord Term Fields
| ProjField Term FieldName
| ProjIdx Term Word
Expand Down Expand Up @@ -157,8 +158,8 @@ lowerProg (D.Prog imports atms term) = Prog imports (trans atms) (lower term)

-- the rest of the declarations in this part are not exported

trans :: D.Atoms -> Atoms
trans (D.Atoms atms) = Atoms atms
trans :: D.DataTypes -> Atoms
trans (D.DataTypes atms) = Atoms [] -- (concat $ map snd atms)

lowerLam (D.Lambda vs t) =
case vs of
Expand All @@ -172,7 +173,7 @@ lowerLit (D.LLabel s) = LLabel s
lowerLit (D.LDCLabel dc) = LDCLabel dc
lowerLit D.LUnit = LUnit
lowerLit (D.LBool b) = LBool b
lowerLit (D.LAtom n) = LAtom n
lowerLit (D.LDataType n) = LAtom n

lower :: D.Term -> Core.Term
lower (D.Lit l) = Lit (lowerLit l)
Expand All @@ -198,7 +199,7 @@ lower (D.Let decls e) =
-- lower (D.Case t patTermLst) = Case (lower t) (map (\(p,t) -> (lowerDeclPat p, lower t)) patTermLst)
lower (D.If e1 e2 e3) = If (lower e1) (lower e2) (lower e3)
lower (D.AssertElseError e1 e2 e3 p) = AssertElseError (lower e1 ) (lower e2) (lower e3) p
lower (D.Tuple terms) = Tuple (map lower terms)
lower (D.Tuple terms tag) = Tuple (map lower terms) tag
lower (D.Record fields) = Record (map (\(f, t) -> (f, lower t)) fields)
lower (D.WithRecord e fields) = WithRecord (lower e) (map (\(f, t) -> (f, lower t)) fields)
lower (D.ProjField t f) = ProjField (lower t) f
Expand Down Expand Up @@ -330,8 +331,8 @@ rename (AssertElseError t1 t2 t3 p) m = do
return $ AssertElseError t1' t2' t3' p


rename (Tuple terms) m =
Tuple <$> mapM (flip rename m) terms
rename (Tuple terms tag) m =
(\x -> Tuple x tag) <$> mapM (flip rename m) terms

rename (Record fields) m =
Record <$> mapM renameField fields
Expand Down Expand Up @@ -438,10 +439,14 @@ ppTerm' (Lit literal) = ppLit literal

ppTerm' (Error t _) = text "error " PP.<> ppTerm' t

ppTerm' (Tuple ts) =
ppTerm' (Tuple ts False) =
PP.parens $
PP.hcat $
PP.punctuate (text ",") (map (ppTerm 0) ts)
ppTerm' (Tuple ts True) =
case ts of [Lit (LString nm)] -> text nm
[Lit (LString nm), t] -> text nm PP.<> PP.space PP.<> ppTerm 0 t
otherwise -> text "error: MissingADT"

ppTerm' (List ts) =
PP.brackets $
Expand Down Expand Up @@ -561,7 +566,7 @@ ppLit (LDCLabel dc) = ppDCLabelExpLit dc

termPrec :: Term -> Precedence
termPrec (Lit _) = maxPrec
termPrec (Tuple _) = maxPrec
termPrec (Tuple _ _) = maxPrec
termPrec (List _ ) = maxPrec
termPrec (Var _) = maxPrec
termPrec (App _ _) = appPrec
Expand Down
Loading
Loading