feat: store token on expression::int
This commit is contained in:
parent
f7168f1d09
commit
d88d2e7f2d
@ -17,7 +17,7 @@ impl<'a> PHPTransformable<'a> for Expression<'_> {
|
||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(expr))
|
||||
}
|
||||
Expression::Int(value) => {
|
||||
let expr = PhpPrimaryExpression::IntegerLiteral(value);
|
||||
let expr = PhpPrimaryExpression::IntegerLiteral(&value.value);
|
||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(expr))
|
||||
}
|
||||
Expression::Float(value) => {
|
||||
@ -32,6 +32,7 @@ impl<'a> PHPTransformable<'a> for Expression<'_> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
lexic::token::Token,
|
||||
php_ast::{
|
||||
transformers::PHPTransformable, PhpAssignmentExpression, PhpExpression,
|
||||
PhpPrimaryExpression,
|
||||
@ -57,8 +58,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn should_transform_int() {
|
||||
let value = String::from("322");
|
||||
let input = Expression::Int(&value);
|
||||
let binding = Token::new_int(String::from("322"), 0);
|
||||
let input = Expression::Int(&binding);
|
||||
let output = input.into_php_ast();
|
||||
|
||||
match output {
|
||||
|
@ -54,7 +54,7 @@ impl<'a> PHPTransformable<'a> for ModuleAST<'_> {
|
||||
Expression::Int(value) => {
|
||||
php_statements.push(PhpStatement::PhpExpressionStatement(
|
||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(
|
||||
PhpPrimaryExpression::IntegerLiteral(value),
|
||||
PhpPrimaryExpression::IntegerLiteral(&value.value),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
use crate::{
|
||||
error_handling::{semantic_error::SemanticError, MistiError},
|
||||
semantic::{impls::SemanticCheck, symbol_table::SymbolTable, types::{Type, Typed}},
|
||||
semantic::{
|
||||
impls::SemanticCheck,
|
||||
symbol_table::SymbolTable,
|
||||
types::{Type, Typed},
|
||||
},
|
||||
syntax::ast::Expression,
|
||||
};
|
||||
|
||||
@ -36,13 +40,14 @@ impl SemanticCheck for Expression<'_> {
|
||||
let argument_datatype = argument.get_type(scope)?;
|
||||
if !argument_datatype.is_value(parameter) {
|
||||
// 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: 0,
|
||||
error_end: 1,
|
||||
error_start,
|
||||
error_end,
|
||||
reason: format!(
|
||||
"Expected datatype {}, got {:?}",
|
||||
parameter, argument
|
||||
"Expected a {}, got {:?}",
|
||||
parameter, argument_datatype
|
||||
),
|
||||
}));
|
||||
}
|
||||
@ -74,16 +79,22 @@ impl SemanticCheck for Expression<'_> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{error_handling::MistiError, lexic::token::Token, semantic::{impls::SemanticCheck, symbol_table::SymbolTable}, syntax::ast::{functions::{ArgumentsList, FunctionCall}, Expression}};
|
||||
use crate::{
|
||||
error_handling::MistiError,
|
||||
lexic::token::Token,
|
||||
semantic::{impls::SemanticCheck, std::populate, symbol_table::SymbolTable},
|
||||
syntax::ast::{
|
||||
functions::{ArgumentsList, FunctionCall},
|
||||
Expression,
|
||||
},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn should_error() {
|
||||
fn should_error_on_undefined_symbol() {
|
||||
// source code: `print()`
|
||||
let expr_token = Token::new_identifier("print".into(), 0);
|
||||
let expr_function = Expression::Identifier(&expr_token);
|
||||
let arguments = ArgumentsList {
|
||||
arguments: vec![]
|
||||
};
|
||||
let arguments = ArgumentsList { arguments: vec![] };
|
||||
|
||||
let expr = Expression::FunctionCall(FunctionCall {
|
||||
function: Box::new(expr_function),
|
||||
@ -99,8 +110,39 @@ mod tests {
|
||||
assert_eq!(err.reason, "Cannot find `print` in this scope.");
|
||||
assert_eq!(err.error_start, 0);
|
||||
assert_eq!(err.error_end, 5);
|
||||
},
|
||||
Err(e) => panic!("Expected a Semantic error, got {:?}", e)
|
||||
}
|
||||
Err(e) => panic!("Expected a Semantic error, got {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_error_on_invalid_function_argument() {
|
||||
// source code: `print(322)`
|
||||
let mut scope = SymbolTable::new();
|
||||
populate(&mut scope);
|
||||
|
||||
let expr_token = Token::new_identifier("print".into(), 0);
|
||||
let expr_function = Expression::Identifier(&expr_token);
|
||||
|
||||
let arg_t = Token::new_int(String::from("322"), 6);
|
||||
let arg_1 = Expression::Int(&arg_t);
|
||||
let arguments = ArgumentsList {
|
||||
arguments: vec![arg_1],
|
||||
};
|
||||
|
||||
let expr = Expression::FunctionCall(FunctionCall {
|
||||
function: Box::new(expr_function),
|
||||
arguments: Box::new(arguments),
|
||||
});
|
||||
|
||||
match expr.check_semantics(&scope) {
|
||||
Ok(_) => panic!("Expected semantic error, got ok"),
|
||||
Err(MistiError::Semantic(e)) => {
|
||||
assert_eq!(e.reason, "Expected a String, got Value(\"Int\")");
|
||||
assert_eq!(e.error_start, 6);
|
||||
assert_eq!(e.error_end, 9);
|
||||
}
|
||||
Err(e) => panic!("Expected semantic error, got {:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
pub mod binding;
|
||||
pub mod expression;
|
||||
pub mod function_declaration;
|
||||
pub mod top_level_declaration;
|
||||
pub mod expression;
|
||||
|
||||
|
@ -35,9 +35,6 @@ impl Typed for Expression<'_> {
|
||||
// for this to work with any arbitrary expression.
|
||||
// for now it justs expects an identifier
|
||||
|
||||
// The type of a function call is the return type
|
||||
// of the function
|
||||
|
||||
// TODO: Should this check that the type signature is correct?
|
||||
// or is this done elsewhere?
|
||||
|
||||
@ -48,7 +45,7 @@ impl Typed for Expression<'_> {
|
||||
// Return the return type of the function,
|
||||
// not the function itself
|
||||
Ok(Type::Value(return_type))
|
||||
},
|
||||
}
|
||||
Some(_) => Err(MistiError::Semantic(SemanticError {
|
||||
error_start: id.position,
|
||||
error_end: id.get_end_position(),
|
||||
@ -127,10 +124,21 @@ impl Typed for Expression<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{error_handling::MistiError, lexic::token::Token, semantic::{std::populate, symbol_table::SymbolTable, types::{Type, Typed}}, syntax::ast::{functions::{ArgumentsList, FunctionCall}, Expression}};
|
||||
use crate::{
|
||||
error_handling::MistiError,
|
||||
lexic::token::Token,
|
||||
semantic::{
|
||||
std::populate,
|
||||
symbol_table::SymbolTable,
|
||||
types::{Type, Typed},
|
||||
},
|
||||
syntax::ast::{
|
||||
functions::{ArgumentsList, FunctionCall},
|
||||
Expression,
|
||||
},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn should_get_global_print_type() {
|
||||
@ -145,7 +153,7 @@ mod tests {
|
||||
assert_eq!(params.len(), 1);
|
||||
assert_eq!(params[0], "String");
|
||||
assert_eq!(return_type, "Void");
|
||||
},
|
||||
}
|
||||
Ok(t) => panic!("Expected a Function, got {:?}", t),
|
||||
Err(e) => panic!("Expected Ok, got Err: {:?}", e),
|
||||
}
|
||||
@ -164,8 +172,8 @@ mod tests {
|
||||
assert_eq!(err.error_start, 0);
|
||||
assert_eq!(err.error_end, 5);
|
||||
assert_eq!(err.reason, "Cannot find `print` in this scope.");
|
||||
},
|
||||
Err(e) => panic!("Expected a semantic error, got {:?}", e)
|
||||
}
|
||||
Err(e) => panic!("Expected a semantic error, got {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,8 +184,8 @@ mod tests {
|
||||
|
||||
let id_token = Token::new_identifier("print".into(), 0);
|
||||
let fn_expr = Expression::Identifier(&id_token);
|
||||
|
||||
let args = ArgumentsList{arguments: vec![]};
|
||||
|
||||
let args = ArgumentsList { arguments: vec![] };
|
||||
|
||||
let fn_call = Expression::FunctionCall(FunctionCall {
|
||||
function: Box::new(fn_expr),
|
||||
@ -199,8 +207,8 @@ mod tests {
|
||||
|
||||
let id_token = Token::new_identifier("print".into(), 0);
|
||||
let fn_expr = Expression::Identifier(&id_token);
|
||||
|
||||
let args = ArgumentsList{arguments: vec![]};
|
||||
|
||||
let args = ArgumentsList { arguments: vec![] };
|
||||
|
||||
let fn_call = Expression::FunctionCall(FunctionCall {
|
||||
function: Box::new(fn_expr),
|
||||
@ -224,8 +232,8 @@ mod tests {
|
||||
|
||||
let id_token = Token::new_identifier("print".into(), 0);
|
||||
let fn_expr = Expression::Identifier(&id_token);
|
||||
|
||||
let args = ArgumentsList{arguments: vec![]};
|
||||
|
||||
let args = ArgumentsList { arguments: vec![] };
|
||||
|
||||
let fn_call = Expression::FunctionCall(FunctionCall {
|
||||
function: Box::new(fn_expr),
|
||||
|
@ -60,7 +60,7 @@ pub struct Parameter<'a> {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Expression<'a> {
|
||||
Int(&'a String),
|
||||
Int(&'a Token),
|
||||
Float(&'a String),
|
||||
String(&'a String),
|
||||
Boolean(bool),
|
||||
@ -69,3 +69,20 @@ pub enum Expression<'a> {
|
||||
UnaryOperator(&'a String, Box<Expression<'a>>),
|
||||
BinaryOperator(Box<Expression<'a>>, Box<Expression<'a>>, &'a String),
|
||||
}
|
||||
|
||||
impl Expression<'_> {
|
||||
/// Returns the absolute start and end position
|
||||
/// of this expression
|
||||
pub fn get_position(&self) -> (usize, usize) {
|
||||
match self {
|
||||
Expression::Identifier(id) => (id.position, id.get_end_position()),
|
||||
Expression::Int(id) => (id.position, id.get_end_position()),
|
||||
Expression::Float(_) => todo!(),
|
||||
Expression::String(_) => todo!(),
|
||||
Expression::Boolean(_) => todo!(),
|
||||
Expression::FunctionCall(_) => todo!(),
|
||||
Expression::UnaryOperator(_, _) => todo!(),
|
||||
Expression::BinaryOperator(_, _, _) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ use crate::{
|
||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
|
||||
match tokens.get_significant(pos) {
|
||||
Some((token, token_pos)) => match token.token_type {
|
||||
TokenType::Int => Ok((Expression::Int(&token.value), token_pos + 1)),
|
||||
TokenType::Int => Ok((Expression::Int(&token), token_pos + 1)),
|
||||
TokenType::Float => Ok((Expression::Float(&token.value), token_pos + 1)),
|
||||
TokenType::String => Ok((Expression::String(&token.value), token_pos + 1)),
|
||||
TokenType::Identifier if token.value == "true" || token.value == "false" => {
|
||||
@ -53,7 +53,7 @@ mod tests {
|
||||
|
||||
match expression {
|
||||
Ok((Expression::Int(value), _)) => {
|
||||
assert_eq!("40", format!("{}", value))
|
||||
assert_eq!("40", format!("{}", value.value))
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ mod tests {
|
||||
match (operator, *expression) {
|
||||
(op, Expression::Int(value)) => {
|
||||
assert_eq!(*op, "-");
|
||||
assert_eq!(*value, "10");
|
||||
assert_eq!(value.value, "10");
|
||||
}
|
||||
_ => panic!("unexpected values"),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user