Skip to content

Commit

Permalink
made set optional
Browse files Browse the repository at this point in the history
  • Loading branch information
ScottCarda-MS committed Dec 11, 2024
1 parent 5a86a67 commit 33dfa81
Show file tree
Hide file tree
Showing 2 changed files with 282 additions and 31 deletions.
59 changes: 54 additions & 5 deletions compiler/qsc_parse/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ struct MixfixOp {
enum OpKind {
Postfix(UnOp),
Binary(BinOp, Assoc),
Assign,
AssignUpdate,
AssignBinary(BinOp),
Ternary(TernOp, TokenKind, Assoc),
Rich(fn(&mut ParserContext, Box<Expr>) -> Result<Box<ExprKind>>),
}
Expand Down Expand Up @@ -131,6 +134,20 @@ fn expr_op(s: &mut ParserContext, context: OpContext) -> Result<Box<Expr>> {
s.advance();
let kind = match op.kind {
OpKind::Postfix(kind) => Box::new(ExprKind::UnOp(kind, lhs)),
OpKind::Assign => {
let rhs = expr_op(s, OpContext::Precedence(op.precedence))?;
Box::new(ExprKind::Assign(lhs, rhs))
}
OpKind::AssignUpdate => {
let mid = expr(s)?;
token(s, TokenKind::LArrow)?;
let rhs = expr_op(s, OpContext::Precedence(op.precedence))?;
Box::new(ExprKind::AssignUpdate(lhs, mid, rhs))
}
OpKind::AssignBinary(kind) => {
let rhs = expr_op(s, OpContext::Precedence(op.precedence))?;
Box::new(ExprKind::AssignOp(kind, lhs, rhs))
}
OpKind::Binary(kind, assoc) => {
let precedence = next_precedence(op.precedence, assoc);
let rhs = expr_op(s, OpContext::Precedence(precedence))?;
Expand Down Expand Up @@ -212,7 +229,17 @@ fn expr_base(s: &mut ParserContext) -> Result<Box<Expr>> {
} else if token(s, TokenKind::Keyword(Keyword::Return)).is_ok() {
Ok(Box::new(ExprKind::Return(expr(s)?)))
} else if token(s, TokenKind::Keyword(Keyword::Set)).is_ok() {
expr_set(s)
// Need to rewrite the span of the expr to include the `set` keyword.
return expr(s).map(|assign| {
Box::new(Expr {
id: assign.id,
span: Span {
lo,
hi: assign.span.hi,
},
kind: assign.kind,
})
});
} else if token(s, TokenKind::Keyword(Keyword::While)).is_ok() {
Ok(Box::new(ExprKind::While(expr(s)?, stmt::parse_block(s)?)))
} else if token(s, TokenKind::Keyword(Keyword::Within)).is_ok() {
Expand Down Expand Up @@ -357,8 +384,8 @@ fn expr_array_core(s: &mut ParserContext) -> Result<Box<ExprKind>> {

s.expect(WordKinds::Size);
let second = expr(s)?;
if is_ident("size", &second.kind) && token(s, TokenKind::Eq).is_ok() {
let size = expr(s)?;
if let Some(size) = is_array_size(&second.kind) {
let size = Box::new(size.clone());
return Ok(Box::new(ExprKind::ArrayRepeat(first, size)));
}

Expand All @@ -369,8 +396,18 @@ fn expr_array_core(s: &mut ParserContext) -> Result<Box<ExprKind>> {
Ok(Box::new(ExprKind::Array(items.into_boxed_slice())))
}

fn is_ident(name: &str, kind: &ExprKind) -> bool {
matches!(kind, ExprKind::Path(PathKind::Ok(path)) if path.segments.is_none() && path.name.name.as_ref() == name)
fn is_array_size(kind: &ExprKind) -> Option<&Expr> {
match kind {
ExprKind::Assign(lhs, rhs) => match lhs.kind.as_ref() {
ExprKind::Path(PathKind::Ok(path))
if path.segments.is_none() && path.name.name.as_ref() == "size" =>
{
Some(rhs)
}
_ => None,
},
_ => None,
}
}

fn expr_range_prefix(s: &mut ParserContext) -> Result<Box<ExprKind>> {
Expand Down Expand Up @@ -572,6 +609,18 @@ fn prefix_op(name: OpName) -> Option<PrefixOp> {
#[allow(clippy::too_many_lines)]
fn mixfix_op(name: OpName) -> Option<MixfixOp> {
match name {
OpName::Token(TokenKind::Eq) => Some(MixfixOp {
kind: OpKind::Assign,
precedence: 0,
}),
OpName::Token(TokenKind::WSlashEq) => Some(MixfixOp {
kind: OpKind::AssignUpdate,
precedence: 0,
}),
OpName::Token(TokenKind::BinOpEq(kind)) => Some(MixfixOp {
kind: OpKind::AssignBinary(closed_bin_op(kind)),
precedence: 0,
}),
OpName::Token(TokenKind::RArrow) => Some(MixfixOp {
kind: OpKind::Rich(|s, input| lambda_op(s, *input, CallableKind::Function)),
precedence: LAMBDA_PRECEDENCE,
Expand Down
Loading

0 comments on commit 33dfa81

Please sign in to comment.