diff --git a/fco/Main.hs b/fco/Main.hs index ee8a778..53e2bee 100644 --- a/fco/Main.hs +++ b/fco/Main.hs @@ -15,7 +15,7 @@ import PhaseSource import PhaseIntermediate import PhaseOutput -import qualified OccamTypes as O +import TreeToAST phaseList = [phaseSource, phaseIntermediate, phaseOutput] @@ -26,13 +26,15 @@ doPhases (p:ps) n progress = do n'' <- doPhases ps n' progress return n'' -data Flag = ParseOnly | SOccamOnly | Verbose +data Flag = ParseOnly | SOccamOnly | RawParseOnly | ASTOnly | Verbose deriving (Eq, Show) options :: [OptDescr Flag] options = [ Option [] ["parse-tree"] (NoArg ParseOnly) "parse input files and output S-expression parse tree" , Option [] ["soccam"] (NoArg SOccamOnly) "parse input files and output soccam" + , Option [] ["raw-parse-tree"] (NoArg RawParseOnly) "parse input files and output parse tree" + , Option [] ["ast"] (NoArg ASTOnly) "parse input files and output AST" , Option ['v'] ["verbose"] (NoArg Verbose) "show more detail about what's going on" ] @@ -72,6 +74,10 @@ main = do putStrLn $ show (nodeToSExp parsed) else if SOccamOnly `elem` opts then do putStrLn $ show (nodeToSOccam parsed) + else if RawParseOnly `elem` opts then do + putStrLn $ show parsed + else if ASTOnly `elem` opts then do + putStrLn $ show (treeToAST parsed) else do progress $ "Parsed: " ++ show parsed progress "" diff --git a/fco/Makefile b/fco/Makefile index fecc45e..7df5e62 100644 --- a/fco/Makefile +++ b/fco/Makefile @@ -10,6 +10,7 @@ sources = \ PhaseSource.hs \ SExpression.hs \ Tree.hs \ + TreeToAST.hs \ Main.hs fco: $(sources) @@ -18,3 +19,16 @@ fco: $(sources) BaseTransforms.hs: Tree.hs make-passthrough.py python make-passthrough.py +tests = $(wildcard test*.occ) + +test: fco $(tests) + @set -e; for x in $(tests); do \ + echo -n "$$x: " ; \ + if ! ./fco --raw-parse-tree $$x >/dev/null ; then \ + echo "parse failed" ; \ + elif ! ./fco --ast $$x >/dev/null ; then \ + echo "ast failed" ; \ + else \ + echo "ok" ; \ + fi ; \ + done diff --git a/fco/OccamTypes.hs b/fco/OccamTypes.hs index e3e2303..3000307 100644 --- a/fco/OccamTypes.hs +++ b/fco/OccamTypes.hs @@ -6,8 +6,10 @@ module OccamTypes where import Data.Generics -type Name = String -data Tag = Tag Name +data Name = Name String + deriving (Show, Eq, Typeable, Data) + +data Tag = Tag String deriving (Show, Eq, Typeable, Data) data Type = @@ -16,13 +18,15 @@ data Type = | Int | Int16 | Int32 | Int64 | Real32 | Real64 | Array Expression Type - | UnsizedArray Type + | ArrayUnsized Type | UserType Name | Chan Type | Counted Type Type | Any | Timer | Port Type + | Val Type + | Infer -- for where the type is not given but can be worked out (e.g. "x IS y:") deriving (Show, Eq, Typeable, Data) data ConversionMode = @@ -31,25 +35,30 @@ data ConversionMode = | Trunc deriving (Show, Eq, Typeable, Data) -data Slice = - SliceFromFor Expression Expression - | SliceFrom Expression - | SliceFor Expression +data Subscript = + Subscript Expression + | SubFromFor Expression Expression + | SubFrom Expression + | SubFor Expression deriving (Show, Eq, Typeable, Data) data LiteralRepr = RealLiteral String | IntLiteral String + | HexLiteral String | ByteLiteral String | StringLiteral String | ArrayLiteral [Expression] - | SlicedLiteral Slice LiteralRepr + deriving (Show, Eq, Typeable, Data) + +data Literal = + Literal Type LiteralRepr + | SubscriptedLiteral Subscript Literal deriving (Show, Eq, Typeable, Data) data Variable = Variable Name - | SlicedVariable Slice Variable - | Subscript Expression Variable + | SubscriptedVariable Subscript Variable deriving (Show, Eq, Typeable, Data) data Expression = @@ -60,13 +69,12 @@ data Expression = | Size Type | Conversion ConversionMode Expression | ExprVariable Variable - | Literal Type LiteralRepr + | ExprLiteral Literal | True | False - | Table | FunctionCall Name [Expression] | BytesInType Type - | OffsetOf Type Name + | OffsetOf Type Tag deriving (Show, Eq, Typeable, Data) data ExpressionList = @@ -108,9 +116,9 @@ data Choice = Choice Expression Process deriving (Show, Eq, Typeable, Data) data Alternative = - AltInput Input Process - | GuardedAltInput Expression Input Process - | GuardedSkip Expression Process + Alternative Variable InputMode Process + | AlternativeCond Expression Variable InputMode Process + | AlternativeSkip Expression Process deriving (Show, Eq, Typeable, Data) data Option = @@ -122,44 +130,46 @@ data Variant = Variant Tag [InputItem] Process deriving (Show, Eq, Typeable, Data) -- This represents something that can contain local replicators and specifications. -type Structured t = [StructEntry t] -data StructEntry t = +data Structured t = Rep Replicator (Structured t) | Spec Specification (Structured t) | Only t + | Several [Structured t] deriving (Show, Eq, Typeable, Data) -data Input = - InputSimple Variable [InputItem] - | InputCase Variable (Structured Variant) - | InputAfter Variable Expression +data InputMode = + InputSimple [InputItem] + | InputCase (Structured Variant) + | InputAfter Expression deriving (Show, Eq, Typeable, Data) -data Specification = - Place Name Expression - | Declaration Type Name - | Is Type Name Variable - | ValIs Type Name Expression - | DataTypeIs Name Type - | DataTypeRecord Name Bool [(Type, Name)] - | ProtocolIs Name [Type] - | ProtocolCase Name [(Tag, [Type])] - | Proc Name [(Type, Name)] Process - | Function Name [Type] [(Type, Name)] ValueProcess - | Retypes Name Variable - | Reshapes Name Variable - | ValRetypes Name Variable - | ValReshapes Name Variable +type Specification = (Name, SpecType) +data SpecType = + Place Expression + | Declaration Type + | Is Type Variable + | ValIs Type Expression + | DataTypeIs Type + | DataTypeRecord Bool [(Type, Tag)] + | ProtocolIs [Type] + | ProtocolCase [(Tag, [Type])] + | Proc [(Type, Name)] Process + | Function [Type] [(Type, Name)] ValueProcess + | Retypes Type Variable + | Reshapes Type Variable + | ValRetypes Type Variable + | ValReshapes Type Variable deriving (Show, Eq, Typeable, Data) -type ValueProcess = Structured ValOf -data ValOf = ValOf Process ExpressionList +data ValueProcess = + ValOfSpec Specification ValueProcess + | ValOf Process ExpressionList deriving (Show, Eq, Typeable, Data) -type Process = Structured ProcessEntry -data ProcessEntry = - Assignment [Variable] ExpressionList - | Input Input +data Process = + ProcSpec Specification Process + | Assign [Variable] ExpressionList + | Input Variable InputMode | Output Variable [OutputItem] | OutputCase Variable Tag [OutputItem] | Skip @@ -170,7 +180,8 @@ data ProcessEntry = | If (Structured Choice) | Case Expression (Structured Option) | While Expression Process - | Par Bool (Structured Process) + | Par Bool [Process] + | ParRep Bool Replicator Process | PlacedPar (Structured Process) | Processor Expression Process | Alt Bool (Structured Alternative) diff --git a/fco/TreeToAST.hs b/fco/TreeToAST.hs new file mode 100644 index 0000000..a1a2182 --- /dev/null +++ b/fco/TreeToAST.hs @@ -0,0 +1,250 @@ +-- Convert the parse tree into the AST + +module TreeToAST (treeToAST) where + +import qualified Tree as N +import qualified OccamTypes as O + +doName :: N.Node -> O.Name +doName (N.Name s) = O.Name s +doName n = error $ "Can't do name: " ++ (show n) + +doTag :: N.Node -> O.Tag +doTag (N.Name s) = O.Tag s + +doType :: N.Node -> O.Type +doType n = case n of + N.Bool -> O.Bool + N.Byte -> O.Byte + N.Int -> O.Int + N.Int16 -> O.Int16 + N.Int32 -> O.Int32 + N.Int64 -> O.Int64 + N.Real32 -> O.Real32 + N.Real64 -> O.Real64 + N.Array e t -> O.Array (doExpression e) (doType t) + N.ArrayUnsized t -> O.ArrayUnsized (doType t) + N.Name _ -> O.UserType (doName n) + N.ChanOf t -> O.Chan (doType t) + N.Counted ct dt -> O.Counted (doType ct) (doType dt) + N.Any -> O.Any + N.Timer -> O.Timer + N.PortOf t -> O.Port (doType t) + N.Val t -> O.Val (doType t) + +doMonadicOp :: N.Node -> O.MonadicOp +doMonadicOp n = case n of + N.MonSub -> O.MonadicSubtr + N.MonBitNot -> O.MonadicBitNot + N.MonNot -> O.MonadicNot + N.MonSize -> O.MonadicSize + +doDyadicOp :: N.Node -> O.DyadicOp +doDyadicOp n = case n of + N.Add -> O.Add + N.Subtr -> O.Subtr + N.Mul -> O.Mul + N.Div -> O.Div + N.Rem -> O.Rem + N.Plus -> O.Plus + N.Minus -> O.Minus + N.Times -> O.Times + N.BitAnd -> O.BitAnd + N.BitOr -> O.BitOr + N.BitXor -> O.BitXor + N.And -> O.And + N.Or -> O.Or + N.Eq -> O.Eq + N.NEq -> O.NotEq + N.Less -> O.Less + N.More -> O.More + N.LessEq -> O.LessEq + N.MoreEq -> O.MoreEq + N.After -> O.After + +doSubscript :: N.Node -> O.Subscript +doSubscript n = case n of + N.SubPlain e -> O.Subscript (doExpression e) + N.SubFromFor e f -> O.SubFromFor (doExpression e) (doExpression f) + N.SubFrom e -> O.SubFrom (doExpression e) + N.SubFor f -> O.SubFor (doExpression f) + +doLiteral :: N.Node -> O.Literal +doLiteral n = case n of + N.TypedLit t l -> O.Literal (doType t) rep where (O.Literal _ rep) = doLiteral l + N.LitReal s -> O.Literal O.Real32 (O.RealLiteral s) + N.LitInt s -> O.Literal O.Int (O.IntLiteral s) + N.LitHex s -> O.Literal O.Int (O.HexLiteral s) + N.LitByte s -> O.Literal O.Byte (O.ByteLiteral s) + N.LitString s -> O.Literal (O.ArrayUnsized O.Byte) (O.StringLiteral s) + N.LitArray ns -> O.Literal O.Infer (O.ArrayLiteral (map doExpression ns)) + N.Sub s l -> O.SubscriptedLiteral (doSubscript s) (doLiteral l) + +doVariable :: N.Node -> O.Variable +doVariable n = case n of + N.Name _ -> O.Variable (doName n) + N.Sub s v -> O.SubscriptedVariable (doSubscript s) (doVariable v) + +doExpression :: N.Node -> O.Expression +doExpression n = case n of + N.MonadicOp o a -> O.Monadic (doMonadicOp o) (doExpression a) + N.DyadicOp o a b -> O.Dyadic (doDyadicOp o) (doExpression a) (doExpression b) + N.MostPos t -> O.MostPos (doType t) + N.MostNeg t -> O.MostNeg (doType t) + N.Size t -> O.Size (doType t) + N.Conv t e -> O.Conversion O.DefaultConversion (doExpression e) + N.Round t e -> O.Conversion O.Round (doExpression e) + N.Trunc t e -> O.Conversion O.Trunc (doExpression e) + N.TypedLit _ _ -> O.ExprLiteral $ doLiteral n + N.LitReal _ -> O.ExprLiteral $ doLiteral n + N.LitInt _ -> O.ExprLiteral $ doLiteral n + N.LitHex _ -> O.ExprLiteral $ doLiteral n + N.LitByte _ -> O.ExprLiteral $ doLiteral n + N.LitString _ -> O.ExprLiteral $ doLiteral n + N.LitArray _ -> O.ExprLiteral $ doLiteral n + N.True -> O.True + N.False -> O.False + N.Call f es -> O.FunctionCall (doName f) (map doExpression es) + N.BytesIn t -> O.BytesInType (doType t) + N.OffsetOf t g -> O.OffsetOf (doType t) (doTag g) + otherwise -> O.ExprVariable (doVariable n) + +doExpressionList :: N.Node -> O.ExpressionList +doExpressionList n = case n of + N.Call f es -> O.FunctionCallList (doName f) (map doExpression es) + N.ExpList es -> O.ExpressionList (map doExpression es) + +doReplicator :: N.Node -> O.Replicator +doReplicator n = case n of + N.For v f t -> O.For (doName v) (doExpression f) (doExpression t) + +doFields :: [N.Node] -> [(O.Type, O.Tag)] +doFields ns = concat $ [[(doType t, doTag f) | f <- fs] | (N.Fields t fs) <- ns] + +doFormals :: [N.Node] -> [(O.Type, O.Name)] +doFormals fs = concat $ [[(doType t, doName n) | n <- ns] | (N.Formals t ns) <- fs] + +doVariant :: N.Node -> O.Structured O.Variant +doVariant n = case n of + N.Variant (N.Tag t is) p -> O.Only $ O.Variant (doTag t) (map doInputItem is) (doProcess p) + N.Decl s v -> doSpecifications s O.Spec (doVariant v) + +doChoice :: N.Node -> O.Structured O.Choice +doChoice n = case n of + N.If cs -> O.Several $ map doChoice cs + N.IfRep r c -> O.Rep (doReplicator r) (doChoice c) + N.Choice b p -> O.Only $ O.Choice (doExpression b) (doProcess p) + N.Decl s c -> doSpecifications s O.Spec (doChoice c) + +doOption :: N.Node -> O.Structured O.Option +doOption n = case n of + N.CaseExps cs p -> O.Only $ O.Option (map doExpression cs) (doProcess p) + N.Else p -> O.Only $ O.Else (doProcess p) + N.Decl s o -> doSpecifications s O.Spec (doOption o) + +doInputItem :: N.Node -> O.InputItem +doInputItem n = case n of + N.Counted c d -> O.InCounted (doVariable c) (doVariable d) + otherwise -> O.InVariable (doVariable n) + +doOutputItem :: N.Node -> O.OutputItem +doOutputItem n = case n of + N.Counted c d -> O.OutCounted (doExpression c) (doExpression d) + otherwise -> O.OutExpression (doExpression n) + +doInputMode :: N.Node -> O.InputMode +doInputMode n = case n of + N.InSimple is -> O.InputSimple (map doInputItem is) + N.InCase vs -> O.InputCase (O.Several $ map doVariant vs) + N.InTag (N.Tag t is) -> O.InputCase (O.Only $ O.Variant (doTag t) (map doInputItem is) O.Skip) + N.InAfter e -> O.InputAfter (doExpression e) + +doSimpleSpec :: N.Node -> O.Specification +doSimpleSpec n = case n of + N.Is d v -> (doName d, O.Is O.Infer (doVariable v)) + N.IsType t d v -> (doName d, O.Is (doType t) (doVariable v)) + N.ValIs d e -> (doName d, O.ValIs O.Infer (doExpression e)) + N.ValIsType t d e -> (doName d, O.ValIs (doType t) (doExpression e)) + N.Place v e -> (doName v, O.Place (doExpression e)) + N.DataType n (N.Record fs) -> (doName n, O.DataTypeRecord False (doFields fs)) + N.DataType n (N.PackedRecord fs) -> (doName n, O.DataTypeRecord True (doFields fs)) + N.DataType n t -> (doName n, O.DataTypeIs (doType t)) + N.Protocol n is -> (doName n, O.ProtocolIs (map doType is)) + N.TaggedProtocol n ts -> (doName n, O.ProtocolCase [(doTag tn, map doType tts) | (N.Tag tn tts) <- ts]) + N.Proc n fs p -> (doName n, O.Proc (doFormals fs) (doProcess p)) + N.Func n rs fs vp -> (doName n, O.Function (map doType rs) (doFormals fs) (doValueProcess vp)) + N.FuncIs n rs fs el -> (doName n, O.Function (map doType rs) (doFormals fs) (O.ValOf O.Skip (doExpressionList el))) + N.Retypes t d s -> (doName d, O.Retypes (doType t) (doVariable s)) + N.ValRetypes t d s -> (doName d, O.ValRetypes (doType t) (doVariable s)) + N.Reshapes t d s -> (doName d, O.Reshapes (doType t) (doVariable s)) + N.ValReshapes t d s -> (doName d, O.ValReshapes (doType t) (doVariable s)) + +doSpecifications :: N.Node -> (O.Specification -> a -> a) -> a -> a +doSpecifications n comb arg = case n of + N.Vars t [] -> arg + N.Vars t (v:vs) -> comb (doName v, O.Declaration (doType t)) (doSpecifications (N.Vars t vs) comb arg) + otherwise -> comb (doSimpleSpec n) arg + +doAlternative :: N.Node -> O.Alternative +doAlternative n = case n of + N.Guard (N.In c m) p -> O.Alternative (doVariable c) (doInputMode m) (doProcess p) + N.Guard (N.CondGuard b (N.In c m)) p -> O.AlternativeCond (doExpression b) (doVariable c) (doInputMode m) (doProcess p) + N.Guard (N.CondGuard b N.Skip) p -> O.AlternativeSkip (doExpression b) (doProcess p) + -- ALT over "? CASE": the O.Skip that gets inserted here doesn't correspond + -- to anything in real occam; it's just there to let us handle these the same + -- way as the regular ALT inputs. + N.In c m@(N.InCase _) -> O.Alternative (doVariable c) (doInputMode m) O.Skip + N.CondGuard b (N.In c m@(N.InCase _)) -> O.AlternativeCond (doExpression b) (doVariable c) (doInputMode m) O.Skip + +doAlt :: N.Node -> O.Structured O.Alternative +doAlt n = case n of + N.Alt ns -> O.Several $ map doAlt ns + N.PriAlt ns -> O.Several $ map doAlt ns + N.AltRep r n -> O.Rep (doReplicator r) (doAlt n) + N.PriAltRep r n -> O.Rep (doReplicator r) (doAlt n) + N.Decl s n -> doSpecifications s O.Spec (doAlt n) + otherwise -> O.Only $ doAlternative n + +doValueProcess :: N.Node -> O.ValueProcess +doValueProcess n = case n of + N.Decl s n -> doSpecifications s O.ValOfSpec (doValueProcess n) + N.ValOf p el -> O.ValOf (doProcess p) (doExpressionList el) + +doPlacedPar :: N.Node -> O.Structured O.Process +doPlacedPar n = case n of + N.PlacedPar ps -> O.Several $ map doPlacedPar ps + N.PlacedParRep r p -> O.Rep (doReplicator r) (doPlacedPar p) + N.Processor e p -> O.Only $ O.Processor (doExpression e) (doProcess p) + N.Decl s p -> doSpecifications s O.Spec (doPlacedPar p) + +doProcess :: N.Node -> O.Process +doProcess n = case n of + N.Decl s p -> doSpecifications s O.ProcSpec (doProcess p) + N.Assign vs el -> O.Assign (map doVariable vs) (doExpressionList el) + N.In c m -> O.Input (doVariable c) (doInputMode m) + N.Out c os -> O.Output (doVariable c) (map doOutputItem os) + N.OutCase c t os -> O.OutputCase (doVariable c) (doTag t) (map doOutputItem os) + N.Skip -> O.Skip + N.Stop -> O.Stop + N.MainProcess -> O.Main + N.Seq ps -> O.Seq (map doProcess ps) + N.SeqRep r p -> O.ReplicatedSeq (doReplicator r) (doProcess p) + N.If _ -> O.If $ doChoice n + N.Case e os -> O.Case (doExpression e) (O.Several $ map doOption os) + N.While e p -> O.While (doExpression e) (doProcess p) + N.Par ns -> O.Par False (map doProcess ns) + N.PriPar ns -> O.Par True (map doProcess ns) + N.ParRep r p -> O.ParRep False (doReplicator r) (doProcess p) + N.PriParRep r p -> O.ParRep True (doReplicator r) (doProcess p) + N.PlacedPar _ -> O.PlacedPar $ doPlacedPar n + N.PlacedParRep _ _ -> O.PlacedPar $ doPlacedPar n + N.Processor _ _ -> O.PlacedPar $ doPlacedPar n + N.Alt _ -> O.Alt False $ doAlt n + N.AltRep _ _ -> O.Alt False $ doAlt n + N.PriAlt _ -> O.Alt True $ doAlt n + N.PriAltRep _ _ -> O.Alt True $ doAlt n + N.ProcCall p es -> O.ProcCall (doName p) (map doExpression es) + +treeToAST :: N.Node -> O.Process +treeToAST = doProcess + diff --git a/fco/test7.occ b/fco/test7.occ new file mode 100644 index 0000000..9ee273c --- /dev/null +++ b/fco/test7.occ @@ -0,0 +1,25 @@ +PROTOCOL MYPROTO + CASE + tag1 + tag2 +: +PROC n () + CHAN OF INT c1: + CHAN OF MYPROTO c2: + BOOL b: + ALT + c1 ? x + STOP + b & c1 ? x + STOP + c2 ? CASE + tag1 + STOP + tag2 + STOP + b & c2 ? CASE + tag1 + STOP + tag2 + STOP +: diff --git a/fco/test8.occ b/fco/test8.occ new file mode 100644 index 0000000..0bd6126 --- /dev/null +++ b/fco/test8.occ @@ -0,0 +1,11 @@ +PROC test.syntax () + [1000][1000]CHAN OF INT css: + [1000]CHAN OF INT cs: + SEQ + -- channel + css[111][222] ? x + cs[333] ? x + [cs FROM 444 FOR 11][555] ? x + [cs FROM 666][77] ? x + [cs FOR 888][99] ? x +: diff --git a/fco/test9.occ b/fco/test9.occ new file mode 100644 index 0000000..57a1c2f --- /dev/null +++ b/fco/test9.occ @@ -0,0 +1,9 @@ +PROC other (CHAN OF INT c) + SKIP +: + +PROC foo () + [10]CHAN OF INT xs: + PAR i = 0 FOR SIZE xs + other (xs[i]) +: