diff --git a/src/constfold.rs b/src/constfold.rs index 0fa295a..ab44801 100644 --- a/src/constfold.rs +++ b/src/constfold.rs @@ -140,6 +140,20 @@ fn fold_expr(context: &Context, expr: &mut ast::Expression) { (ast::UnaryOp::Negate, ast::Expr::F64Const(value)) => { Some(ast::Expr::F64Const(-*value)) } + (ast::UnaryOp::Negate, ast::Expr::Cast { value, type_ }) => { + if let ast::Expr::I32Const(v) = value.expr { + Some(ast::Expr::Cast { + value: Box::new(ast::Expression { + expr: ast::Expr::I32Const(-v), + span: value.span.clone(), + type_: value.type_, + }), + type_: *type_, + }) + } else { + None + } + } (ast::UnaryOp::Not, ast::Expr::I32Const(value)) => { Some(ast::Expr::I32Const((*value == 0) as i32)) } diff --git a/src/parser.rs b/src/parser.rs index aba975a..548d380 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -79,6 +79,7 @@ enum Token { Str(String), Int(i32), Int64(i64), + IntFloat(i32), Float(String), Float64(String), Op(String), @@ -107,6 +108,7 @@ impl fmt::Display for Token { Token::Str(s) => write!(f, "{:?}", s), Token::Int(v) => write!(f, "{}", v), Token::Int64(v) => write!(f, "{}", v), + Token::IntFloat(v) => write!(f, "{}_f", v), Token::Float(v) => write!(f, "{}", v), Token::Float64(v) => write!(f, "{}", v), Token::Op(s) => write!(f, "{}", s), @@ -275,6 +277,11 @@ fn lexer() -> impl Parser, Error = LexerError> { .then_ignore(just("i64")) .map(|n| Token::Int64(n as i64)); + let int_float = integer + .clone() + .then_ignore(just("_f")) + .map(|n| Token::IntFloat(n as i32)); + let int = integer.try_map(|n, span| { u32::try_from(n) .map(|n| Token::Int(n as i32)) @@ -334,6 +341,7 @@ fn lexer() -> impl Parser, Error = LexerError> { let token = float .or(float64) .or(int64) + .or(int_float) .or(int) .or(str_) .or(op) @@ -349,10 +357,10 @@ fn lexer() -> impl Parser, Error = LexerError> { } fn map_token( - f: impl Fn(&Token) -> Option + 'static + Clone, + f: impl Fn(&Token, &Span) -> Option + 'static + Clone, ) -> impl Parser + Clone { filter_map(move |span, tok: Token| { - if let Some(output) = f(&tok) { + if let Some(output) = f(&tok, &span) { Ok(output) } else { Err(ScriptError::expected_input_found( @@ -376,12 +384,12 @@ fn script_parser() -> impl Parser + Clo }) .labelled("identifier"); - let integer = map_token(|tok| match tok { + let integer = map_token(|tok, _| match tok { Token::Int(v) => Some(*v), _ => None, }); - let string = map_token(|tok| match tok { + let string = map_token(|tok, _| match tok { Token::Str(s) => Some(s.clone()), _ => None, }); @@ -390,9 +398,13 @@ fn script_parser() -> impl Parser + Clo let block = recursive(|block| { let mut block_expression = None; let expression = recursive(|expression| { - let val = map_token(|tok| match tok { + let val = map_token(|tok, span| match tok { Token::Int(v) => Some(ast::Expr::I32Const(*v)), Token::Int64(v) => Some(ast::Expr::I64Const(*v)), + Token::IntFloat(v) => Some(ast::Expr::Cast { + value: Box::new(ast::Expr::I32Const(*v).with_span(span.clone())), + type_: ast::Type::F32, + }), Token::Float(v) => Some(ast::Expr::F32Const(v.parse().unwrap())), Token::Float64(v) => Some(ast::Expr::F64Const(v.parse().unwrap())), _ => None,