mirror of
https://github.com/powdr-labs/powdr.git
synced 2026-04-20 03:03:25 -04:00
Commandline access to asm compiler.
This commit is contained in:
13
Cargo.toml
13
Cargo.toml
@@ -5,12 +5,13 @@ edition = "2021"
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
codespan-reporting = "0.11.1"
|
||||
json = "0.12.4"
|
||||
lalrpop-util = {version = "0.19.8", features = ["lexer"]}
|
||||
clap = { version = "^4.1", features = ["derive"] }
|
||||
codespan-reporting = "^0.11"
|
||||
itertools = "^0.10"
|
||||
json = "^0.12"
|
||||
lalrpop-util = {version = "^0.19", features = ["lexer"]}
|
||||
mktemp = "0.5.0"
|
||||
num-bigint = "0.4.3"
|
||||
regex = "1"
|
||||
num-bigint = "^0.4"
|
||||
|
||||
[build-dependencies]
|
||||
lalrpop = "0.19.8"
|
||||
lalrpop = "^0.19"
|
||||
|
||||
@@ -1,27 +1,84 @@
|
||||
use std::{env, fs, path::Path};
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use powdr::compiler::no_callback;
|
||||
use powdr::number::AbstractNumberType;
|
||||
use std::{fs, path::Path};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Cli {
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
/// Compiles assembly to PIL and generates fixed and witness columns.
|
||||
Asm {
|
||||
/// Input file
|
||||
file: String,
|
||||
|
||||
/// Comma-separated list of free inputs (numbers).
|
||||
#[arg(short, long)]
|
||||
inputs: String,
|
||||
|
||||
/// Output directory for PIL file, json file and fixed and witness column data.
|
||||
#[arg(short, long)]
|
||||
#[arg(default_value_t = String::from("."))]
|
||||
output_directory: String,
|
||||
|
||||
/// Force overwriting of PIL output file.
|
||||
#[arg(short, long)]
|
||||
#[arg(default_value_t = false)]
|
||||
force: bool,
|
||||
},
|
||||
|
||||
/// Parses and prints the PIL file on stdout.
|
||||
Reformat {
|
||||
/// Input file
|
||||
file: String,
|
||||
},
|
||||
|
||||
/// Compiles the PIL file to json and generates fixed and witness columns.
|
||||
Compile {
|
||||
/// Input file
|
||||
file: String,
|
||||
/// Output directory for json file and fixed and witness column data.
|
||||
#[arg(short, long)]
|
||||
#[arg(default_value_t = String::from("."))]
|
||||
output_directory: String,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if env::args().nth(1).unwrap() == "--asm" {
|
||||
let file_name = env::args().nth(2).unwrap();
|
||||
let contents = fs::read_to_string(Path::new(&file_name)).unwrap();
|
||||
match powdr::asm_compiler::compile(Some(&file_name), &contents) {
|
||||
Ok(pil) => println!("{pil}"),
|
||||
Err(err) => err.output_to_stderr(),
|
||||
match Cli::parse().command {
|
||||
Commands::Asm {
|
||||
file,
|
||||
inputs,
|
||||
output_directory,
|
||||
force,
|
||||
} => {
|
||||
let inputs = inputs
|
||||
.split(',')
|
||||
.map(|x| x.parse().unwrap())
|
||||
.collect::<Vec<AbstractNumberType>>();
|
||||
powdr::compiler::compile_asm(&file, inputs, Path::new(&output_directory), force);
|
||||
}
|
||||
} else if env::args().nth(1).unwrap() == "--reformat" {
|
||||
let file_name = env::args().nth(2).unwrap();
|
||||
let contents = fs::read_to_string(Path::new(&file_name)).unwrap();
|
||||
match powdr::parser::parse(Some(&file_name), &contents) {
|
||||
Ok(ast) => println!("{ast}"),
|
||||
Err(err) => err.output_to_stderr(),
|
||||
Commands::Reformat { file } => {
|
||||
let contents = fs::read_to_string(&file).unwrap();
|
||||
match powdr::parser::parse(Some(&file), &contents) {
|
||||
Ok(ast) => println!("{ast}"),
|
||||
Err(err) => err.output_to_stderr(),
|
||||
}
|
||||
}
|
||||
Commands::Compile {
|
||||
file,
|
||||
output_directory,
|
||||
} => {
|
||||
powdr::compiler::compile_pil(
|
||||
Path::new(&file),
|
||||
Path::new(&output_directory),
|
||||
no_callback(),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
powdr::compiler::compile_pil(
|
||||
Path::new(&env::args().nth(1).unwrap()),
|
||||
&env::current_dir().unwrap(),
|
||||
no_callback(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,12 @@ use std::fs;
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::path::Path;
|
||||
|
||||
use itertools::Itertools;
|
||||
use num_bigint::Sign;
|
||||
|
||||
use crate::number::{abstract_to_degree, AbstractNumberType, DegreeType};
|
||||
use crate::parser::ast::PILFile;
|
||||
use crate::{analyzer, commit_evaluator, constant_evaluator, json_exporter};
|
||||
use crate::{analyzer, asm_compiler, commit_evaluator, constant_evaluator, json_exporter};
|
||||
|
||||
pub fn no_callback() -> Option<fn(&str) -> Option<AbstractNumberType>> {
|
||||
None
|
||||
@@ -45,6 +46,52 @@ pub fn compile_pil_ast(
|
||||
)
|
||||
}
|
||||
|
||||
/// Compiles a .asm file, outputs the PIL on stdout and tries to generate
|
||||
/// fixed and witness columns.
|
||||
pub fn compile_asm(
|
||||
file_name: &str,
|
||||
inputs: Vec<AbstractNumberType>,
|
||||
output_dir: &Path,
|
||||
force_overwrite: bool,
|
||||
) {
|
||||
let contents = fs::read_to_string(file_name).unwrap();
|
||||
let pil = asm_compiler::compile(Some(file_name), &contents).unwrap();
|
||||
let pil_file_name = output_dir.join(format!(
|
||||
"{}.pil",
|
||||
Path::new(file_name).file_stem().unwrap().to_str().unwrap()
|
||||
));
|
||||
if pil_file_name.exists() && !force_overwrite {
|
||||
eprint!(
|
||||
"Target file {} already exists. Not overwriting.",
|
||||
pil_file_name.to_str().unwrap()
|
||||
);
|
||||
return;
|
||||
}
|
||||
fs::write(pil_file_name.clone(), format!("{pil}")).unwrap();
|
||||
|
||||
let query_callback = |query: &str| -> Option<AbstractNumberType> {
|
||||
let items = query.split(',').map(|s| s.trim()).collect::<Vec<_>>();
|
||||
let mut it = items.iter();
|
||||
let _current_step = it.next().unwrap();
|
||||
let current_pc = it.next().unwrap();
|
||||
assert!(it.clone().len() % 3 == 0);
|
||||
for (pc_check, input, index) in it.tuples() {
|
||||
if pc_check == current_pc {
|
||||
assert_eq!(*input, "\"input\"");
|
||||
let index: usize = index.parse().unwrap();
|
||||
return inputs.get(index).cloned();
|
||||
}
|
||||
}
|
||||
None
|
||||
};
|
||||
compile_pil_ast(
|
||||
&pil,
|
||||
pil_file_name.to_str().unwrap(),
|
||||
output_dir,
|
||||
Some(query_callback),
|
||||
);
|
||||
}
|
||||
|
||||
fn compile(
|
||||
analyzed: &analyzer::Analyzed,
|
||||
file_name: &str,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::{fs, path::Path, process::Command};
|
||||
|
||||
use itertools::Itertools;
|
||||
use powdr::compiler;
|
||||
use powdr::number::AbstractNumberType;
|
||||
|
||||
@@ -31,14 +32,12 @@ fn verify_asm(file_name: &str, inputs: Vec<AbstractNumberType>) {
|
||||
let mut it = items.iter();
|
||||
let _current_step = it.next().unwrap();
|
||||
let current_pc = it.next().unwrap();
|
||||
while let Some(pc_check) = it.next() {
|
||||
assert!(it.clone().len() % 3 == 0);
|
||||
for (pc_check, input, index) in it.tuples() {
|
||||
if pc_check == current_pc {
|
||||
assert_eq!(*it.next().unwrap(), "\"input\"");
|
||||
let index: usize = it.next().map(|s| s.parse().unwrap()).unwrap();
|
||||
return Some(inputs[index].clone());
|
||||
} else {
|
||||
it.next();
|
||||
it.next();
|
||||
assert_eq!(*input, "\"input\"");
|
||||
let index: usize = index.parse().unwrap();
|
||||
return inputs.get(index).cloned();
|
||||
}
|
||||
}
|
||||
None
|
||||
|
||||
Reference in New Issue
Block a user