forked from AbleScript/ablescript
Changed variable declaration / assignment and equals syntax:
- `dim <ident> [value];` is now used for declaration - `<value> =: <assignable>` is used for assignments - As token `=` doesn't cause any ambiguity now, it can be used for equals operation
This commit is contained in:
parent
ea931d1f4b
commit
e3d49c9c1f
|
@ -113,7 +113,7 @@ pub enum Stmt {
|
|||
Break,
|
||||
HopBack,
|
||||
|
||||
Var {
|
||||
Dim {
|
||||
ident: Spanned<String>,
|
||||
init: Option<Spanned<Expr>>,
|
||||
},
|
||||
|
@ -186,7 +186,7 @@ impl BinOpKind {
|
|||
Token::FwdSlash => Ok(Self::Divide),
|
||||
Token::GreaterThan => Ok(Self::Greater),
|
||||
Token::LessThan => Ok(Self::Less),
|
||||
Token::EqualEqual => Ok(Self::Equal),
|
||||
Token::Equals => Ok(Self::Equal),
|
||||
Token::Aint => Ok(Self::NotEqual),
|
||||
t => Err(crate::error::ErrorKind::UnexpectedToken(t)),
|
||||
}
|
||||
|
|
|
@ -209,7 +209,7 @@ impl ExecEnv {
|
|||
Stmt::Print(expr) => {
|
||||
println!("{}", self.eval_expr(expr)?);
|
||||
}
|
||||
Stmt::Var { ident, init } => {
|
||||
Stmt::Dim { ident, init } => {
|
||||
let init = match init {
|
||||
Some(e) => self.eval_expr(e)?,
|
||||
None => Value::Nul,
|
||||
|
@ -719,7 +719,7 @@ mod tests {
|
|||
let mut env = ExecEnv::new();
|
||||
|
||||
// Declaring and reading from a variable.
|
||||
eval(&mut env, "var foo = 32; var bar = foo + 1;").unwrap();
|
||||
eval(&mut env, "dim foo 32; dim bar foo + 1;").unwrap();
|
||||
assert_eq!(
|
||||
env.get_var(&Spanned {
|
||||
item: "bar".to_owned(),
|
||||
|
@ -730,7 +730,7 @@ mod tests {
|
|||
);
|
||||
|
||||
// Assigning an existing variable.
|
||||
eval(&mut env, "foo = /*hi*/;").unwrap();
|
||||
eval(&mut env, "/*hi*/ =: foo;").unwrap();
|
||||
assert_eq!(
|
||||
env.get_var(&Spanned {
|
||||
item: "foo".to_owned(),
|
||||
|
@ -742,7 +742,7 @@ mod tests {
|
|||
|
||||
// But variable assignment should be illegal when the variable
|
||||
// hasn't been declared in advance.
|
||||
eval(&mut env, "invalid = bar + 1;").unwrap_err();
|
||||
eval(&mut env, "bar + 1 =: invalid;").unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -753,7 +753,7 @@ mod tests {
|
|||
let mut env = ExecEnv::new();
|
||||
eval(
|
||||
&mut env,
|
||||
"var foo = 1; foo = 2; if (always) { var foo = 3; foo = 4; }",
|
||||
"dim foo 1; 2 =: foo; if (always) { dim foo 3; 4 =: foo; }",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -40,8 +40,8 @@ pub enum Token {
|
|||
#[token("/")]
|
||||
FwdSlash,
|
||||
|
||||
#[token("=")]
|
||||
Equal,
|
||||
#[token("=:")]
|
||||
Assign,
|
||||
|
||||
#[token("<=")]
|
||||
Arrow,
|
||||
|
@ -53,8 +53,8 @@ pub enum Token {
|
|||
#[token(">")]
|
||||
GreaterThan,
|
||||
|
||||
#[token("==")]
|
||||
EqualEqual,
|
||||
#[token("=")]
|
||||
Equals,
|
||||
|
||||
#[token("ain't")]
|
||||
Aint,
|
||||
|
@ -68,8 +68,8 @@ pub enum Token {
|
|||
Bff,
|
||||
|
||||
/// Variable bro
|
||||
#[token("var")]
|
||||
Var,
|
||||
#[token("dim")]
|
||||
Dim,
|
||||
|
||||
/// Prints the preceding things
|
||||
#[token("print")]
|
||||
|
@ -152,24 +152,25 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn simple_fn() {
|
||||
let code = "functio test() { var a = 3; if a == 3 { a print } }";
|
||||
let code = "functio test() { dim var 3; if (var = 3) { var print } }";
|
||||
let expected = &[
|
||||
Functio,
|
||||
Identifier("test".to_owned()),
|
||||
LeftParen,
|
||||
RightParen,
|
||||
LeftCurly,
|
||||
Var,
|
||||
Identifier("a".to_owned()),
|
||||
Equal,
|
||||
Dim,
|
||||
Identifier("var".to_owned()),
|
||||
Integer(3),
|
||||
Semicolon,
|
||||
If,
|
||||
Identifier("a".to_owned()),
|
||||
EqualEqual,
|
||||
LeftParen,
|
||||
Identifier("var".to_owned()),
|
||||
Equals,
|
||||
Integer(3),
|
||||
RightParen,
|
||||
LeftCurly,
|
||||
Identifier("a".to_owned()),
|
||||
Identifier("var".to_owned()),
|
||||
Print,
|
||||
RightCurly,
|
||||
RightCurly,
|
||||
|
|
|
@ -73,7 +73,7 @@ impl<'source> Parser<'source> {
|
|||
start..self.lexer.span().end,
|
||||
)),
|
||||
Token::Bff => Ok(Spanned::new(self.bff_flow()?, start..self.lexer.span().end)),
|
||||
Token::Var => Ok(Spanned::new(self.var_flow()?, start..self.lexer.span().end)),
|
||||
Token::Dim => Ok(Spanned::new(self.dim_flow()?, start..self.lexer.span().end)),
|
||||
Token::Melo => Ok(Spanned::new(
|
||||
self.melo_flow()?,
|
||||
start..self.lexer.span().end,
|
||||
|
@ -209,7 +209,7 @@ impl<'source> Parser<'source> {
|
|||
| Token::Minus
|
||||
| Token::Star
|
||||
| Token::FwdSlash
|
||||
| Token::EqualEqual
|
||||
| Token::Equals
|
||||
| Token::LessThan
|
||||
| Token::GreaterThan
|
||||
| Token::Aint => Ok(Spanned::new(
|
||||
|
@ -382,17 +382,13 @@ impl<'source> Parser<'source> {
|
|||
}
|
||||
|
||||
// Variable Assignment
|
||||
Token::Equal => {
|
||||
if let Some(Ok(assignable)) = buf.take().map(Assignable::from_expr) {
|
||||
break Stmt::Assign {
|
||||
assignable,
|
||||
value: self.expr_flow(Token::Semicolon)?,
|
||||
};
|
||||
} else {
|
||||
return Err(Error::new(
|
||||
ErrorKind::UnexpectedToken(Token::Equal),
|
||||
Token::Assign => {
|
||||
return match buf.take() {
|
||||
Some(expr) => self.assignment_flow(expr),
|
||||
None => Err(Error::new(
|
||||
ErrorKind::UnexpectedToken(Token::Assign),
|
||||
self.lexer.span(),
|
||||
));
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -546,15 +542,47 @@ impl<'source> Parser<'source> {
|
|||
}
|
||||
|
||||
/// Parse variable declaration
|
||||
fn var_flow(&mut self) -> Result<Stmt, Error> {
|
||||
fn dim_flow(&mut self) -> Result<Stmt, Error> {
|
||||
let ident = self.get_ident()?;
|
||||
let init = match self.checked_next()? {
|
||||
Token::Equal => Some(self.expr_flow(Token::Semicolon)?),
|
||||
Token::Semicolon => None,
|
||||
let mut init = None;
|
||||
loop {
|
||||
match self.checked_next()? {
|
||||
Token::Semicolon => break,
|
||||
t => init = Some(self.parse_expr(t, &mut init)?),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Stmt::Dim { ident, init })
|
||||
}
|
||||
|
||||
/// Parse assignment to assignable
|
||||
fn assignment_flow(&mut self, value: Spanned<Expr>) -> Result<Stmt, Error> {
|
||||
let ident = self.get_ident()?;
|
||||
let kind = match self.checked_next()? {
|
||||
Token::Semicolon => AssignableKind::Variable,
|
||||
Token::LeftBracket => {
|
||||
let mut indices = vec![];
|
||||
loop {
|
||||
indices.push(self.expr_flow(Token::RightBracket)?);
|
||||
match self.checked_next()? {
|
||||
Token::Semicolon => break AssignableKind::Index { indices },
|
||||
Token::LeftBracket => (),
|
||||
t => {
|
||||
return Err(Error::new(
|
||||
ErrorKind::UnexpectedToken(t),
|
||||
self.lexer.span(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
t => return Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())),
|
||||
};
|
||||
|
||||
Ok(Stmt::Var { ident, init })
|
||||
Ok(Stmt::Assign {
|
||||
assignable: Assignable { ident, kind },
|
||||
value,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse Melo flow
|
||||
|
@ -624,9 +652,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn variable_declaration() {
|
||||
let code = "var a = 42;";
|
||||
let code = "dim a 42;";
|
||||
let expected = &[Spanned {
|
||||
item: Stmt::Var {
|
||||
item: Stmt::Dim {
|
||||
ident: Spanned {
|
||||
item: "a".to_owned(),
|
||||
span: 4..5,
|
||||
|
@ -645,7 +673,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn if_flow() {
|
||||
let code = "if (a == always) { /*Buy Able products!*/ print; }";
|
||||
let code = "if (a = always) { /*Buy Able products!*/ print; }";
|
||||
let expected = &[Spanned {
|
||||
item: Stmt::If {
|
||||
cond: Spanned {
|
||||
|
@ -679,9 +707,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn tdark() {
|
||||
let code = "T-Dark { var lang = /*lang*/ + lang; }";
|
||||
let code = "T-Dark { dim lang /*lang*/ + lang; }";
|
||||
let expected = &[Spanned {
|
||||
item: Stmt::Var {
|
||||
item: Stmt::Dim {
|
||||
ident: Spanned {
|
||||
item: "script".to_owned(),
|
||||
span: 13..17,
|
||||
|
|
|
@ -25,20 +25,20 @@ owo arity_1(/*foo*/);
|
|||
owo arity_2(/*foo*/, /*bar*/);
|
||||
owo arity_3(/*foo*/, /*bar*/, /*baz*/);
|
||||
|
||||
var i1 = arity_0 * arity_1;
|
||||
dim i1 arity_0 * arity_1;
|
||||
i1(/*second*/);
|
||||
|
||||
/*----*/ print;
|
||||
|
||||
var i2 = arity_1 * arity_0;
|
||||
dim i2 arity_1 * arity_0;
|
||||
i2(/*first*/);
|
||||
|
||||
/*----*/ print;
|
||||
|
||||
var ifancy = arity_3 * arity_3;
|
||||
dim ifancy arity_3 * arity_3;
|
||||
ifancy(/*left1*/, /*right1*/, /*left2*/, /*right2*/, /*left3*/, /*right3*/);
|
||||
|
||||
/*---*/" print;
|
||||
/*---*/ print;
|
||||
|
||||
var another = arity_0 * arity_3;
|
||||
dim another arity_0 * arity_3;
|
||||
another(/*right1*/, /*right2*/, /*right3*/);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
functio helloable() {
|
||||
"´/*Hello, Able!*/ print;
|
||||
/*Hello, Able!*/ print;
|
||||
}
|
||||
|
||||
var cart = [/*able*/ <= 42, helloable <= /*hello*/];
|
||||
dim cart [/*able*/ <= 42, helloable <= /*hello*/];
|
||||
|
||||
cart[42] print;
|
||||
cart[/*hello*/]();
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
var hello = /*world*/;
|
||||
dim hello /*world*/;
|
||||
hello print;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
var data;
|
||||
dim data;
|
||||
loop {
|
||||
data read;
|
||||
data print;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
var hi = /*wonk*/;
|
||||
dim hi /*wonk*/;
|
||||
melo hi;
|
||||
hi print; owo Should error out
|
||||
|
|
|
@ -2,22 +2,22 @@ owo Pass-by-reference test
|
|||
|
||||
owo Swap two variables.
|
||||
functio swap(left, right) {
|
||||
var tmp = left;
|
||||
left = right;
|
||||
right = tmp;
|
||||
dim tmp left;
|
||||
right =: left;
|
||||
tmp =: right;
|
||||
}
|
||||
|
||||
var foo = /*hello*/;
|
||||
var bar = /*world*/;
|
||||
dim foo /*hello*/;
|
||||
dim bar /*world*/;
|
||||
|
||||
swap(foo, bar);
|
||||
|
||||
if (foo != /*world*/) {
|
||||
if (foo ain't /*world*/) {
|
||||
/*FAILED*/ print;
|
||||
/*foo should be 'world', is actually:*/ print;
|
||||
foo print;
|
||||
}
|
||||
|
||||
if (foo == /*world*/) {
|
||||
if (foo = /*world*/) {
|
||||
/*OK*/ print;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue