implement variable assignments
This commit is contained in:
parent
94693cce6c
commit
e772c4b2c2
|
@ -307,6 +307,10 @@ impl Semicolon {
|
||||||
SemicolonStatement::VariableDeclaration(decl) => {
|
SemicolonStatement::VariableDeclaration(decl) => {
|
||||||
decl.analyze_semantics(function_names, macro_names, handler)
|
decl.analyze_semantics(function_names, macro_names, handler)
|
||||||
}
|
}
|
||||||
|
SemicolonStatement::Assignment(_assignment) => {
|
||||||
|
// TODO: correctly analyze the semantics of the assignment
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,14 @@ impl Statement {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
SemicolonStatement::Assignment(_) => {
|
||||||
|
let err = Error::InvalidAnnotation(InvalidAnnotation {
|
||||||
|
annotation: annotation.assignment.identifier.span,
|
||||||
|
target: "assignments".to_string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
SemicolonStatement::Expression(_) => {
|
SemicolonStatement::Expression(_) => {
|
||||||
let err = Error::InvalidAnnotation(InvalidAnnotation {
|
let err = Error::InvalidAnnotation(InvalidAnnotation {
|
||||||
annotation: annotation.assignment.identifier.span,
|
annotation: annotation.assignment.identifier.span,
|
||||||
|
@ -272,7 +280,7 @@ impl Semicolon {
|
||||||
/// Syntax Synopsis:
|
/// Syntax Synopsis:
|
||||||
/// ``` ebnf
|
/// ``` ebnf
|
||||||
/// SemicolonStatement:
|
/// SemicolonStatement:
|
||||||
/// (Expression | VariableDeclaration)
|
/// (Expression | VariableDeclaration | Assignment)
|
||||||
/// ';'
|
/// ';'
|
||||||
/// ;
|
/// ;
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -283,6 +291,8 @@ pub enum SemicolonStatement {
|
||||||
Expression(Expression),
|
Expression(Expression),
|
||||||
/// A variable declaration.
|
/// A variable declaration.
|
||||||
VariableDeclaration(VariableDeclaration),
|
VariableDeclaration(VariableDeclaration),
|
||||||
|
/// An assignment.
|
||||||
|
Assignment(Assignment),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceElement for SemicolonStatement {
|
impl SourceElement for SemicolonStatement {
|
||||||
|
@ -290,6 +300,7 @@ impl SourceElement for SemicolonStatement {
|
||||||
match self {
|
match self {
|
||||||
Self::Expression(expression) => expression.span(),
|
Self::Expression(expression) => expression.span(),
|
||||||
Self::VariableDeclaration(declaration) => declaration.span(),
|
Self::VariableDeclaration(declaration) => declaration.span(),
|
||||||
|
Self::Assignment(assignment) => assignment.span(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -669,6 +680,44 @@ impl TagVariableDeclaration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents an assignment in the syntax tree.
|
||||||
|
///
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
/// ```ebnf
|
||||||
|
/// Assignment:
|
||||||
|
/// Identifier '=' Expression
|
||||||
|
/// ```
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
|
||||||
|
pub struct Assignment {
|
||||||
|
/// The identifier of the assignment.
|
||||||
|
#[get = "pub"]
|
||||||
|
identifier: Identifier,
|
||||||
|
/// The equals sign of the assignment.
|
||||||
|
#[get = "pub"]
|
||||||
|
equals: Punctuation,
|
||||||
|
/// The expression of the assignment.
|
||||||
|
#[get = "pub"]
|
||||||
|
expression: Expression,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SourceElement for Assignment {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
self.identifier
|
||||||
|
.span()
|
||||||
|
.join(&self.expression.span())
|
||||||
|
.expect("The span of the assignment is invalid.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Assignment {
|
||||||
|
/// Dissolves the [`Assignment`] into its components.
|
||||||
|
#[must_use]
|
||||||
|
pub fn dissolve(self) -> (Identifier, Punctuation, Expression) {
|
||||||
|
(self.identifier, self.equals, self.expression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
/// Parses a [`Block`].
|
/// Parses a [`Block`].
|
||||||
///
|
///
|
||||||
|
@ -808,9 +857,27 @@ impl<'a> Parser<'a> {
|
||||||
self.parse_variable_declaration(handler)
|
self.parse_variable_declaration(handler)
|
||||||
.map(SemicolonStatement::VariableDeclaration)
|
.map(SemicolonStatement::VariableDeclaration)
|
||||||
}
|
}
|
||||||
_ => self
|
_ => {
|
||||||
.parse_expression(handler)
|
// try to parse assignment
|
||||||
.map(SemicolonStatement::Expression),
|
// TODO: improve
|
||||||
|
#[expect(clippy::option_if_let_else)]
|
||||||
|
if let Ok(assignment) = self.try_parse(|p| {
|
||||||
|
let identifier = p.parse_identifier(&VoidHandler)?;
|
||||||
|
let equals = p.parse_punctuation('=', true, &VoidHandler)?;
|
||||||
|
let expression = p.parse_expression(&VoidHandler)?;
|
||||||
|
|
||||||
|
Ok(SemicolonStatement::Assignment(Assignment {
|
||||||
|
identifier,
|
||||||
|
equals,
|
||||||
|
expression,
|
||||||
|
}))
|
||||||
|
}) {
|
||||||
|
Ok(assignment)
|
||||||
|
} else {
|
||||||
|
self.parse_expression(handler)
|
||||||
|
.map(SemicolonStatement::Expression)
|
||||||
|
}
|
||||||
|
}
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
let semicolon = self.parse_punctuation(';', true, handler)?;
|
let semicolon = self.parse_punctuation(';', true, handler)?;
|
||||||
|
|
|
@ -566,6 +566,12 @@ impl Transpiler {
|
||||||
SemicolonStatement::VariableDeclaration(decl) => {
|
SemicolonStatement::VariableDeclaration(decl) => {
|
||||||
self.transpile_variable_declaration(decl, program_identifier, scope, handler)
|
self.transpile_variable_declaration(decl, program_identifier, scope, handler)
|
||||||
}
|
}
|
||||||
|
SemicolonStatement::Assignment(assignment) => self.transpile_assignment(
|
||||||
|
assignment.identifier(),
|
||||||
|
assignment.expression(),
|
||||||
|
scope,
|
||||||
|
handler,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,22 +254,6 @@ impl Transpiler {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
KeywordKind::Bool => {
|
KeywordKind::Bool => {
|
||||||
let setup_cmd = Command::Execute(Execute::If(
|
|
||||||
Condition::Not(Box::new(Condition::Atom(
|
|
||||||
format!(
|
|
||||||
"data storage {namespace}:{name} {target}",
|
|
||||||
namespace = self.main_namespace_name
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
))),
|
|
||||||
Box::new(Execute::Run(Box::new(Command::Raw(format!(
|
|
||||||
r#"data merge storage {namespace}:{name} {{"{target}": 0b}}"#,
|
|
||||||
namespace = self.main_namespace_name
|
|
||||||
))))),
|
|
||||||
None,
|
|
||||||
));
|
|
||||||
self.setup_cmds.push(setup_cmd);
|
|
||||||
|
|
||||||
scope.set_variable(
|
scope.set_variable(
|
||||||
single.identifier().span.str(),
|
single.identifier().span.str(),
|
||||||
VariableData::BooleanStorage {
|
VariableData::BooleanStorage {
|
||||||
|
@ -294,7 +278,7 @@ impl Transpiler {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transpile_assignment(
|
pub(super) fn transpile_assignment(
|
||||||
&mut self,
|
&mut self,
|
||||||
identifier: &Identifier,
|
identifier: &Identifier,
|
||||||
expression: &crate::syntax::syntax_tree::expression::Expression,
|
expression: &crate::syntax::syntax_tree::expression::Expression,
|
||||||
|
|
Loading…
Reference in New Issue