more or less complete regarding basic operators

This commit is contained in:
Shautvast 2025-10-26 18:10:16 +01:00
parent d2d7bb2034
commit 50de71572f
3 changed files with 63 additions and 53 deletions

View file

@ -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<Expression> {
self.equality()
self.or()
}
fn or(&mut self) -> anyhow::Result<Expression> {
let mut expr = self.and()?;
self.binary(vec![TokenType::LogicalOr], expr)
}
fn and(&mut self) -> anyhow::Result<Expression> {
let expr = self.bit_and()?;
self.binary(vec![TokenType::LogicalAnd], expr)
}
fn bit_and(&mut self) -> anyhow::Result<Expression> {
let expr = self.bit_or()?;
self.binary(vec![TokenType::BitAnd], expr)
}
fn bit_or(&mut self) -> anyhow::Result<Expression> {
let expr = self.bit_xor()?;
self.binary(vec![TokenType::BitOr], expr)
}
fn bit_xor(&mut self) -> anyhow::Result<Expression> {
let expr = self.equality()?;
self.binary(vec![TokenType::BitXor], expr)
}
fn equality(&mut self) -> anyhow::Result<Expression> {
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<Expression> {
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),
};
let expr = self.bitshift()?;
self.binary(vec![Greater, GreaterEqual, Less, LessEqual], expr)
}
Ok(expr)
fn bitshift(&mut self) -> anyhow::Result<Expression> {
let mut expr = self.term()?;
self.binary(vec![GreaterGreater, LessLess], expr)
}
fn term(&mut self) -> anyhow::Result<Expression> {
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<Expression> {
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<TokenType>,
mut expr: Expression,
) -> anyhow::Result<Expression> {
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,

View file

@ -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<Statement>) -> anyhow::Result<Chunk> {
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"),
}
}

View file

@ -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);