mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Small improvements ♻
This commit is contained in:
parent
ac788f2082
commit
16ac3f3ebc
@ -270,8 +270,8 @@ impl Spanned<&ExprBinary> {
|
|||||||
|
|
||||||
// Short-circuit boolean operations.
|
// Short-circuit boolean operations.
|
||||||
match (self.v.op.v, &lhs) {
|
match (self.v.op.v, &lhs) {
|
||||||
(BinOp::And, Value::Bool(false)) => return Value::Bool(false),
|
(BinOp::And, Value::Bool(false)) => return lhs,
|
||||||
(BinOp::Or, Value::Bool(true)) => return Value::Bool(true),
|
(BinOp::Or, Value::Bool(true)) => return lhs,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,12 +310,10 @@ impl Spanned<&ExprBinary> {
|
|||||||
let lhs = std::mem::replace(slot, Value::None);
|
let lhs = std::mem::replace(slot, Value::None);
|
||||||
*slot = op(lhs, rhs);
|
*slot = op(lhs, rhs);
|
||||||
return Value::None;
|
return Value::None;
|
||||||
|
} else if ctx.scopes.is_const(id) {
|
||||||
|
ctx.diag(error!(span, "cannot assign to constant"));
|
||||||
} else {
|
} else {
|
||||||
if ctx.scopes.is_const(id) {
|
ctx.diag(error!(span, "unknown variable"));
|
||||||
ctx.diag(error!(span, "cannot assign to constant"));
|
|
||||||
} else {
|
|
||||||
ctx.diag(error!(span, "unknown variable"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx.diag(error!(span, "cannot assign to this expression"));
|
ctx.diag(error!(span, "cannot assign to this expression"));
|
||||||
|
@ -380,42 +380,50 @@ fn stmt_let(p: &mut Parser) -> Option<Expr> {
|
|||||||
p.start_group(Group::Stmt, TokenMode::Code);
|
p.start_group(Group::Stmt, TokenMode::Code);
|
||||||
p.eat_assert(Token::Let);
|
p.eat_assert(Token::Let);
|
||||||
|
|
||||||
let pat = p.span_if(ident);
|
let pat = match p.span_if(ident) {
|
||||||
let mut rhs = None;
|
Some(pat) => pat,
|
||||||
|
None => {
|
||||||
if pat.is_some() {
|
p.expected("identifier");
|
||||||
if p.eat_if(Token::Eq) {
|
p.end_group();
|
||||||
rhs = p.span_if(expr);
|
return None;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if !p.eof() {
|
let rhs = if p.eat_if(Token::Eq) { p.span_if(expr) } else { None };
|
||||||
p.expected_at("semicolon or line break", p.last_end());
|
|
||||||
}
|
if !p.eof() {
|
||||||
} else {
|
p.expected_at("semicolon or line break", p.last_end());
|
||||||
p.expected("identifier");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p.end_group();
|
p.end_group();
|
||||||
|
|
||||||
Some(Expr::Let(ExprLet { pat: pat?, expr: rhs.map(Box::new) }))
|
Some(Expr::Let(ExprLet { pat, expr: rhs.map(Box::new) }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an if expresion.
|
/// Parse an if expresion.
|
||||||
fn expr_if(p: &mut Parser) -> Option<Expr> {
|
fn expr_if(p: &mut Parser) -> Option<Expr> {
|
||||||
p.start_group(Group::Expr, TokenMode::Code);
|
p.start_group(Group::Expr, TokenMode::Code);
|
||||||
p.eat_assert(Token::If);
|
p.eat_assert(Token::If);
|
||||||
let condition = p.span_if(expr);
|
|
||||||
|
let condition = match p.span_if(expr) {
|
||||||
|
Some(condition) => Box::new(condition),
|
||||||
|
None => {
|
||||||
|
p.end_group();
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
p.end_group();
|
p.end_group();
|
||||||
|
|
||||||
let condition = Box::new(condition?);
|
|
||||||
let if_body = Box::new(control_body(p)?);
|
let if_body = Box::new(control_body(p)?);
|
||||||
let end = p.last_end();
|
|
||||||
|
let start = p.last_end();
|
||||||
p.skip_white();
|
p.skip_white();
|
||||||
|
|
||||||
let else_body = if p.eat_if(Token::Else) {
|
let else_body = if p.eat_if(Token::Else) {
|
||||||
control_body(p).map(Box::new)
|
control_body(p).map(Box::new)
|
||||||
} else {
|
} else {
|
||||||
p.jump(end);
|
p.jump(start);
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -127,7 +127,6 @@ impl<'s> Iterator for Tokens<'s> {
|
|||||||
'=' => Token::Eq,
|
'=' => Token::Eq,
|
||||||
'<' => Token::Lt,
|
'<' => Token::Lt,
|
||||||
'>' => Token::Gt,
|
'>' => Token::Gt,
|
||||||
'?' => Token::Question,
|
|
||||||
|
|
||||||
// Identifiers.
|
// Identifiers.
|
||||||
c if is_id_start(c) => self.ident(start),
|
c if is_id_start(c) => self.ident(start),
|
||||||
@ -206,7 +205,6 @@ impl<'s> Tokens<'s> {
|
|||||||
"#if" => Token::If,
|
"#if" => Token::If,
|
||||||
"#else" => Token::Else,
|
"#else" => Token::Else,
|
||||||
"#for" => Token::For,
|
"#for" => Token::For,
|
||||||
"#in" => Token::In,
|
|
||||||
"#while" => Token::While,
|
"#while" => Token::While,
|
||||||
"#break" => Token::Break,
|
"#break" => Token::Break,
|
||||||
"#continue" => Token::Continue,
|
"#continue" => Token::Continue,
|
||||||
@ -612,7 +610,6 @@ mod tests {
|
|||||||
t!(Code: "-=" => HyphEq);
|
t!(Code: "-=" => HyphEq);
|
||||||
t!(Code: "*=" => StarEq);
|
t!(Code: "*=" => StarEq);
|
||||||
t!(Code: "/=" => SlashEq);
|
t!(Code: "/=" => SlashEq);
|
||||||
t!(Code: "?" => Question);
|
|
||||||
t!(Code: ".." => Dots);
|
t!(Code: ".." => Dots);
|
||||||
t!(Code: "=>" => Arrow);
|
t!(Code: "=>" => Arrow);
|
||||||
|
|
||||||
@ -636,7 +633,6 @@ mod tests {
|
|||||||
("if", If),
|
("if", If),
|
||||||
("else", Else),
|
("else", Else),
|
||||||
("for", For),
|
("for", For),
|
||||||
("in", In),
|
|
||||||
("while", While),
|
("while", While),
|
||||||
("break", Break),
|
("break", Break),
|
||||||
("continue", Continue),
|
("continue", Continue),
|
||||||
@ -654,6 +650,7 @@ mod tests {
|
|||||||
("not", Not),
|
("not", Not),
|
||||||
("and", And),
|
("and", And),
|
||||||
("or", Or),
|
("or", Or),
|
||||||
|
("in", In),
|
||||||
("none", Token::None),
|
("none", Token::None),
|
||||||
("false", Bool(false)),
|
("false", Bool(false)),
|
||||||
("true", Bool(true)),
|
("true", Bool(true)),
|
||||||
|
@ -61,8 +61,6 @@ pub enum Token<'s> {
|
|||||||
StarEq,
|
StarEq,
|
||||||
/// A slash followed by an equals sign: `/=`.
|
/// A slash followed by an equals sign: `/=`.
|
||||||
SlashEq,
|
SlashEq,
|
||||||
/// A question mark: `?`.
|
|
||||||
Question,
|
|
||||||
/// Two dots: `..`.
|
/// Two dots: `..`.
|
||||||
Dots,
|
Dots,
|
||||||
/// An equals sign followed by a greater-than sign: `=>`.
|
/// An equals sign followed by a greater-than sign: `=>`.
|
||||||
@ -212,30 +210,29 @@ impl<'s> Token<'s> {
|
|||||||
Self::Eq => "assignment operator",
|
Self::Eq => "assignment operator",
|
||||||
Self::EqEq => "equality operator",
|
Self::EqEq => "equality operator",
|
||||||
Self::BangEq => "inequality operator",
|
Self::BangEq => "inequality operator",
|
||||||
Self::Lt => "less than operator",
|
Self::Lt => "less-than operator",
|
||||||
Self::LtEq => "less than or equal operator",
|
Self::LtEq => "less-than or equal operator",
|
||||||
Self::Gt => "greater than operator",
|
Self::Gt => "greater-than operator",
|
||||||
Self::GtEq => "greater than or equal operator",
|
Self::GtEq => "greater-than or equal operator",
|
||||||
Self::PlusEq => "add-assign operator",
|
Self::PlusEq => "add-assign operator",
|
||||||
Self::HyphEq => "subtract-assign operator",
|
Self::HyphEq => "subtract-assign operator",
|
||||||
Self::StarEq => "multiply-assign operator",
|
Self::StarEq => "multiply-assign operator",
|
||||||
Self::SlashEq => "divide-assign operator",
|
Self::SlashEq => "divide-assign operator",
|
||||||
Self::Question => "question mark",
|
|
||||||
Self::Dots => "dots",
|
Self::Dots => "dots",
|
||||||
Self::Arrow => "arrow",
|
Self::Arrow => "arrow",
|
||||||
Self::Not => "not operator",
|
Self::Not => "operator `not`",
|
||||||
Self::And => "and operator",
|
Self::And => "operator `and`",
|
||||||
Self::Or => "or operator",
|
Self::Or => "operator `or`",
|
||||||
Self::Let => "let keyword",
|
Self::Let => "keyword `let`",
|
||||||
Self::If => "if keyword",
|
Self::If => "keyword `if`",
|
||||||
Self::Else => "else keyword",
|
Self::Else => "keyword `else`",
|
||||||
Self::For => "for keyword",
|
Self::For => "keyword `for`",
|
||||||
Self::In => "in keyword",
|
Self::In => "keyword `in`",
|
||||||
Self::While => "while keyword",
|
Self::While => "keyword `while`",
|
||||||
Self::Break => "break keyword",
|
Self::Break => "keyword `break`",
|
||||||
Self::Continue => "continue keyword",
|
Self::Continue => "keyword `continue`",
|
||||||
Self::Return => "return keyword",
|
Self::Return => "keyword `return`",
|
||||||
Self::None => "none",
|
Self::None => "`none`",
|
||||||
Self::Space(_) => "space",
|
Self::Space(_) => "space",
|
||||||
Self::Text(_) => "text",
|
Self::Text(_) => "text",
|
||||||
Self::Raw(_) => "raw block",
|
Self::Raw(_) => "raw block",
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
"Fi" + "ve"
|
"Fi" + "ve"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spacing is somewhat delicated. We only want to have spacing in the output if
|
// Spacing is somewhat delicate. We only want to have spacing in the output if
|
||||||
// there was whitespace before/after the full if-else statement. In particular,
|
// there was whitespace before/after the full if-else statement. In particular,
|
||||||
// spacing after a simple if should be retained, but spacing between the first
|
// spacing after a simple if should be retained, but spacing between the first
|
||||||
// body and the else should be ignored.
|
// body and the else should be ignored.
|
||||||
@ -53,7 +53,7 @@ a#if true {}
|
|||||||
a#if true [b] #else c
|
a#if true [b] #else c
|
||||||
|
|
||||||
// Lone else.
|
// Lone else.
|
||||||
// Error: 2:1-2:6 unexpected else keyword
|
// Error: 2:1-2:6 unexpected keyword `else`
|
||||||
// Error: 1:8-1:8 expected function name
|
// Error: 1:8-1:8 expected function name
|
||||||
#else []
|
#else []
|
||||||
|
|
||||||
|
@ -28,11 +28,15 @@
|
|||||||
// Error: 1:6-1:7 expected identifier, found integer
|
// Error: 1:6-1:7 expected identifier, found integer
|
||||||
#let 1 = 2
|
#let 1 = 2
|
||||||
|
|
||||||
// Terminated by end of line before binding name.
|
// Missing binding name.
|
||||||
// Error: 1:5-1:5 expected identifier
|
// Error: 1:5-1:5 expected identifier
|
||||||
#let
|
#let
|
||||||
x = 5
|
x = 5
|
||||||
|
|
||||||
|
// Missing right-hand side.
|
||||||
|
// Error: 1:9-1:9 expected expression
|
||||||
|
#let a =
|
||||||
|
|
||||||
// No name at all.
|
// No name at all.
|
||||||
// Error: 1:11-1:11 expected identifier
|
// Error: 1:11-1:11 expected identifier
|
||||||
The Fi#let;rst
|
The Fi#let;rst
|
||||||
|
@ -254,7 +254,7 @@ fn parse_metadata(src: &str, map: &LineMap) -> (bool, SpanVec<Diag>) {
|
|||||||
let pos = |s: &mut Scanner| -> Pos {
|
let pos = |s: &mut Scanner| -> Pos {
|
||||||
let (delta, _, column) = (num(s), s.eat_assert(':'), num(s));
|
let (delta, _, column) = (num(s), s.eat_assert(':'), num(s));
|
||||||
let line = i as u32 + 1 + delta;
|
let line = i as u32 + 1 + delta;
|
||||||
map.pos(Location { line, column }).unwrap()
|
map.pos(Location::new(line, column)).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut s = Scanner::new(rest);
|
let mut s = Scanner::new(rest);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user