From 1e0c8e4ed961b0ae97d9265456a13a409bf76eca Mon Sep 17 00:00:00 2001 From: Lef Ioannidis Date: Wed, 7 Oct 2020 00:47:27 -0400 Subject: [PATCH 1/2] Add control flow AST --- libsnark-frontend/depends/libsnark | 2 +- package.yaml | 2 ++ src/IR/Circify/Control.hs | 50 ++++++++++++++++++++++++++++++ stack.yaml | 3 +- stack.yaml.lock | 14 +++++++++ 5 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 src/IR/Circify/Control.hs diff --git a/libsnark-frontend/depends/libsnark b/libsnark-frontend/depends/libsnark index 2af44024..477c9dfd 160000 --- a/libsnark-frontend/depends/libsnark +++ b/libsnark-frontend/depends/libsnark @@ -1 +1 @@ -Subproject commit 2af440246fa2c3d0b1b0a425fb6abd8cc8b9c54d +Subproject commit 477c9dfd07b280e42369f82f89c08416319e24ae diff --git a/package.yaml b/package.yaml index b5dc7c0c..39546612 100644 --- a/package.yaml +++ b/package.yaml @@ -48,7 +48,9 @@ library: - union-find >= 0.2 && < 0.3 - aeson >= 1.4.6 && < 1.5 - text >= 1.2.3 && < 1.3 + - string-interpolate >= 0.3.0 - deepseq >= 1.4.4 && < 1.5 + - natural-numbers >= 0.1.2 - unordered-containers >= 0.2.10 && < 0.3 - hashable >= 1.2.7 && < 1.3 diff --git a/src/IR/Circify/Control.hs b/src/IR/Circify/Control.hs new file mode 100644 index 00000000..31361364 --- /dev/null +++ b/src/IR/Circify/Control.hs @@ -0,0 +1,50 @@ +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE QuantifiedConstraints #-} +{-# LANGUAGE StandaloneDeriving #-} +{-# LANGUAGE QuasiQuotes #-} +module IR.Circify.Control where + +import Data.Natural +import Data.String.Interpolate (i) +import Control.Monad.State.Lazy + +newtype Range = Range { start :: Int, end :: Int, step :: Int, iter :: term Int } + +mkRange :: Int -> Int -> Int -> Range +mkRange start end step iter + | abs (end - start) >= step && step > 0 = Range start end step iter + | abs (end - start) >= (- step) && step < 0 = Range start end step iter + | otherwise = error [i| Bad loop bounds for(i = #{start}; i < #{end}; i = i + #{step})|] + +-- Control flow semantics +data Control (a :: *) (term :: * -> *) where + For :: Range -> Control a term -> Control a term + While :: term Bool -> Natural -> Control a term -> Control a term + If :: term Bool -> Control a term -> Control a term -> Control a term + One :: term a -> Control a term + Seq :: term b -> Control a term -> Control a term + deriving (Functor, Applicative, Monad, Traversable) + +-- Convenience constructors +forloop :: Range -> Control a term -> Control a term +forloop range body = For range body + +whileloop :: term Bool -> Natural -> Control a term -> Control a term +whileloop check maxIterations body = While check maxIterations body + +ifstmt :: term Bool -> Control a term -> Control a term -> Control a term +ifstmt check left right = If check left right + +data LoopAnalysis a term = LoopAnalysis { stack :: Control a term } + +loopAnalysis :: Control a term -> State (LoopAnalysis a term) (Control a term) +loopAnalysis = undefined + +loopFlatten :: Control a term -> Control a term +loopFlatten top = undefined + + diff --git a/stack.yaml b/stack.yaml index 885aca40..c3fead64 100644 --- a/stack.yaml +++ b/stack.yaml @@ -53,9 +53,10 @@ extra-deps: - ghc-typelits-natnormalise-0.7.2@sha256:0fc48a3744aa25e5e53a054a8bb1fe6410752e497f446d75db9bd67bb258d05e,3495 - integer-roots-1.0@sha256:5ea7ecb80633fb05a8a36acd40e9da6fe22a6cef320b1310cb9f0330801ac124,2271 - mod-0.1.2.0@sha256:4c331986c46808d89da590d791841f046509041c849c4254b0872c72284f73ad,2202 + - natural-numbers-0.1.2.0@sha256:0fcbe1220979b83fa612fca73a1adb1a99ff43c84f9652b3ff32b2323309b43c,1407 - poly-0.4.0.0@sha256:75c243113712745dab5d2f4a52643705e146473770af212f9e0ce3d87a83f2ed,2123 - semirings-0.5.4@sha256:5bd49c52a22c876c93d030cafa96b1233e9e7c42dacbe9f49686574368578c9c,2998 - + - string-interpolate-0.3.0.2@sha256:0102ed1eac13b7f85c6d2d3da764ad178d98a23d74912f5d2898eb54af624651,4022 # Override default flag values for local packages and extra-deps # flags: {} diff --git a/stack.yaml.lock b/stack.yaml.lock index 1a36cf41..070e46c3 100644 --- a/stack.yaml.lock +++ b/stack.yaml.lock @@ -78,6 +78,13 @@ packages: sha256: e98a21bc2bdaba7dfba0aeb33d7b2ed5472cd496aea38098b40bac665171cefb original: hackage: mod-0.1.2.0@sha256:4c331986c46808d89da590d791841f046509041c849c4254b0872c72284f73ad,2202 +- completed: + hackage: natural-numbers-0.1.2.0@sha256:0fcbe1220979b83fa612fca73a1adb1a99ff43c84f9652b3ff32b2323309b43c,1407 + pantry-tree: + size: 220 + sha256: bd4beb677280f4586265c5657ab4e4a599c16f9e624df43d8edda6bf1e46dcdf + original: + hackage: natural-numbers-0.1.2.0@sha256:0fcbe1220979b83fa612fca73a1adb1a99ff43c84f9652b3ff32b2323309b43c,1407 - completed: hackage: poly-0.4.0.0@sha256:75c243113712745dab5d2f4a52643705e146473770af212f9e0ce3d87a83f2ed,2123 pantry-tree: @@ -92,6 +99,13 @@ packages: sha256: 83e891acded173adc21b1bcce537f70f82d4b835fb42a41838ddf58d7bde7c7b original: hackage: semirings-0.5.4@sha256:5bd49c52a22c876c93d030cafa96b1233e9e7c42dacbe9f49686574368578c9c,2998 +- completed: + hackage: string-interpolate-0.3.0.2@sha256:0102ed1eac13b7f85c6d2d3da764ad178d98a23d74912f5d2898eb54af624651,4022 + pantry-tree: + size: 1002 + sha256: 073892b62ecdbee3138c572ede59b223433ac56795af96d2b18885de23b82f96 + original: + hackage: string-interpolate-0.3.0.2@sha256:0102ed1eac13b7f85c6d2d3da764ad178d98a23d74912f5d2898eb54af624651,4022 snapshots: - completed: size: 524996 From 80daf6180cb74c9725f07a406dc9159b96e803dc Mon Sep 17 00:00:00 2001 From: Lef Ioannidis Date: Wed, 7 Oct 2020 01:23:52 -0400 Subject: [PATCH 2/2] Derive control instances --- src/IR/Circify/Control.hs | 53 +++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/src/IR/Circify/Control.hs b/src/IR/Circify/Control.hs index 31361364..fdc1de9a 100644 --- a/src/IR/Circify/Control.hs +++ b/src/IR/Circify/Control.hs @@ -6,45 +6,54 @@ {-# LANGUAGE QuantifiedConstraints #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE QuasiQuotes #-} +{-# LANGUAGE DeriveFunctor #-} +{-# LANGUAGE DeriveAnyClass #-} module IR.Circify.Control where -import Data.Natural -import Data.String.Interpolate (i) -import Control.Monad.State.Lazy +import Data.Natural +import Data.String.Interpolate (i) +import Control.Monad.State.Lazy -newtype Range = Range { start :: Int, end :: Int, step :: Int, iter :: term Int } +-- Range of a for loop +data Range = Range { start :: Int, end :: Int, step :: Int } +-- Convenience function that errors on bad ranges mkRange :: Int -> Int -> Int -> Range -mkRange start end step iter - | abs (end - start) >= step && step > 0 = Range start end step iter - | abs (end - start) >= (- step) && step < 0 = Range start end step iter +mkRange start end step + | abs (end - start) >= step && step > 0 = Range start end step + | abs (end - start) >= (- step) && step < 0 = Range start end step | otherwise = error [i| Bad loop bounds for(i = #{start}; i < #{end}; i = i + #{step})|] --- Control flow semantics -data Control (a :: *) (term :: * -> *) where - For :: Range -> Control a term -> Control a term - While :: term Bool -> Natural -> Control a term -> Control a term - If :: term Bool -> Control a term -> Control a term -> Control a term - One :: term a -> Control a term - Seq :: term b -> Control a term -> Control a term - deriving (Functor, Applicative, Monad, Traversable) +-- Control flow syntax +data Control (term :: * -> *) (a :: *) where + For :: Range -> term Int -> Control term a -> Control term a + While :: term Bool -> Natural -> Control term a -> Control term a + If :: term Bool -> Control term a -> Control term a -> Control term a + One :: term a -> Control term a + Seq :: term b -> Control term a -> Control term a + +deriving instance Functor term => Functor (Control term) +deriving instance Applicative term => Applicative (Control term) +deriving instance Monad term => Monad (Control term) -- Convenience constructors -forloop :: Range -> Control a term -> Control a term -forloop range body = For range body +forloop :: Range -> term Int -> Control term a -> Control term a +forloop range iterator body = For range iterator body -whileloop :: term Bool -> Natural -> Control a term -> Control a term +whileloop :: term Bool -> Natural -> Control term a -> Control term a whileloop check maxIterations body = While check maxIterations body -ifstmt :: term Bool -> Control a term -> Control a term -> Control a term +ifstmt :: term Bool -> Control term a -> Control term a -> Control term a ifstmt check left right = If check left right -data LoopAnalysis a term = LoopAnalysis { stack :: Control a term } +-- Analysis state +data LoopAnalysis a term = LoopAnalysis { stack :: [Control term a] } -loopAnalysis :: Control a term -> State (LoopAnalysis a term) (Control a term) +-- TODO: Implement analysis and loop flattening transformation +loopAnalysis :: Control term a -> State (LoopAnalysis a term) (Control term a) loopAnalysis = undefined -loopFlatten :: Control a term -> Control a term +loopFlatten :: Control term a -> Control term a loopFlatten top = undefined