Skip to content

Commit

Permalink
Merge pull request #217 from HigherOrderCO/feature/sc-483/add-an-opti…
Browse files Browse the repository at this point in the history
…on-to-pass-arguments-to-hvm-lang

[sc-483] Add an option to pass arguments to hvm-lang programs
  • Loading branch information
imaqtkatt authored Mar 1, 2024
2 parents 8722c96 + d7ce307 commit 2e9b3d3
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 55 deletions.
52 changes: 26 additions & 26 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 12 additions & 3 deletions src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use crate::term::{
},
display::DisplayFn,
transform::{
encode_pattern_matching::MatchErr, resolve_refs::ReferencedMainErr, simplify_ref_to_ref::CyclicDefErr,
apply_args::ArgError, encode_pattern_matching::MatchErr, resolve_refs::ReferencedMainErr,
simplify_ref_to_ref::CyclicDefErr,
},
Name,
};
Expand Down Expand Up @@ -59,8 +60,8 @@ impl Info {
self.err_counter = 0;
}

/// Checks if any error was emitted since the start of the pass,
/// Returning all the current information as a `Err(Info)`, replacing `&mut self` with an empty one.
/// Checks if any error was emitted since the start of the pass,
/// Returning all the current information as a `Err(Info)`, replacing `&mut self` with an empty one.
/// Otherwise, returns the given arg as an `Ok(T)`.
pub fn fatal<T>(&mut self, t: T) -> Result<T, Info> {
if self.err_counter == 0 { Ok(t) } else { Err(std::mem::take(self)) }
Expand Down Expand Up @@ -110,6 +111,7 @@ pub enum Error {
EntryPoint(EntryErr),
TopLevel(TopLevelErr),
Custom(String),
ArgError(ArgError),
}

impl Display for Error {
Expand All @@ -129,6 +131,7 @@ impl Error {
Error::EntryPoint(err) => write!(f, "{err}"),
Error::TopLevel(err) => write!(f, "{err}"),
Error::Custom(err) => write!(f, "{err}"),
Error::ArgError(err) => write!(f, "{err}"),
})
}
}
Expand Down Expand Up @@ -175,6 +178,12 @@ impl From<TopLevelErr> for Error {
}
}

impl From<ArgError> for Error {
fn from(value: ArgError) -> Self {
Self::ArgError(value)
}
}

#[derive(Debug, Clone)]
pub enum Warning {
MatchOnlyVars(Name),
Expand Down
21 changes: 16 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,18 @@ pub fn create_host(book: Arc<Book>, labels: Arc<Labels>, compile_opts: CompileOp
pub fn check_book(book: &mut Book) -> Result<(), Info> {
// TODO: Do the checks without having to do full compilation
// TODO: Shouldn't the check mode show warnings?
compile_book(book, CompileOpts::light())?;
compile_book(book, CompileOpts::light(), None)?;
Ok(())
}

pub fn compile_book(book: &mut Book, opts: CompileOpts) -> Result<CompileResult, Info> {
let warns = desugar_book(book, opts)?;
pub fn compile_book(
book: &mut Book,
opts: CompileOpts,
args: Option<Vec<Term>>,
) -> Result<CompileResult, Info> {
let warns = desugar_book(book, opts, args)?;
let (nets, labels) = book_to_nets(book);

let mut core_book = nets_to_hvmc(nets)?;
if opts.pre_reduce {
pre_reduce_book(&mut core_book, book.hvmc_entrypoint())?;
Expand All @@ -112,11 +117,16 @@ pub fn compile_book(book: &mut Book, opts: CompileOpts) -> Result<CompileResult,
Ok(CompileResult { core_book, labels, warns })
}

pub fn desugar_book(book: &mut Book, opts: CompileOpts) -> Result<Vec<Warning>, Info> {
pub fn desugar_book(
book: &mut Book,
opts: CompileOpts,
args: Option<Vec<Term>>,
) -> Result<Vec<Warning>, Info> {
let mut ctx = Ctx::new(book);

ctx.check_shared_names();
ctx.set_entrypoint();
ctx.apply_args(args)?;

ctx.book.encode_adts(opts.adt_encoding);
ctx.book.encode_builtins();
Expand Down Expand Up @@ -184,8 +194,9 @@ pub fn run_book(
run_opts: RunOpts,
warning_opts: WarningOpts,
compile_opts: CompileOpts,
args: Option<Vec<Term>>,
) -> Result<(Term, RunInfo), Info> {
let CompileResult { core_book, labels, warns } = compile_book(&mut book, compile_opts)?;
let CompileResult { core_book, labels, warns } = compile_book(&mut book, compile_opts, args)?;

// Turn the book into an Arc so that we can use it for logging, debugging, etc.
// from anywhere else in the program
Expand Down
14 changes: 11 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ enum Mode {
)]
comp_opts: Vec<OptArgs>,

#[arg(value_parser = |arg: &str| hvml::term::parser::parse_term(arg)
.map_err(|e| match e[0].reason() {
chumsky::error::RichReason::Many(errs) => format!("{}", &errs[0]),
_ => format!("{}", e[0].reason()),
}))]
arguments: Option<Vec<hvml::term::Term>>,

#[command(flatten)]
warn_opts: CliWarnOpts,
},
Expand Down Expand Up @@ -192,7 +199,7 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Info> {
}

let mut book = load_book(&path)?;
let compiled = compile_book(&mut book, opts)?;
let compiled = compile_book(&mut book, opts, None)?;
println!("{}", compiled.display_with_warns(warning_opts)?);
}
Mode::Desugar { path, comp_opts, lazy_mode } => {
Expand All @@ -202,7 +209,7 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Info> {
}
let mut book = load_book(&path)?;
// TODO: Shouldn't the desugar have `warn_opts` too? maybe WarningOpts::allow_all() by default
let _warns = desugar_book(&mut book, opts)?;
let _warns = desugar_book(&mut book, opts, None)?;
println!("{}", book);
}
Mode::Run {
Expand All @@ -216,6 +223,7 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Info> {
comp_opts,
warn_opts,
lazy_mode,
arguments,
} => {
if debug && lazy_mode {
return Err("Unsupported configuration, can not use debug mode `-d` with lazy mode `-L`".into());
Expand All @@ -235,7 +243,7 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Info> {
let run_opts =
RunOpts { single_core, debug, linear, lazy_mode, max_memory: max_mem, max_rewrites: max_rwts };
let (res_term, RunInfo { stats, readback_errors, net, book: _, labels: _ }) =
run_book(book, max_mem as usize, run_opts, warning_opts, opts)?;
run_book(book, max_mem as usize, run_opts, warning_opts, opts, arguments)?;

let total_rewrites = stats.rewrites.total() as f64;
let rps = total_rewrites / stats.run_time / 1_000_000.0;
Expand Down
10 changes: 1 addition & 9 deletions src/term/check/set_entrypoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ pub enum EntryErr {
NotFound(Name),
Multiple(Vec<Name>),
MultipleRules,
Arguments,
}

impl Display for EntryErr {
Expand All @@ -23,7 +22,6 @@ impl Display for EntryErr {
write!(f, "File has '{}', '{}' and '{}' definitions.", fnd[0], fnd[1], fnd[2])
}
EntryErr::MultipleRules => write!(f, "Main definition can't have more than one rule."),
EntryErr::Arguments => write!(f, "Main definition can't have any arguments."),
}
}
}
Expand Down Expand Up @@ -69,13 +67,7 @@ impl Ctx<'_> {
}

fn validate_entry_point(entry: &Definition) -> Result<Name, EntryErr> {
if entry.rules.len() > 1 {
Err(EntryErr::MultipleRules)
} else if !entry.rules[0].pats.is_empty() {
Err(EntryErr::Arguments)
} else {
Ok(entry.name.clone())
}
if entry.rules.len() > 1 { Err(EntryErr::MultipleRules) } else { Ok(entry.name.clone()) }
}

impl Book {
Expand Down
50 changes: 50 additions & 0 deletions src/term/transform/apply_args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use std::fmt::Display;

use crate::{
diagnostics::Info,
term::{Ctx, Pattern, Term},
};

#[derive(Clone, Debug)]
pub enum ArgError {
PatternArgError,
ArityArgError { expected: usize, got: usize },
}

impl Display for ArgError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ArgError::PatternArgError => write!(f, ""),
ArgError::ArityArgError { expected, got } => write!(f, "Expected {expected} arguments, got {got}."),
}
}
}

impl Ctx<'_> {
pub fn apply_args(&mut self, args: Option<Vec<Term>>) -> Result<(), Info> {
self.info.start_pass();

if let Some(entrypoint) = &self.book.entrypoint {
let main_def = &mut self.book.defs[entrypoint];

if !main_def.rules[0].pats.iter().all(|pat| matches!(pat, Pattern::Var(Some(..)))) {
self.info.def_error(entrypoint.clone(), ArgError::PatternArgError);
}

if let Some(args) = args {
let expected = main_def.rules[0].pats.len();
let got = args.len();
if expected != got {
self.info.error(ArgError::ArityArgError { expected, got });
}

main_def.convert_match_def_to_term();
let main_body = &mut self.book.defs[entrypoint].rule_mut().body;

*main_body = Term::call(main_body.clone(), args);
}
}

self.info.fatal(())
}
}
1 change: 1 addition & 0 deletions src/term/transform/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod apply_args;
pub mod definition_merge;
pub mod definition_pruning;
pub mod desugar_implicit_match_binds;
Expand Down
Loading

0 comments on commit 2e9b3d3

Please sign in to comment.