Skip to content

Commit

Permalink
feat: for can iterate over ranges, compile-time values, or arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
delehef committed Jul 27, 2023
1 parent 72f221f commit 6e3ff21
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 19 deletions.
6 changes: 2 additions & 4 deletions src/compiler/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,11 @@ impl FuncVerifier<AstNode> for Form {
fn validate_types(&self, args: &[AstNode]) -> Result<()> {
match self {
Form::For => {
if matches!(args[0].class, Token::Symbol(_))
&& matches!(args[1].class, Token::Range(_))
{
if matches!(args[0].class, Token::Symbol(_)) {
Ok(())
} else {
bail!(
"`{:?}` expects [SYMBOL RANGE EXPR] but received {:?}",
"`{:?}` expects [SYMBOL ITERABLE EXPR] but received {:?}",
self,
args
)
Expand Down
27 changes: 21 additions & 6 deletions src/compiler/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use std::fmt::Debug;
use std::io::Write;

use std::sync::atomic::AtomicUsize;
use std::{unimplemented, unreachable};

use super::node::ColumnRef;
use super::tables::{ComputationTable, Scope};
Expand Down Expand Up @@ -956,17 +955,33 @@ fn apply_form(

match f {
Form::For => {
if let (Token::Symbol(i_name), Token::Range(is), body) =
(&args[0].class, &args[1].class, &args[2])
{
if let (Token::Symbol(i_name), range, body) = (&args[0].class, &args[1], &args[2]) {
let is = match &range.class {
// a for can iterate over an explicit range...
Token::Range(is) => is.to_owned(),
// ...or over [1..<compile-time evaluable value>]
_ => {
if let Some(range_exp) = reduce(&range, ctx, settings)? {
if let Expression::ArrayColumn { domain, .. } = range_exp.e() {
domain.iter().map(|&i| i as isize).collect::<Vec<_>>()
} else {
let k = range_exp.pure_eval()?.to_isize().unwrap();
(1..=k).collect::<Vec<_>>()
}
} else {
bail!("unable to iterate over {}", &range)
}
}
};

let mut l = vec![];
let mut t = Type::INFIMUM;
for i in is {
let mut for_ctx = ctx.derive(&uniquify(format!("{}-for-{}", ctx.name(), i)))?;

for_ctx.insert_symbol(
i_name,
Expression::Const(BigInt::from(*i), Fr::from_str(&i.to_string())).into(),
Expression::Const(BigInt::from(i), Fr::from_str(&i.to_string())).into(),
)?;

if let Some(r) = reduce(&body.clone(), &mut for_ctx, settings)? {
Expand Down Expand Up @@ -1246,7 +1261,7 @@ pub fn reduce(e: &AstNode, ctx: &mut Scope, settings: &CompileSettings) -> Resul
.build(),
))
} else {
bail!("tried to access `{}` at index {}", array.pretty(), i)
bail!("tried to access {} at index {}", array.pretty().bold(), i)
}
}
_ => unimplemented!(),
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,7 @@ fn rec_parse(pair: Pair<Rule>) -> Result<AstNode> {
(Some(start), Some(stop), Some(step)) => {
(start..=stop).step_by(step.try_into()?).collect()
}
x => unimplemented!("{:?}", x),
x => unimplemented!("{} -> {:?}", src, x),
};
Ok(AstNode {
class: Token::Range(range),
Expand Down
2 changes: 1 addition & 1 deletion src/corset.pest
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ nth = { "[" ~ symbol ~ expr ~ "]" }

range = _{ immediate_range | interval }
immediate_range = { "{" ~ integer+ ~ "}" }
interval = { "[" ~ ((natural ~ (":" ~ natural ~ (":" ~ natural)?)?) | expr) ~ "]" }
interval = { "[" ~ (natural ~ (":" ~ natural ~ (":" ~ natural)?)?) ~ "]" }

integer = @{ "-"? ~ natural }
natural = @{ "0x" ~ ASCII_HEX_DIGIT+ | "0b" ~ ASCII_BIN_DIGIT+ | ASCII_DIGIT+ }
Expand Down
2 changes: 1 addition & 1 deletion src/exporters/debugger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ fn render_constraints(
} => {
let mut tty = Tty::new();
pretty_expr(expr, None, &mut tty, show_types);
println!("\n{}", handle.pretty());
println!("\n- {}:", handle.pretty());
println!("{}", tty.page_feed());
}
Constraint::Plookup {
Expand Down
12 changes: 6 additions & 6 deletions tests/for.lisp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
(defcolumns A (B :ARRAY [1:10]))
(defcolumns A (B :ARRAY [4:14]))

(defconstraint test1 () (for i {1 2 3} (eq! A [B i])))
(defconstraint test1 () (for i {4 5 6} (eq! A [B i])))

(defconstraint test2 () (for i [(length B)] (eq! A [B i])))
(defconstraint test2 () (for i B (eq! A [B i])))

(defconstraint test3 () (for i [1:5]
(for j {2 4 6}
(defconstraint test3 () (for i [10:14]
(for j {4 6 8}
(for k {1 5} (eq! [B i] [B j])))))

(defconstraint test4 () (for i [5] (vanishes! (shift [B i] 1))))
(defconstraint test4 () (for i [5:10] (vanishes! (shift [B i] 1))))

0 comments on commit 6e3ff21

Please sign in to comment.