Эх сурвалжийг харах

zkas: WIP circuit parsing.

parazyd 4 жил өмнө
parent
commit
b996e0266c

+ 33 - 0
zkas/src/ast.rs

@@ -0,0 +1,33 @@
+use crate::opcode::Opcode;
+
+pub enum StatementType {
+    Assignment,
+    Call,
+    Noop,
+}
+
+pub struct Variable {
+    pub name: String,
+    pub line: usize,
+    pub column: usize,
+}
+
+pub struct Statement {
+    pub typ: StatementType,
+    pub variable: Option<Variable>,
+    pub opcode: Opcode,
+    pub args: Vec<Variable>,
+    pub line: usize,
+}
+
+impl Default for Statement {
+    fn default() -> Self {
+        Statement {
+            typ: StatementType::Noop,
+            variable: None,
+            opcode: Opcode::Noop,
+            args: vec![],
+            line: 0,
+        }
+    }
+}

+ 2 - 0
zkas/src/lib.rs

@@ -1,3 +1,5 @@
+/// AST
+pub mod ast;
 /// Lexer module
 /// Lexer module
 pub mod lexer;
 pub mod lexer;
 /// Language opcodes
 /// Language opcodes

+ 3 - 0
zkas/src/main.rs

@@ -6,6 +6,9 @@ use zkas::{lexer::Lexer, parser::Parser};
 
 
 fn main() -> Result<()> {
 fn main() -> Result<()> {
     let args = clap_app!(zkas =>
     let args = clap_app!(zkas =>
+        (@arg strip: -s "Strip debug symbols")
+        (@arg preprocess: -E "Preprocess only; do not compile")
+        (@arg OUTPUT: -o +takes_value "Place the output into <OUTPUT>")
         (@arg INPUT: +required "ZK script to compile")
         (@arg INPUT: +required "ZK script to compile")
     )
     )
     .get_matches();
     .get_matches();

+ 3 - 1
zkas/src/opcode.rs

@@ -1,5 +1,5 @@
 // Opcodes supported by the VM
 // Opcodes supported by the VM
-pub enum OpCode {
+pub enum Opcode {
     EcAdd = 0x00,
     EcAdd = 0x00,
     EcMul = 0x01,
     EcMul = 0x01,
     EcMulShort = 0x02,
     EcMulShort = 0x02,
@@ -11,4 +11,6 @@ pub enum OpCode {
     CalculateMerkleRoot = 0x20,
     CalculateMerkleRoot = 0x20,
 
 
     ConstrainInstance = 0xf0,
     ConstrainInstance = 0xf0,
+
+    Noop = 0xff,
 }
 }

+ 87 - 4
zkas/src/parser.rs

@@ -4,7 +4,9 @@ use itertools::Itertools;
 use termion::{color, style};
 use termion::{color, style};
 
 
 use crate::{
 use crate::{
+    ast::{Statement, StatementType, Variable},
     lexer::{Token, TokenType},
     lexer::{Token, TokenType},
+    opcode::Opcode,
     types::{Constant, Type, Witness},
     types::{Constant, Type, Witness},
 };
 };
 
 
@@ -459,19 +461,100 @@ impl Parser {
         // 2. For each statement, see if there are variable assignments
         // 2. For each statement, see if there are variable assignments
         // 3. When referencing, check if they're in Constants, Witnesses
         // 3. When referencing, check if they're in Constants, Witnesses
         //    and finally, or they've been assigned
         //    and finally, or they've been assigned
+
         for statement in statements {
         for statement in statements {
-            /*
+            // TODO: If there are parentheses, verify that there are both
+            //       openings and closings.
+
+            // C = poseidon_hash(pub_x, pub_y, value, token, serial, coin_blind)
+            // | |         |                     |
+            // V V         V                     V
+            // variable   opcode                args
+            // assign
+
+            // constrain_instance(C)
+            //     |              |
+            //     V              V
+            //   opcode         args
+
             let mut iter = statement.iter().peekable();
             let mut iter = statement.iter().peekable();
+            let mut stmt = Statement::default();
             while let Some(token) = iter.next() {
             while let Some(token) = iter.next() {
                 if let Some(next_token) = iter.peek() {
                 if let Some(next_token) = iter.peek() {
                     if next_token.token_type == TokenType::Assign {
                     if next_token.token_type == TokenType::Assign {
-                        variables.push(token);
+                        stmt.typ = StatementType::Assignment;
+                        stmt.variable = Some(Variable {
+                            name: token.token.clone(),
+                            line: token.line,
+                            column: token.column,
+                        });
+                        // Skip over the `=` token.
+                        iter.next();
+                    }
+                } else {
+                    panic!();
+                }
+
+                match token.token.as_str() {
+                    "poseidon_hash" => {
+                        if let Some(next_token) = iter.peek() {
+                            if next_token.token_type != TokenType::LeftParen {
+                                panic!();
+                            }
+                            // The function call opening is correct, so skip the
+                            // opening parenthesis:
+                            iter.next();
+                        } else {
+                            panic!();
+                        }
+
+                        stmt.opcode = Opcode::PoseidonHash;
+
+                        // Eat up function arguments
+                    }
+
+                    "constrain_instance" => {
+                        stmt.opcode = Opcode::ConstrainInstance;
+                        unimplemented!();
+                    }
+
+                    "calculate_merkle_root" => {
+                        stmt.opcode = Opcode::CalculateMerkleRoot;
+                        unimplemented!();
+                    }
+
+                    "ec_mul_short" => {
+                        stmt.opcode = Opcode::EcMulShort;
+                        unimplemented!();
+                    }
+
+                    "ec_mul" => {
+                        stmt.opcode = Opcode::EcMul;
+                        unimplemented!();
+                    }
+
+                    "ec_get_x" => {
+                        stmt.opcode = Opcode::EcGetX;
+                        unimplemented!();
+                    }
+
+                    "ec_get_y" => {
+                        stmt.opcode = Opcode::EcGetY;
+                        unimplemented!();
+                    }
+
+                    "ec_add" => {
+                        stmt.opcode = Opcode::EcAdd;
+                        unimplemented!();
+                    }
+
+                    x => {
+                        unimplemented!();
                     }
                     }
                 }
                 }
             }
             }
-            */
-            println!("{:?}", statement);
 
 
+            println!("{:?}", statement);
             break
             break
         }
         }