@ -0,0 +1,10 @@ |
|||
package circuitcompiler |
|||
|
|||
type Circuit struct { |
|||
NVars int |
|||
NPublic int |
|||
NSignals int |
|||
Inputs []int |
|||
Witness []int |
|||
Constraints []Constraint |
|||
} |
@ -0,0 +1,36 @@ |
|||
package circuitcompiler |
|||
|
|||
import ( |
|||
"fmt" |
|||
"strings" |
|||
"testing" |
|||
|
|||
"github.com/stretchr/testify/assert" |
|||
) |
|||
|
|||
func TestCircuitParser(t *testing.T) { |
|||
/* |
|||
input: |
|||
def test(): |
|||
y = x**3 |
|||
return x + y + 5 |
|||
|
|||
flattened: |
|||
m1 = s1 * s1 |
|||
m2 = m1 * s1 |
|||
m3 = m2 + s1 |
|||
out = m3 + 5 |
|||
*/ |
|||
raw := ` |
|||
y = x^x |
|||
z = x + y |
|||
out = z + 5 |
|||
` |
|||
parser := NewParser(strings.NewReader(raw)) |
|||
res, err := parser.Parse() |
|||
assert.Nil(t, err) |
|||
fmt.Println(res) |
|||
|
|||
// flat code
|
|||
// flat code to R1CS
|
|||
} |
@ -0,0 +1,144 @@ |
|||
package circuitcompiler |
|||
|
|||
import ( |
|||
"bufio" |
|||
"bytes" |
|||
"io" |
|||
) |
|||
|
|||
type OperatorSymbol int |
|||
type Token int |
|||
|
|||
const ( |
|||
ILLEGAL Token = iota |
|||
WS |
|||
EOF |
|||
|
|||
IDENT // val
|
|||
|
|||
VAR // var
|
|||
CONST // const value
|
|||
|
|||
EQ // =
|
|||
PLUS // +
|
|||
MINUS // -
|
|||
MULTIPLY // *
|
|||
DIVIDE // /
|
|||
EXP // ^
|
|||
|
|||
OUT |
|||
) |
|||
|
|||
var eof = rune(0) |
|||
|
|||
func isWhitespace(ch rune) bool { |
|||
return ch == ' ' || ch == '\t' || ch == '\n' |
|||
} |
|||
|
|||
func isLetter(ch rune) bool { |
|||
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') |
|||
} |
|||
func isDigit(ch rune) bool { |
|||
return (ch >= '0' && ch <= '9') |
|||
} |
|||
|
|||
type Scanner struct { |
|||
r *bufio.Reader |
|||
} |
|||
|
|||
func NewScanner(r io.Reader) *Scanner { |
|||
return &Scanner{r: bufio.NewReader(r)} |
|||
} |
|||
|
|||
func (s *Scanner) read() rune { |
|||
ch, _, err := s.r.ReadRune() |
|||
if err != nil { |
|||
return eof |
|||
} |
|||
return ch |
|||
} |
|||
|
|||
func (s *Scanner) unread() { |
|||
_ = s.r.UnreadRune() |
|||
} |
|||
|
|||
func (s *Scanner) Scan() (tok Token, lit string) { |
|||
ch := s.read() |
|||
|
|||
if isWhitespace(ch) { |
|||
// space
|
|||
s.unread() |
|||
return s.scanWhitespace() |
|||
} else if isLetter(ch) { |
|||
// letter
|
|||
s.unread() |
|||
return s.scanIndent() |
|||
} else if isDigit(ch) { |
|||
s.unread() |
|||
return s.scanIndent() |
|||
} |
|||
|
|||
switch ch { |
|||
case eof: |
|||
return EOF, "" |
|||
case '=': |
|||
return EQ, "=" |
|||
case '+': |
|||
return PLUS, "+" |
|||
case '-': |
|||
return MINUS, "-" |
|||
case '*': |
|||
return MULTIPLY, "*" |
|||
case '/': |
|||
return DIVIDE, "/" |
|||
case '^': |
|||
return EXP, "^" |
|||
} |
|||
|
|||
return ILLEGAL, string(ch) |
|||
} |
|||
|
|||
func (s *Scanner) scanWhitespace() (token Token, lit string) { |
|||
var buf bytes.Buffer |
|||
buf.WriteRune(s.read()) |
|||
|
|||
for { |
|||
if ch := s.read(); ch == eof { |
|||
break |
|||
} else if !isWhitespace(ch) { |
|||
s.unread() |
|||
break |
|||
} else { |
|||
_, _ = buf.WriteRune(ch) |
|||
} |
|||
} |
|||
return WS, buf.String() |
|||
} |
|||
|
|||
func (s *Scanner) scanIndent() (tok Token, lit string) { |
|||
var buf bytes.Buffer |
|||
buf.WriteRune(s.read()) |
|||
|
|||
for { |
|||
if ch := s.read(); ch == eof { |
|||
break |
|||
} else if !isLetter(ch) && !isDigit(ch) { |
|||
s.unread() |
|||
break |
|||
} else { |
|||
_, _ = buf.WriteRune(ch) |
|||
} |
|||
} |
|||
switch buf.String() { |
|||
case "var": |
|||
return VAR, buf.String() |
|||
} |
|||
|
|||
if len(buf.String()) == 1 { |
|||
return Token(rune(buf.String()[0])), buf.String() |
|||
} |
|||
if buf.String() == "out" { |
|||
return OUT, buf.String() |
|||
} |
|||
return IDENT, buf.String() |
|||
} |
@ -0,0 +1,92 @@ |
|||
package circuitcompiler |
|||
|
|||
import ( |
|||
"errors" |
|||
"io" |
|||
) |
|||
|
|||
type Parser struct { |
|||
s *Scanner |
|||
buf struct { |
|||
tok Token // last read token
|
|||
lit string // last read literal
|
|||
n int // buffer size (max=1)
|
|||
} |
|||
} |
|||
|
|||
type Constraint struct { |
|||
// v1 op v2 = out
|
|||
Op Token |
|||
V1 Token |
|||
V2 Token |
|||
Out Token |
|||
Literal string |
|||
} |
|||
|
|||
func NewParser(r io.Reader) *Parser { |
|||
return &Parser{s: NewScanner(r)} |
|||
} |
|||
|
|||
func (p *Parser) scan() (tok Token, lit string) { |
|||
// if there is a token in the buffer return it
|
|||
if p.buf.n != 0 { |
|||
p.buf.n = 0 |
|||
return p.buf.tok, p.buf.lit |
|||
} |
|||
tok, lit = p.s.Scan() |
|||
|
|||
p.buf.tok, p.buf.lit = tok, lit |
|||
|
|||
return |
|||
} |
|||
|
|||
func (p *Parser) unscan() { |
|||
p.buf.n = 1 |
|||
} |
|||
|
|||
func (p *Parser) scanIgnoreWhitespace() (tok Token, lit string) { |
|||
tok, lit = p.scan() |
|||
if tok == WS { |
|||
tok, lit = p.scan() |
|||
} |
|||
return |
|||
} |
|||
|
|||
func (p *Parser) ParseLine() (*Constraint, error) { |
|||
/* |
|||
in this version, |
|||
line will be for example s3 = s1 * s4 |
|||
this is: |
|||
val op val op val |
|||
ident op ident op ident |
|||
*/ |
|||
c := &Constraint{} |
|||
var lit string |
|||
c.Out, lit = p.scanIgnoreWhitespace() |
|||
c.Literal += lit |
|||
_, lit = p.scanIgnoreWhitespace() // skip =
|
|||
c.Literal += lit |
|||
c.V1, lit = p.scanIgnoreWhitespace() |
|||
c.Literal += lit |
|||
c.Op, lit = p.scanIgnoreWhitespace() |
|||
c.Literal += lit |
|||
c.V2, lit = p.scanIgnoreWhitespace() |
|||
c.Literal += lit |
|||
if c.Out == EOF { |
|||
return nil, errors.New("eof in parseline") |
|||
} |
|||
return c, nil |
|||
} |
|||
|
|||
func (p *Parser) Parse() (*Circuit, error) { |
|||
circuit := &Circuit{} |
|||
for { |
|||
constraint, err := p.ParseLine() |
|||
if err != nil { |
|||
// return circuit, err
|
|||
break |
|||
} |
|||
circuit.Constraints = append(circuit.Constraints, *constraint) |
|||
} |
|||
return circuit, nil |
|||
} |
@ -1,7 +0,0 @@ |
|||
package compiler |
|||
|
|||
type Circuit struct { |
|||
NVars int |
|||
NPublic int |
|||
NSignals int |
|||
} |
@ -1,9 +1,8 @@ |
|||
module github.com/arnaucube/go-snark |
|||
|
|||
require ( |
|||
github.com/arnaucube/cryptofun v0.0.0-20181124004321-9b11ae8280bd |
|||
github.com/fatih/color v1.7.0 |
|||
github.com/mattn/go-colorable v0.0.9 // indirect |
|||
github.com/mattn/go-isatty v0.0.4 // indirect |
|||
github.com/arnaucube/cryptofun v0.0.0-20181210231954-f5d913b6a74c |
|||
github.com/davecgh/go-spew v1.1.1 // indirect |
|||
github.com/pmezard/go-difflib v1.0.0 // indirect |
|||
github.com/stretchr/testify v1.2.2 |
|||
) |
@ -1,13 +1,11 @@ |
|||
github.com/arnaucube/cryptofun v0.0.0-20181124004321-9b11ae8280bd h1:NDpNBTFeHNE2IHya+msmKlCzIPGzn8qN3Z2jtegFYT0= |
|||
github.com/arnaucube/bn128 v0.0.0-20181124004642-3bb6b68ddbe4/go.mod h1:bIKGJe1ZaHy7HYQML7Me4q38pOpggn3JO1VPPyMe3zI= |
|||
github.com/arnaucube/cryptofun v0.0.0-20181124001128-d55d875d7a54/go.mod h1:PZE8kKpHPD1UMrS3mTfAMmEEinGtijSwjxLRqRcD64A= |
|||
github.com/arnaucube/cryptofun v0.0.0-20181124004321-9b11ae8280bd/go.mod h1:PZE8kKpHPD1UMrS3mTfAMmEEinGtijSwjxLRqRcD64A= |
|||
github.com/arnaucube/cryptofun v0.0.0-20181210231954-f5d913b6a74c h1:i0PwrCdHaQXw6KhbIS+VVj1x/GmqHgOs/LCXLeevE3c= |
|||
github.com/arnaucube/cryptofun v0.0.0-20181210231954-f5d913b6a74c/go.mod h1:jLYDEjM/9/Q/bpdj+9ZdKh2qDIgS2gqcywjg+93MyGI= |
|||
github.com/arnaucube/go-snark v0.0.0-20181207210027-19f7216d0e3d/go.mod h1:gLycS/B43DufBaH0jH8kqiE4A7w5FdOM8I9S416xh2Y= |
|||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= |
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
|||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= |
|||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= |
|||
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= |
|||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= |
|||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= |
|||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= |
|||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= |
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= |
|||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= |
|||
|