Skip to content

Commit 9d33776

Browse files
committed
Access to external functions from expressions
1 parent 529ad02 commit 9d33776

29 files changed

+988
-1893
lines changed

examples/filter.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,6 @@ So if you could go ahead and try to remember to do that from now on, that'd be g
8383
// Set to true if the ID is duplicate
8484
input = false.into();
8585
}
86-
Event::Plugin { id, arguments } => {
87-
println!("Script executed plugin {id} with parameters {arguments:?}");
88-
// Set to true if the script succeeded
89-
input = false.into();
90-
}
9186
Event::SetEnvelope { envelope, value } => {
9287
println!("Set envelope {envelope:?} to {value:?}");
9388
input = true.into();
@@ -157,6 +152,13 @@ So if you could go ahead and try to remember to do that from now on, that'd be g
157152
messages.push(String::from_utf8(message).unwrap());
158153
input = true.into();
159154
}
155+
Event::Function { id, arguments } => {
156+
println!(
157+
"Script executed external function {id} with parameters {arguments:?}"
158+
);
159+
// Return variable result back to interpreter
160+
input = Input::result("hello world".into());
161+
}
160162

161163
#[cfg(test)]
162164
_ => unreachable!(),

src/compiler/grammar/actions/action_set.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ use serde::{Deserialize, Serialize};
2525

2626
use crate::{
2727
compiler::{
28-
grammar::instruction::{CompilerState, Instruction},
28+
grammar::{
29+
expr::Expression,
30+
instruction::{CompilerState, Instruction},
31+
},
2932
lexer::{tokenizer::TokenInfo, word::Word, Token},
3033
CompileError, ErrorType, Value, VariableType,
3134
},
@@ -68,6 +71,12 @@ pub(crate) struct Set {
6871
pub value: Value,
6972
}
7073

74+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
75+
pub(crate) struct Let {
76+
pub name: VariableType,
77+
pub expr: Vec<Expression>,
78+
}
79+
7180
impl<'x> CompilerState<'x> {
7281
pub(crate) fn parse_set(&mut self) -> Result<(), CompileError> {
7382
let mut modifiers = Vec::new();
@@ -125,6 +134,15 @@ impl<'x> CompilerState<'x> {
125134
Ok(())
126135
}
127136

137+
pub(crate) fn parse_let(&mut self) -> Result<(), CompileError> {
138+
let name = self.tokens.unwrap_next()?;
139+
let name = self.parse_variable_name(name, false)?;
140+
let expr = self.parse_expr()?;
141+
142+
self.instructions.push(Instruction::Let(Let { name, expr }));
143+
Ok(())
144+
}
145+
128146
pub(crate) fn parse_variable_name(
129147
&mut self,
130148
token_info: TokenInfo,

src/compiler/grammar/expr/mod.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ pub(crate) enum Expression {
3737
JmpIf { val: bool, pos: u32 },
3838
Function { id: u32, num_args: u32 },
3939
ArrayAccess,
40+
ArrayBuild(u32),
4041
}
4142

4243
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
4344
pub(crate) enum Constant {
4445
Integer(i64),
4546
Float(f64),
4647
String(String),
47-
Array(Vec<Constant>),
4848
}
4949

5050
impl Eq for Constant {}
@@ -64,12 +64,6 @@ impl From<String> for Constant {
6464
}
6565
}
6666

67-
impl From<Vec<Constant>> for Constant {
68-
fn from(value: Vec<Constant>) -> Self {
69-
Constant::Array(value)
70-
}
71-
}
72-
7367
#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
7468
pub(crate) enum BinaryOperator {
7569
Add,

src/compiler/grammar/expr/parser.rs

+32-48
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ where
3333
arg_count: Vec<i32>,
3434
}
3535

36+
pub(crate) const ID_ARRAY_ACCESS: u32 = u32::MAX;
37+
pub(crate) const ID_ARRAY_BUILD: u32 = u32::MAX - 1;
38+
pub(crate) const ID_EXTERNAL: u32 = u32::MAX - 2;
39+
3640
impl<'x, F> ExpressionParser<'x, F>
3741
where
3842
F: Fn(&str, bool) -> Result<Token, String>,
@@ -106,13 +110,13 @@ where
106110
});
107111
}
108112

109-
let expr = if *id != u32::MAX {
110-
Expression::Function {
111-
id: *id,
113+
let expr = match *id {
114+
ID_ARRAY_ACCESS => Expression::ArrayAccess,
115+
ID_ARRAY_BUILD => Expression::ArrayBuild(*num_args),
116+
id => Expression::Function {
117+
id,
112118
num_args: *num_args,
113-
}
114-
} else {
115-
Expression::ArrayAccess
119+
},
116120
};
117121

118122
self.operator_stack.pop();
@@ -168,50 +172,23 @@ where
168172
.push((Token::Function { id, name, num_args }, None))
169173
}
170174
Token::OpenBracket => {
171-
if last_is_var_or_fnc {
172-
// Array access
173-
self.arg_count.push(1);
174-
self.operator_stack.push((
175-
Token::Function {
176-
id: u32::MAX,
177-
name: "[".to_string(),
178-
num_args: 2,
179-
},
180-
None,
181-
));
182-
self.operator_stack.push((token, None))
175+
// Array functions
176+
let (id, num_args, arg_count) = if last_is_var_or_fnc {
177+
(ID_ARRAY_ACCESS, 2, 1)
183178
} else {
184-
// Array literal
185-
let mut array = Vec::new();
186-
187-
loop {
188-
match self.tokenizer.next()? {
189-
Some(Token::Number(n)) => array.push(n.into()),
190-
Some(Token::String(s)) => array.push(s.into()),
191-
Some(Token::CloseBracket) => break,
192-
_ => {
193-
return Err(format!(
194-
"Invalid token {:?} in array literal",
195-
token
196-
))
197-
}
198-
}
199-
200-
match self.tokenizer.next()? {
201-
Some(Token::Comma) => {}
202-
Some(Token::CloseBracket) => break,
203-
_ => {
204-
return Err(format!(
205-
"Invalid token {:?} in array literal",
206-
token
207-
))
208-
}
209-
}
210-
}
211-
212179
self.inc_arg_count();
213-
self.output.push(Expression::Constant(array.into()))
214-
}
180+
(ID_ARRAY_BUILD, 0, 0)
181+
};
182+
self.arg_count.push(arg_count);
183+
self.operator_stack.push((
184+
Token::Function {
185+
id,
186+
name: String::from("array"),
187+
num_args,
188+
},
189+
None,
190+
));
191+
self.operator_stack.push((token, None));
215192
}
216193
Token::Comma => {
217194
while let Some((token, jmp_pos)) = self.operator_stack.last() {
@@ -253,6 +230,13 @@ where
253230
fn inc_arg_count(&mut self) {
254231
if let Some(x) = self.arg_count.last_mut() {
255232
*x = x.saturating_add(1);
233+
let op_pos = self.operator_stack.len() - 2;
234+
match self.operator_stack.get_mut(op_pos) {
235+
Some((Token::Function { num_args, id, .. }, _)) if *id == ID_ARRAY_BUILD => {
236+
*num_args += 1;
237+
}
238+
_ => {}
239+
}
256240
}
257241
}
258242

src/compiler/grammar/expr/tokenizer.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,10 @@ where
223223
return Err(format!("Invalid character {:?}", char::from(ch),));
224224
}
225225
};
226-
self.is_start = ch == b'(';
226+
self.is_start = matches!(
227+
token,
228+
Token::OpenParen | Token::Comma | Token::BinaryOperator(_)
229+
);
227230

228231
return if prev_token.is_some() {
229232
self.next_token.push(token);

0 commit comments

Comments
 (0)