Improved compiler error output and handling return values
This commit is contained in:
parent
8781fc72f2
commit
147e5ee18a
2 changed files with 141 additions and 14 deletions
|
@ -7,7 +7,7 @@ use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::blocklang::*;
|
use crate::blocklang::*;
|
||||||
use synfx_dsp_jit::ASTNode;
|
use synfx_dsp_jit::{ASTNode, JITCompileError};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct JASTNode {
|
struct JASTNode {
|
||||||
|
@ -186,6 +186,7 @@ pub enum BlkJITCompileError {
|
||||||
TooManyInputs(String, usize),
|
TooManyInputs(String, usize),
|
||||||
WrongNumberOfChilds(String, usize, usize),
|
WrongNumberOfChilds(String, usize, usize),
|
||||||
UnassignedInput(String, usize, String),
|
UnassignedInput(String, usize, String),
|
||||||
|
JITCompileError(JITCompileError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Block2JITCompiler {
|
pub struct Block2JITCompiler {
|
||||||
|
@ -251,7 +252,19 @@ impl Block2JITCompiler {
|
||||||
// TODO: handle results properly, like remembering the most recent result
|
// TODO: handle results properly, like remembering the most recent result
|
||||||
// and append it to the end of the statements block. so that a temporary
|
// and append it to the end of the statements block. so that a temporary
|
||||||
// variable is created.
|
// variable is created.
|
||||||
"<r>" | "->" | "<res>" => {
|
"<r>" => {
|
||||||
|
if let Some((_in, out, first)) = node.first_child() {
|
||||||
|
let out = if out.len() > 0 { Some(out) } else { None };
|
||||||
|
let childs = vec![
|
||||||
|
self.trans2bjit(&first, out)?,
|
||||||
|
BlkASTNode::new_get(0, "_res_")
|
||||||
|
];
|
||||||
|
Ok(BlkASTNode::new_area(childs))
|
||||||
|
} else {
|
||||||
|
Err(BlkJITCompileError::BadTree(node.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"->" => {
|
||||||
if let Some((_in, out, first)) = node.first_child() {
|
if let Some((_in, out, first)) = node.first_child() {
|
||||||
let out = if out.len() > 0 { Some(out) } else { None };
|
let out = if out.len() > 0 { Some(out) } else { None };
|
||||||
self.trans2bjit(&first, out)
|
self.trans2bjit(&first, out)
|
||||||
|
@ -260,11 +273,15 @@ impl Block2JITCompiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"value" => Ok(BlkASTNode::new_literal(&node.0.borrow().lbl)?),
|
"value" => Ok(BlkASTNode::new_literal(&node.0.borrow().lbl)?),
|
||||||
"set" => {
|
"set" | "<res>" => {
|
||||||
if let Some((_in, out, first)) = node.first_child() {
|
if let Some((_in, out, first)) = node.first_child() {
|
||||||
let out = if out.len() > 0 { Some(out) } else { None };
|
let out = if out.len() > 0 { Some(out) } else { None };
|
||||||
let expr = self.trans2bjit(&first, out)?;
|
let expr = self.trans2bjit(&first, out)?;
|
||||||
Ok(BlkASTNode::new_set(&node.0.borrow().lbl, expr))
|
if &node.0.borrow().typ[..] == "<res>" {
|
||||||
|
Ok(BlkASTNode::new_set("_res_", expr))
|
||||||
|
} else {
|
||||||
|
Ok(BlkASTNode::new_set(&node.0.borrow().lbl, expr))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(BlkJITCompileError::BadTree(node.clone()))
|
Err(BlkJITCompileError::BadTree(node.clone()))
|
||||||
}
|
}
|
||||||
|
@ -306,16 +323,30 @@ impl Block2JITCompiler {
|
||||||
let cnt = self.lang.borrow().type_output_count(optype);
|
let cnt = self.lang.borrow().type_output_count(optype);
|
||||||
if cnt > 1 {
|
if cnt > 1 {
|
||||||
let mut area = vec![];
|
let mut area = vec![];
|
||||||
area.push(BlkASTNode::new_node(
|
|
||||||
id,
|
|
||||||
my_out.clone(),
|
|
||||||
&node.0.borrow().typ,
|
|
||||||
&node.0.borrow().lbl,
|
|
||||||
childs,
|
|
||||||
));
|
|
||||||
|
|
||||||
for i in 0..cnt {
|
let oname = self.lang.borrow().get_output_name_at_index(optype, 0);
|
||||||
|
|
||||||
|
if let Some(oname) = oname {
|
||||||
|
let tmp_var = self.next_tmpvar_name(&oname);
|
||||||
|
|
||||||
|
area.push(BlkASTNode::new_set(
|
||||||
|
&tmp_var,
|
||||||
|
BlkASTNode::new_node(
|
||||||
|
id,
|
||||||
|
my_out.clone(),
|
||||||
|
&node.0.borrow().typ,
|
||||||
|
&node.0.borrow().lbl,
|
||||||
|
childs,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
self.store_idout_var(id, &oname, &tmp_var);
|
||||||
|
} else {
|
||||||
|
return Err(BlkJITCompileError::NoOutputAtIdx(optype.to_string(), 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 1..cnt {
|
||||||
let oname = self.lang.borrow().get_output_name_at_index(optype, i);
|
let oname = self.lang.borrow().get_output_name_at_index(optype, i);
|
||||||
|
|
||||||
if let Some(oname) = oname {
|
if let Some(oname) = oname {
|
||||||
let tmp_var = self.next_tmpvar_name(&oname);
|
let tmp_var = self.next_tmpvar_name(&oname);
|
||||||
|
|
||||||
|
@ -323,6 +354,7 @@ impl Block2JITCompiler {
|
||||||
&tmp_var,
|
&tmp_var,
|
||||||
BlkASTNode::new_get(0, &format!("%{}", i)),
|
BlkASTNode::new_get(0, &format!("%{}", i)),
|
||||||
));
|
));
|
||||||
|
|
||||||
self.store_idout_var(id, &oname, &tmp_var);
|
self.store_idout_var(id, &oname, &tmp_var);
|
||||||
} else {
|
} else {
|
||||||
return Err(BlkJITCompileError::NoOutputAtIdx(optype.to_string(), i));
|
return Err(BlkJITCompileError::NoOutputAtIdx(optype.to_string(), i));
|
||||||
|
@ -625,4 +657,96 @@ mod test {
|
||||||
assert_float_eq!(ret, 0.5 / 0.0);
|
assert_float_eq!(ret, 0.5 / 0.0);
|
||||||
ctx.borrow_mut().free();
|
ctx.borrow_mut().free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_blocklang_divrem() {
|
||||||
|
// &sig1 on second output:
|
||||||
|
let (ctx, mut fun) = new_jit_fun(|bf| {
|
||||||
|
bf.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())).unwrap();
|
||||||
|
bf.instanciate_at(0, 0, 2, "value", Some("-0.4".to_string())).unwrap();
|
||||||
|
bf.instanciate_at(0, 1, 1, "/%", None);
|
||||||
|
bf.instanciate_at(0, 2, 2, "set", Some("&sig1".to_string())).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
let (s1, _, ret) = fun.exec_2in_2out(0.0, 0.0);
|
||||||
|
|
||||||
|
assert_float_eq!(s1, 0.3);
|
||||||
|
assert_float_eq!(ret, -0.75);
|
||||||
|
ctx.borrow_mut().free();
|
||||||
|
|
||||||
|
// &sig1 on first output:
|
||||||
|
let (ctx, mut fun) = new_jit_fun(|bf| {
|
||||||
|
bf.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())).unwrap();
|
||||||
|
bf.instanciate_at(0, 0, 2, "value", Some("-0.4".to_string())).unwrap();
|
||||||
|
bf.instanciate_at(0, 1, 1, "/%", None);
|
||||||
|
bf.instanciate_at(0, 2, 1, "set", Some("&sig1".to_string())).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
let (s1, _, ret) = fun.exec_2in_2out(0.0, 0.0);
|
||||||
|
|
||||||
|
assert_float_eq!(ret, 0.3);
|
||||||
|
assert_float_eq!(s1, -0.75);
|
||||||
|
ctx.borrow_mut().free();
|
||||||
|
|
||||||
|
// &sig1 on second output, but swapped outputs:
|
||||||
|
let (ctx, mut fun) = new_jit_fun(|bf| {
|
||||||
|
bf.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())).unwrap();
|
||||||
|
bf.instanciate_at(0, 0, 2, "value", Some("-0.4".to_string())).unwrap();
|
||||||
|
bf.instanciate_at(0, 1, 1, "/%", None);
|
||||||
|
bf.instanciate_at(0, 2, 2, "set", Some("&sig1".to_string())).unwrap();
|
||||||
|
bf.shift_port(0, 1, 1, 0, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
let (s1, _, ret) = fun.exec_2in_2out(0.0, 0.0);
|
||||||
|
|
||||||
|
assert_float_eq!(ret, 0.3);
|
||||||
|
assert_float_eq!(s1, -0.75);
|
||||||
|
ctx.borrow_mut().free();
|
||||||
|
|
||||||
|
// &sig1 on first output, but swapped outputs:
|
||||||
|
let (ctx, mut fun) = new_jit_fun(|bf| {
|
||||||
|
bf.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())).unwrap();
|
||||||
|
bf.instanciate_at(0, 0, 2, "value", Some("-0.4".to_string())).unwrap();
|
||||||
|
bf.instanciate_at(0, 1, 1, "/%", None);
|
||||||
|
bf.instanciate_at(0, 2, 1, "set", Some("&sig1".to_string())).unwrap();
|
||||||
|
bf.shift_port(0, 1, 1, 0, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
let (s1, _, ret) = fun.exec_2in_2out(0.0, 0.0);
|
||||||
|
|
||||||
|
assert_float_eq!(s1, 0.3);
|
||||||
|
assert_float_eq!(ret, -0.75);
|
||||||
|
ctx.borrow_mut().free();
|
||||||
|
|
||||||
|
// &sig1 on first output, but swapped inputs:
|
||||||
|
let (ctx, mut fun) = new_jit_fun(|bf| {
|
||||||
|
bf.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())).unwrap();
|
||||||
|
bf.instanciate_at(0, 0, 2, "value", Some("-0.4".to_string())).unwrap();
|
||||||
|
bf.instanciate_at(0, 1, 1, "/%", None);
|
||||||
|
bf.instanciate_at(0, 2, 1, "set", Some("&sig1".to_string())).unwrap();
|
||||||
|
bf.shift_port(0, 1, 1, 0, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
let (s1, _, ret) = fun.exec_2in_2out(0.0, 0.0);
|
||||||
|
|
||||||
|
assert_float_eq!(s1, -1.33333);
|
||||||
|
assert_float_eq!(ret, -0.1);
|
||||||
|
ctx.borrow_mut().free();
|
||||||
|
|
||||||
|
// &sig1 on first output, but swapped inputs and outputs:
|
||||||
|
let (ctx, mut fun) = new_jit_fun(|bf| {
|
||||||
|
bf.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())).unwrap();
|
||||||
|
bf.instanciate_at(0, 0, 2, "value", Some("-0.4".to_string())).unwrap();
|
||||||
|
bf.instanciate_at(0, 1, 1, "/%", None);
|
||||||
|
bf.instanciate_at(0, 2, 1, "set", Some("&sig1".to_string())).unwrap();
|
||||||
|
bf.shift_port(0, 1, 1, 0, false);
|
||||||
|
bf.shift_port(0, 1, 1, 0, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
let (s1, _, ret) = fun.exec_2in_2out(0.0, 0.0);
|
||||||
|
|
||||||
|
assert_float_eq!(ret, -1.33333);
|
||||||
|
assert_float_eq!(s1, -0.1);
|
||||||
|
ctx.borrow_mut().free();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@ use super::{
|
||||||
FeedbackFilter, GraphMessage, NodeOp, NodeProg, MAX_ALLOCATED_NODES, MAX_AVAIL_CODE_ENGINES,
|
FeedbackFilter, GraphMessage, NodeOp, NodeProg, MAX_ALLOCATED_NODES, MAX_AVAIL_CODE_ENGINES,
|
||||||
MAX_AVAIL_TRACKERS, MAX_INPUTS, MAX_SCOPES, UNUSED_MONITOR_IDX,
|
MAX_AVAIL_TRACKERS, MAX_INPUTS, MAX_SCOPES, UNUSED_MONITOR_IDX,
|
||||||
};
|
};
|
||||||
|
use crate::block_compiler::{BlkJITCompileError, Block2JITCompiler};
|
||||||
use crate::blocklang::*;
|
use crate::blocklang::*;
|
||||||
use crate::blocklang_def;
|
use crate::blocklang_def;
|
||||||
use crate::block_compiler::{Block2JITCompiler, BlkJITCompileError};
|
|
||||||
use crate::dsp::tracker::{PatternData, Tracker};
|
use crate::dsp::tracker::{PatternData, Tracker};
|
||||||
use crate::dsp::{node_factory, Node, NodeId, NodeInfo, ParamId, SAtom};
|
use crate::dsp::{node_factory, Node, NodeId, NodeInfo, ParamId, SAtom};
|
||||||
use crate::monitor::{new_monitor_processor, MinMaxMonitorSamples, Monitor, MON_SIG_CNT};
|
use crate::monitor::{new_monitor_processor, MinMaxMonitorSamples, Monitor, MON_SIG_CNT};
|
||||||
|
@ -708,7 +708,10 @@ impl NodeConfigurator {
|
||||||
// let ast = block_compiler::compile(block_fun);
|
// let ast = block_compiler::compile(block_fun);
|
||||||
if let Some(cod) = self.code_engines.get_mut(id) {
|
if let Some(cod) = self.code_engines.get_mut(id) {
|
||||||
use synfx_dsp_jit::build::*;
|
use synfx_dsp_jit::build::*;
|
||||||
cod.upload(ast);
|
match cod.upload(ast) {
|
||||||
|
Err(e) => return Err(BlkJITCompileError::JITCompileError(e)),
|
||||||
|
Ok(()) => (),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue