Kaynağa Gözat

zkas: Add zkas code from zkas repo.

parazyd 4 yıl önce
ebeveyn
işleme
3511b8ff51
9 değiştirilmiş dosya ile 685 ekleme ve 0 silme
  1. 293 0
      zkas/Cargo.lock
  2. 13 0
      zkas/Cargo.toml
  3. 34 0
      zkas/Makefile
  4. 22 0
      zkas/src/bin/zkas.rs
  5. 73 0
      zkas/src/error.rs
  6. 208 0
      zkas/src/lexer.rs
  7. 3 0
      zkas/src/lib.rs
  8. 11 0
      zkas/src/opcode.rs
  9. 28 0
      zkas/src/parser.rs

+ 293 - 0
zkas/Cargo.lock

@@ -0,0 +1,293 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "ansi_term"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.51"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "2.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
+name = "colour"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a27e4532f26f510c24bb8477d963c0c3ef27e293c3b2c507cccb0536d493201a"
+dependencies = [
+ "crossterm",
+]
+
+[[package]]
+name = "crossterm"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c36c10130df424b2f3552fcc2ddcd9b28a27b1e54b358b45874f88d1ca6888c"
+dependencies = [
+ "bitflags",
+ "crossterm_winapi",
+ "lazy_static",
+ "libc",
+ "mio",
+ "parking_lot",
+ "signal-hook",
+ "winapi",
+]
+
+[[package]]
+name = "crossterm_winapi"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0da8964ace4d3e4a044fd027919b2237000b24315a37c916f61809f1ff2140b9"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.112"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
+
+[[package]]
+name = "lock_api"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "mio"
+version = "0.7.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
+dependencies = [
+ "libc",
+ "log",
+ "miow",
+ "ntapi",
+ "winapi",
+]
+
+[[package]]
+name = "miow"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "ntapi"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
+dependencies = [
+ "cfg-if",
+ "instant",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "signal-hook"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729"
+dependencies = [
+ "libc",
+ "mio",
+ "signal-hook-registry",
+]
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
+
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "unicode-width"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+
+[[package]]
+name = "vec_map"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "zkas"
+version = "0.0.1"
+dependencies = [
+ "anyhow",
+ "clap",
+ "colour",
+]

+ 13 - 0
zkas/Cargo.toml

@@ -0,0 +1,13 @@
+[package]
+name = "zkas"
+version = "0.0.1"
+homepage = "https://dark.fi"
+authors = ["darkfi <dev@dark.fi>"]
+repository = "https://github.com/darkrenaissance/darkfi"
+license = "AGPL-3.0-only"
+edition = "2021"
+
+[dependencies]
+anyhow = "1.0.49"
+clap = "2.34.0"
+colour = "0.6.0"

+ 34 - 0
zkas/Makefile

@@ -0,0 +1,34 @@
+.POSIX:
+
+# Cargo binary
+CARGO = cargo
+
+BINS = zkas
+
+# Dependencies which should force the binaries to be rebuilt
+BINDEPS = \
+	Cargo.toml \
+	$(shell find src -type f)
+
+all: $(BINS)
+
+$(BINS): $(BINDEPS)
+	$(CARGO) build --release --all-features --bin $@
+	cp -f target/release/$@ $@
+
+test:
+	$(CARGO) test --release --all-features
+
+fix:
+	$(CARGO) clippy --release --all-features --fix --allow-dirty
+
+clippy:
+	$(CARGO) clippy --release --all-features
+
+clean:
+	rm -f $(BINS)
+
+distclean: clean
+	rm -rf target
+
+.PHONY: all test fix clippy clean distclean

+ 22 - 0
zkas/src/bin/zkas.rs

@@ -0,0 +1,22 @@
+use anyhow::Result;
+use clap::clap_app;
+use std::fs::read_to_string;
+
+use zkas::lexer::lex;
+
+fn main() -> Result<()> {
+    let args = clap_app!(zkas =>
+        (@arg INPUT: +required "ZK script to compile")
+    )
+    .get_matches();
+
+    let filename = args.value_of("INPUT").unwrap();
+    let source = read_to_string(filename)?;
+    let tokens = lex(filename, source.chars());
+
+    println!("{:#?}", tokens);
+
+    //let ast = parse(tokens);
+
+    Ok(())
+}

+ 73 - 0
zkas/src/error.rs

@@ -0,0 +1,73 @@
+use colour::{e_prnt_ln, e_red};
+
+pub struct LexerError {
+    file: String,
+    lines: Vec<String>,
+}
+
+impl LexerError {
+    pub fn new(file: &str, lines: Vec<String>) -> Self {
+        LexerError { file: file.to_string(), lines }
+    }
+
+    pub fn invalid_token(&self, t: char, ln: usize, col: usize) {
+        let err_msg = format!("Invalid token `{}` on line {} (column {})\n", t, ln, col);
+        let dbg_msg = format!("{}:{}:{}: {}", self.file, ln, col, self.lines[ln - 1]);
+        let pad = dbg_msg.split(": ").next().unwrap().len() + col + 2;
+        let caret = format!("{:width$}^", "", width = pad);
+        let msg = format!("{}\n{}\n{}", err_msg, dbg_msg, caret);
+        LexerError::lexer_error(&msg);
+    }
+
+    pub fn invalid_string(&self, s: &str, ln: usize, col: usize) {
+        let err_msg = format!("Invalid ending in string `{}` on line {} (column {})", s, ln, col);
+        let dbg_msg = format!("{}:{}:{}: {}", self.file, ln, col, self.lines[ln - 1]);
+        let pad = dbg_msg.split(": ").next().unwrap().len() + col + 2;
+        let caret = format!("{:width$}^", "", width = pad);
+        let msg = format!("{}\n{}\n{}", err_msg, dbg_msg, caret);
+        LexerError::lexer_error(&msg);
+    }
+
+    pub fn invalid_symbol(&self, s: &str, ln: usize, col: usize) {
+        let err_msg = format!("Illegal char `{}` for symbol on line {} (column {})", s, ln, col);
+        let dbg_msg = format!("{}:{}:{}: {}", self.file, ln, col, self.lines[ln - 1]);
+        let pad = dbg_msg.split(": ").next().unwrap().len() + col + 2;
+        let caret = format!("{:width$}^", "", width = pad);
+        let msg = format!("{}\n{}\n{}", err_msg, dbg_msg, caret);
+        LexerError::lexer_error(&msg);
+    }
+
+    fn lexer_error(msg: &str) {
+        e_red!("Lexer error: ");
+        e_prnt_ln!("{}", msg);
+        std::process::exit(1);
+    }
+}
+
+pub struct ParserError {
+    file: String,
+    lines: Vec<String>,
+}
+
+impl ParserError {
+    pub fn new(file: &str, lines: Vec<String>) -> Self {
+        ParserError { file: file.to_string(), lines }
+    }
+
+    pub fn invalid_section_declaration(&self, s: &str, m: &str, ln: usize, col: usize) {
+        let err_msg =
+            format!("Invalid `{}` section declaration on line {} (column {})", s, ln, col);
+        let err_msg = format!("{}\n{}", err_msg, m);
+        let dbg_msg = format!("{}:{}:{}: {}", self.file, ln, col, self.lines[ln - 1]);
+        let pad = dbg_msg.split(": ").next().unwrap().len() + col + 2;
+        let caret = format!("{:width$}^", "", width = pad);
+        let msg = format!("{}\n{}\n{}", err_msg, dbg_msg, caret);
+        ParserError::parser_error(&msg);
+    }
+
+    fn parser_error(msg: &str) {
+        e_red!("Parser error: ");
+        e_prnt_ln!("{}", msg);
+        std::process::exit(1);
+    }
+}

+ 208 - 0
zkas/src/lexer.rs

@@ -0,0 +1,208 @@
+use std::str::Chars;
+
+use crate::error::LexerError;
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum TokenType {
+    Symbol,
+    String,
+    LeftBrace,
+    RightBrace,
+    LeftParen,
+    RightParen,
+    Comma,
+    Semicolon,
+    Colon,
+    Assign,
+}
+
+const SPECIAL_CHARS: [char; 7] = ['{', '}', '(', ')', ',', ';', '='];
+
+#[derive(Clone, Debug)]
+pub struct Token {
+    pub token: String,
+    pub token_type: TokenType,
+    pub line: usize,
+    pub column: usize,
+}
+
+impl Token {
+    fn new(token: String, token_type: TokenType, line: usize, column: usize) -> Self {
+        Token { token, token_type, line, column }
+    }
+}
+
+pub fn lex(filename: &str, source: Chars) -> Vec<Token> {
+    // For nice error reporting, we'll load everything into a string vector
+    // so we have references to lines.
+    let lines: Vec<String> = source.as_str().lines().map(|x| x.to_string()).collect();
+    let lexer_error = LexerError::new(filename, lines);
+
+    let mut tokens = vec![];
+    let mut lineno = 1;
+    let mut column = 0;
+
+    // We use these as a buffer to keep strings/symbols.
+    let mut strbuf = String::new();
+    let mut symbuf = String::new();
+
+    // We use these to keep state when iterating
+    let mut in_comment = false;
+    let mut in_string = false;
+    let mut in_symbol = false;
+
+    #[allow(clippy::explicit_counter_loop)]
+    for c in source {
+        column += 1;
+
+        if c == '\n' {
+            if in_symbol {
+                in_symbol = false;
+                tokens.push(Token::new(
+                    symbuf.clone(),
+                    TokenType::Symbol,
+                    lineno,
+                    column - symbuf.len(),
+                ));
+                symbuf = String::new();
+            }
+
+            if in_string {
+                // TODO: Allow newlines in strings?
+                lexer_error.invalid_string(&strbuf, lineno, column);
+            }
+
+            in_comment = false;
+            lineno += 1;
+            column = 0;
+            continue
+        }
+
+        if c == '#' || in_comment {
+            if in_symbol {
+                in_symbol = false;
+                tokens.push(Token::new(
+                    symbuf.clone(),
+                    TokenType::Symbol,
+                    lineno,
+                    column - symbuf.len(),
+                ));
+                symbuf = String::new();
+            }
+
+            if in_string {
+                strbuf.push(c);
+                continue
+            }
+
+            in_comment = true;
+            continue
+        }
+
+        if c.is_whitespace() {
+            if in_symbol {
+                in_symbol = false;
+                tokens.push(Token::new(
+                    symbuf.clone(),
+                    TokenType::Symbol,
+                    lineno,
+                    column - symbuf.len(),
+                ));
+                symbuf = String::new();
+            }
+
+            continue
+        }
+
+        if !in_string && is_letter(c) {
+            in_symbol = true;
+            symbuf.push(c);
+            continue
+        }
+
+        if in_string && is_letter(c) {
+            strbuf.push(c);
+            continue
+        }
+
+        if c == '"' && !in_string {
+            if in_symbol {
+                lexer_error.invalid_symbol(&symbuf, lineno, column);
+            }
+            in_string = true;
+            continue
+        }
+
+        if c == '"' && in_string {
+            in_string = false;
+            tokens.push(Token::new(
+                strbuf.clone(),
+                TokenType::String,
+                lineno,
+                column - strbuf.len(),
+            ));
+            strbuf = String::new();
+            continue
+        }
+
+        if SPECIAL_CHARS.contains(&c) {
+            if in_symbol {
+                in_symbol = false;
+                tokens.push(Token::new(
+                    symbuf.clone(),
+                    TokenType::Symbol,
+                    lineno,
+                    column - symbuf.len(),
+                ));
+                symbuf = String::new();
+            }
+
+            match c {
+                '{' => {
+                    tokens.push(Token::new("{".to_string(), TokenType::LeftBrace, lineno, column));
+                    continue
+                }
+                '}' => {
+                    tokens.push(Token::new("}".to_string(), TokenType::RightBrace, lineno, column));
+                    continue
+                }
+                '(' => {
+                    tokens.push(Token::new("(".to_string(), TokenType::LeftParen, lineno, column));
+                    continue
+                }
+                ')' => {
+                    tokens.push(Token::new(")".to_string(), TokenType::RightParen, lineno, column));
+                    continue
+                }
+                ',' => {
+                    tokens.push(Token::new(",".to_string(), TokenType::Comma, lineno, column));
+                    continue
+                }
+                ';' => {
+                    tokens.push(Token::new(";".to_string(), TokenType::Semicolon, lineno, column));
+                    continue
+                }
+                '=' => {
+                    tokens.push(Token::new("=".to_string(), TokenType::Assign, lineno, column));
+                    continue
+                }
+                _ => lexer_error.invalid_token(c, lineno, column - 1),
+            }
+            continue
+        }
+
+        lexer_error.invalid_token(c, lineno, column - 1);
+    }
+
+    tokens
+}
+
+fn is_letter(ch: char) -> bool {
+    ('a'..='z').contains(&ch) || ('A'..='Z').contains(&ch) || ch == '_'
+}
+
+/*
+fn is_digit(ch: char) -> bool {
+    ('0'..'9').contains(&ch)
+}
+*/

+ 3 - 0
zkas/src/lib.rs

@@ -0,0 +1,3 @@
+pub mod error;
+pub mod lexer;
+pub mod parser;

+ 11 - 0
zkas/src/opcode.rs

@@ -0,0 +1,11 @@
+pub enum OpCode {
+    EcAdd = 0x00,
+    EcMul = 0x01,
+    EcMulShort = 0x02,
+    EcGetX = 0x03,
+    EcGetY = 0x04,
+
+    PoseidonHash = 0x10,
+
+    ConstrainInstance = 0xf0,
+}

+ 28 - 0
zkas/src/parser.rs

@@ -0,0 +1,28 @@
+use std::str::Chars;
+
+use crate::{
+    error::ParserError,
+    lexer::{Token, TokenType},
+};
+
+pub fn parse(filename: &str, source: Chars, tokens: Vec<Token>) {
+    // For nice error reporting, we'll load everything into a string vector
+    // so we have references to lines.
+    let lines: Vec<String> = source.as_str().lines().map(|x| x.to_string()).collect();
+    let parser_error = ParserError::new(filename, lines);
+
+    // We use these to keep state when iterating
+    let mut declaring_constant = false;
+    let mut declaring_contract = false;
+    let mut declaring_circuit = false;
+
+    let mut iter = tokens.iter();
+    while let Some(t) = iter.next() {
+        // Start by declaring a section
+        if !declaring_constant && !declaring_contract && !declaring_circuit {
+            if t.token_type != TokenType::Symbol {
+                println!("FOO");
+            }
+        }
+    }
+}