From 50de71572f1106e1ac419bc59f283e3328c66f0e Mon Sep 17 00:00:00 2001 From: Shautvast Date: Sun, 26 Oct 2025 18:10:16 +0100 Subject: [PATCH] more or less complete regarding basic operators --- src/ast_compiler.rs | 103 ++++++++++++++++++++++----------------- src/bytecode_compiler.rs | 10 ++-- src/main.rs | 3 +- 3 files changed, 63 insertions(+), 53 deletions(-) diff --git a/src/ast_compiler.rs b/src/ast_compiler.rs index 75e62ae..630d930 100644 --- a/src/ast_compiler.rs +++ b/src/ast_compiler.rs @@ -1,8 +1,9 @@ use crate::ast_compiler::Expression::Variable; use crate::tokens::TokenType::{ Bang, Bool, Char, Colon, Date, Eol, Equal, F32, F64, False, FloatingPoint, Greater, - GreaterEqual, I32, I64, Identifier, Integer, LeftParen, Less, LessEqual, Let, ListType, - MapType, Minus, Object, Plus, Print, RightParen, Slash, Star, Text, True, U32, U64, + GreaterEqual, GreaterGreater, I32, I64, Identifier, Integer, LeftParen, Less, LessEqual, + LessLess, Let, ListType, MapType, Minus, Object, Plus, Print, RightParen, Slash, Star, Text, + True, U32, U64, }; use crate::tokens::{Token, TokenType}; use crate::value::Value; @@ -105,59 +106,67 @@ impl AstCompiler { } fn expression(&mut self) -> anyhow::Result { - self.equality() + self.or() + } + + fn or(&mut self) -> anyhow::Result { + let mut expr = self.and()?; + self.binary(vec![TokenType::LogicalOr], expr) + } + + fn and(&mut self) -> anyhow::Result { + let expr = self.bit_and()?; + self.binary(vec![TokenType::LogicalAnd], expr) + } + + fn bit_and(&mut self) -> anyhow::Result { + let expr = self.bit_or()?; + self.binary(vec![TokenType::BitAnd], expr) + } + + fn bit_or(&mut self) -> anyhow::Result { + let expr = self.bit_xor()?; + self.binary(vec![TokenType::BitOr], expr) + } + + fn bit_xor(&mut self) -> anyhow::Result { + let expr = self.equality()?; + self.binary(vec![TokenType::BitXor], expr) } fn equality(&mut self) -> anyhow::Result { - let mut expr = self.comparison()?; - while self.match_token(vec![TokenType::BangEqual, TokenType::EqualEqual]) { - let operator = self.previous().clone(); - let right = self.comparison()?; - expr = Expression::Binary { - line: operator.line, - left: Box::new(expr), - operator, - right: Box::new(right), - }; - } - Ok(expr) + let expr = self.comparison()?; + self.binary(vec![TokenType::EqualEqual, TokenType::BangEqual], expr) } fn comparison(&mut self) -> anyhow::Result { + let expr = self.bitshift()?; + self.binary(vec![Greater, GreaterEqual, Less, LessEqual], expr) + } + + fn bitshift(&mut self) -> anyhow::Result { let mut expr = self.term()?; - while self.match_token(vec![Greater, GreaterEqual, Less, LessEqual]) { - let operator = self.previous().clone(); - let right = self.term()?; - expr = Expression::Binary { - line: operator.line, - left: Box::new(expr), - operator, - right: Box::new(right), - }; - } - Ok(expr) + self.binary(vec![GreaterGreater, LessLess], expr) } fn term(&mut self) -> anyhow::Result { - let mut expr = self.factor()?; - while self.match_token(vec![Minus, Plus]) { - let operator = self.previous().clone(); - let right = self.factor()?; - expr = Expression::Binary { - line: operator.line, - left: Box::new(expr), - operator, - right: Box::new(right), - }; - } - Ok(expr) + let expr = self.factor()?; + self.binary(vec![Minus, Plus], expr) } fn factor(&mut self) -> anyhow::Result { - let mut expr = self.unary()?; - while self.match_token(vec![Slash, Star]) { + let expr = self.unary()?; + self.binary(vec![Slash, Star], expr) + } + + fn binary( + &mut self, + types: Vec, + mut expr: Expression, + ) -> anyhow::Result { + while self.match_token(types.clone()) { let operator = self.previous().clone(); - let right = self.unary()?; + let right = self.comparison()?; expr = Expression::Binary { line: operator.line, left: Box::new(expr), @@ -315,8 +324,8 @@ fn calculate_type( declared_type } } else { - match inferred_type{ - Integer => I64, + match inferred_type { + Integer | I64 => I64, FloatingPoint => F64, Text => Text, Bool => Bool, @@ -401,14 +410,16 @@ impl Expression { pub fn infer_type(&self) -> TokenType { match self { Self::Binary { - line, left, operator, right, + .. } => { let left_type = left.infer_type(); let right_type = right.infer_type(); - if left_type == right_type { + if vec![Greater, Less, GreaterEqual, LessEqual].contains(&operator.token_type) { + Bool + } else if left_type == right_type { // map to determined numeric type if yet undetermined (32 or 64 bits) match left_type { FloatingPoint => F64, @@ -426,6 +437,7 @@ impl Expression { (FloatingPoint, _) => F64, (Integer, FloatingPoint) => F64, (Integer, _) => I64, + (I64, Integer) => I64, (F64, _) => F64, (U64, U32) => U64, (I64, I32) => I64, @@ -442,6 +454,7 @@ impl Expression { match (left_type, right_type) { (FloatingPoint, _) => F64, (Integer, FloatingPoint) => F64, + (Integer, I64) => I64, (I64, FloatingPoint) => F64, (F64, _) => F64, (U64, U32) => U64, diff --git a/src/bytecode_compiler.rs b/src/bytecode_compiler.rs index 9d6f07d..5e1d908 100644 --- a/src/bytecode_compiler.rs +++ b/src/bytecode_compiler.rs @@ -3,13 +3,7 @@ use crate::ast_compiler::{Expression, Statement}; use crate::chunk::Chunk; use crate::tokens::TokenType; use crate::value::Value; -use crate::vm::{ - OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CONSTANT, OP_DEF_BOOL, OP_DEF_CHAR, OP_DEF_DATE, - OP_DEF_F32, OP_DEF_F64, OP_DEF_I32, OP_DEF_I64, OP_DEF_LIST, OP_DEF_MAP, OP_DEF_STRING, - OP_DEF_STRUCT, OP_DEFINE, OP_DIVIDE, OP_EQUAL, OP_GET, OP_GREATER, OP_GREATER_EQUAL, OP_LESS, - OP_LESS_EQUAL, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, - OP_SUBTRACT, -}; +use crate::vm::{OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CONSTANT, OP_DEF_BOOL, OP_DEF_CHAR, OP_DEF_DATE, OP_DEF_F32, OP_DEF_F64, OP_DEF_I32, OP_DEF_I64, OP_DEF_LIST, OP_DEF_MAP, OP_DEF_STRING, OP_DEF_STRUCT, OP_DEFINE, OP_DIVIDE, OP_EQUAL, OP_GET, OP_GREATER, OP_GREATER_EQUAL, OP_LESS, OP_LESS_EQUAL, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT, OP_AND, OP_OR}; pub fn compile(ast: Vec) -> anyhow::Result { let compiler = Compiler::new(); @@ -109,6 +103,8 @@ impl Compiler { TokenType::GreaterEqual => self.emit_byte(OP_GREATER_EQUAL), TokenType::Less => self.emit_byte(OP_LESS), TokenType::LessEqual => self.emit_byte(OP_LESS_EQUAL), + TokenType::LogicalAnd => self.emit_byte(OP_AND), + TokenType::LogicalOr => self.emit_byte(OP_OR), _ => unimplemented!("binary other than plus, minus, star, slash"), } } diff --git a/src/main.rs b/src/main.rs index b6d4f8f..94422f7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,8 +6,9 @@ use crudlang::vm::{interpret, Vm}; fn main() -> anyhow::Result<()> { tracing_subscriber::fmt::init(); - let tokens = scan(r#"let a = 42 + let tokens = scan(r#"let a = 1>2 print a"#); + // println!("{:?}", tokens); match ast_compiler::compile(tokens) { Ok(statements) => { println!("{:?}", statements);