feat: semantic check for unary op
This commit is contained in:
parent
28d48c8b2f
commit
ee9b12253d
@ -28,6 +28,7 @@
|
||||
- [x] Scan octal and binary numbers
|
||||
- [x] Simple type checking
|
||||
- [x] Check for conflicting identifiers at the current scope
|
||||
- [x] Semantic check for unary operator
|
||||
|
||||
|
||||
## v0.1.0
|
||||
|
@ -8,6 +8,13 @@ impl Transpilable for PPrimary<'_> {
|
||||
PPrimary::StringLiteral(value) => format!("\"{}\"", value),
|
||||
PPrimary::Variable(name) => format!("${}", name),
|
||||
PPrimary::Symbol(name) => format!("{}", name),
|
||||
PPrimary::BoolLiteral(bool) => {
|
||||
if *bool {
|
||||
String::from("true")
|
||||
} else {
|
||||
String::from("false")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ impl Transpilable for PFile<'_> {
|
||||
fragments.push(statement.transpile());
|
||||
}
|
||||
|
||||
fragments.join("")
|
||||
fragments.join("\n")
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,6 +37,6 @@ mod tests {
|
||||
};
|
||||
let output = ast.transpile();
|
||||
|
||||
assert_eq!("<?php\n\"Hello world!\";", output);
|
||||
assert_eq!("<?php\n\n\"Hello world!\";", output);
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ pub enum PPrimary<'a> {
|
||||
IntegerLiteral(&'a String),
|
||||
FloatingLiteral(&'a String),
|
||||
StringLiteral(&'a String),
|
||||
BoolLiteral(bool),
|
||||
/// https://phplang.org/spec/19-grammar.html#grammar-variable
|
||||
///
|
||||
/// Supports only variable -> callable-variable -> simple-variable -> variable-name
|
||||
|
@ -32,7 +32,11 @@ impl<'a> PHPTransformable<'a> for Expression<'_> {
|
||||
PExpresssion::FunctionCall(fn_call_expr)
|
||||
}
|
||||
Expression::Identifier(i) => PExpresssion::Primary(PPrimary::Variable(&i.value)),
|
||||
_ => todo!("transformation for expression: {:?}", self),
|
||||
Expression::Boolean(b) => {
|
||||
PExpresssion::Primary(PPrimary::BoolLiteral(b.value == "true"))
|
||||
}
|
||||
Expression::UnaryOperator(_, _) => unimplemented!("transform unary op into php"),
|
||||
Expression::BinaryOperator(_, _, _) => unimplemented!("transform binary op into php"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,6 @@ impl SemanticCheck for Expression<'_> {
|
||||
// The argument and the parameter have diferent types
|
||||
let (error_start, error_end) = argument.get_position();
|
||||
return Err(MistiError::Semantic(SemanticError {
|
||||
// TODO: fix
|
||||
error_start,
|
||||
error_end,
|
||||
reason: format!(
|
||||
@ -67,11 +66,48 @@ impl SemanticCheck for Expression<'_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
// These are empty because they have nothing to check,
|
||||
// their existance alone is correct
|
||||
Expression::Int(_) => {}
|
||||
Expression::Float(_) => {}
|
||||
Expression::String(_) => {}
|
||||
Expression::Boolean(_) => {}
|
||||
_ => todo!("Check semantics for expression other than function call and primitive"),
|
||||
Expression::Identifier(_) => {}
|
||||
Expression::UnaryOperator(operator, expression) => {
|
||||
// There are a limited amount of unary operators,
|
||||
// so their checking is not generalized
|
||||
let expr_type = expression.get_type(scope)?;
|
||||
match (operator.value.as_str(), expr_type) {
|
||||
("!", Type::Value(t)) => {
|
||||
if t == "Bool" {
|
||||
// Ok, empty
|
||||
} else {
|
||||
// Error: unary negation can only be applied to a Bool
|
||||
let (error_start, error_end) = expression.get_position();
|
||||
return Err(MistiError::Semantic(SemanticError {
|
||||
error_start,
|
||||
error_end,
|
||||
reason: format!("Expected a Bool, got a {}", t),
|
||||
}));
|
||||
}
|
||||
}
|
||||
("!", Type::Function(_, _)) => {
|
||||
// Error: unary negation can only be applied to a Bool
|
||||
let (error_start, error_end) = expression.get_position();
|
||||
return Err(MistiError::Semantic(SemanticError {
|
||||
error_start,
|
||||
error_end,
|
||||
reason: format!("Expected a Bool, got a function",),
|
||||
}));
|
||||
}
|
||||
(op, _) => {
|
||||
// Compiler error: something that shouldn't be
|
||||
// parsed as a unary operator was found.
|
||||
unreachable!("Found a unary operator that shouldn't be: {}", op)
|
||||
}
|
||||
}
|
||||
}
|
||||
Expression::BinaryOperator(_, _, _) => unimplemented!(),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
error_handling::SyntaxError,
|
||||
lexic::token::Token,
|
||||
lexic::token::{Token, TokenType},
|
||||
syntax::{
|
||||
ast::{Expression, ModuleAST, ModuleMembers, Statement},
|
||||
parseable::{Parseable, ParsingError, ParsingResult},
|
||||
@ -51,6 +51,16 @@ impl<'a> Parseable<'a> for ModuleAST<'a> {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Ignore comments, if any
|
||||
if let Some(s) = tokens.get(current_pos) {
|
||||
if s.token_type == TokenType::Comment
|
||||
|| s.token_type == TokenType::MultilineComment
|
||||
{
|
||||
current_pos += 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If we reached this point we didn't match any productions and fail
|
||||
let t = &tokens[current_pos];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user