support for date literals

This commit is contained in:
Shautvast 2025-11-09 17:35:59 +01:00
parent c64fa00611
commit 3feadcce19
6 changed files with 70 additions and 32 deletions

View file

@ -1,14 +1,12 @@
use crate::ast_compiler::Expression::{
FunctionCall, NamedParameter, Stop, Variable,
};
use crate::ast_compiler::Expression::{FunctionCall, NamedParameter, Stop, Variable};
use crate::errors::CompilerError::{
self, Expected, IncompatibleTypes, ParseError, TooManyParameters, TypeError,
UndeclaredVariable, UnexpectedIndent, UninitializedVariable,
};
use crate::errors::CompilerErrorAtLine;
use crate::tokens::TokenType::{
Bang, Bool, Char, Colon, Date, Dot, Eof, Eol, Equal, F32, F64, False, FloatingPoint, Fn,
Greater, GreaterEqual, GreaterGreater, I32, I64, Identifier, Indent, Integer, LeftBrace,
Bang, Bool, Char, Colon, Date, DateTime, Dot, Eof, Eol, Equal, F32, F64, False, FloatingPoint,
Fn, Greater, GreaterEqual, GreaterGreater, I32, I64, Identifier, Indent, Integer, LeftBrace,
LeftBracket, LeftParen, Less, LessEqual, LessLess, Let, ListType, MapType, Minus, Object, Plus,
Print, RightBrace, RightBracket, RightParen, SignedInteger, SingleRightArrow, Slash, Star,
StringType, True, U32, U64, UnsignedInteger,
@ -469,7 +467,7 @@ impl AstCompiler {
Expression::Literal {
line: self.peek().line,
literaltype: StringType,
value: Value::String(self.previous().lexeme.to_string()),
value: Value::String(self.previous().lexeme.clone()),
}
} else if self.match_token(vec![Char]) {
Expression::Literal {
@ -477,6 +475,19 @@ impl AstCompiler {
literaltype: Char,
value: Value::Char(self.previous().lexeme.chars().next().unwrap()),
}
} else if self.match_token(vec![DateTime]) {
Expression::Literal {
line: self.peek().line,
literaltype: DateTime,
value: Value::DateTime(
chrono::DateTime::parse_from_str(
&self.previous().lexeme,
"%Y-%m-%d %H:%M:%S%.3f %z",
)
.map_err(|e| self.raise(ParseError(self.previous().lexeme.clone())))?
.into(),
),
}
} else if self.match_token(vec![LeftParen]) {
let expr = self.expression()?;
self.consume(RightParen, Expected("')' after expression."))?;

View file

@ -2,6 +2,7 @@
mod tests {
use crate::value::Value;
use crate::{compile, run};
use chrono::{DateTime, FixedOffset, NaiveDate, TimeZone};
#[test]
fn literal_int() {
@ -202,6 +203,16 @@ m"#);
assert_eq!(run(r#"0x10 + 0x20"#), Ok(Value::U32(48)));
}
#[test]
fn date_literal() {
assert_eq!(
run(r#"t"2025-11-09 16:44:28.000 +0100""#),
Ok(Value::DateTime(
DateTime::parse_from_str("2025-11-09 16:44:28.000 +0100", "%Y-%m-%d %H:%M:%S%.3f %z").unwrap().into()
))
);
}
// #[test]
// fn package() {
// assert_eq!(run(r#"a.b.c()"#), Ok(Value::U32(48)));

View file

@ -111,6 +111,11 @@ impl Scanner {
}
'\'' => self.char()?,
'"' => self.string()?,
't' => {
if self.match_next('"') {
self.datetime()?;
}
}
'\r' | '\t' | ' ' => {}
'\n' => {
self.line += 1;
@ -220,6 +225,18 @@ impl Scanner {
CompilerErrorAtLine::raise(error, self.line)
}
fn datetime(&mut self) -> Result<(), CompilerErrorAtLine> {
while self.peek() != '"' && !self.is_at_end() {
self.advance();
}
self.advance();
let value: String = self.chars[self.start + 2..self.current - 1]
.iter()
.collect();
self.add_token_with_value(TokenType::DateTime, value);
Ok(())
}
fn string(&mut self) -> Result<(), CompilerErrorAtLine> {
while self.peek() != '"' && !self.is_at_end() {
if self.peek() == '\n' {

View file

@ -2,11 +2,7 @@ use crate::ast_compiler::{Expression, Parameter, Statement};
use crate::errors::CompilerError;
use crate::errors::CompilerError::{IncompatibleTypes, TypeError};
use crate::tokens::{Token, TokenType};
use crate::tokens::TokenType::{
Bool, Date, F32, F64, FloatingPoint, Greater, GreaterEqual, I32, I64, Integer, Less, LessEqual,
ListType, MapType, Minus, Object, Plus, SignedInteger, StringType, U32, U64, Unknown,
UnsignedInteger,
};
use crate::tokens::TokenType::{Bool, Date, F32, F64, FloatingPoint, Greater, GreaterEqual, I32, I64, Integer, Less, LessEqual, ListType, MapType, Minus, Object, Plus, SignedInteger, StringType, U32, U64, Unknown, UnsignedInteger, DateTime};
use log::debug;
use std::collections::HashMap;
@ -139,6 +135,7 @@ pub fn calculate_type(
FloatingPoint => F64,
Bool => Bool,
Date => Date,
DateTime => DateTime,
ListType => ListType,
MapType => MapType,
Object => Object,

View file

@ -82,6 +82,7 @@ pub enum TokenType {
Star,
StringType,
True,
DateTime,
U32,
U64,
Unknown,
@ -156,6 +157,7 @@ impl fmt::Display for TokenType {
TokenType::SingleRightArrow => write!(f, "->"),
TokenType::Slash => write!(f, "/"),
TokenType::Star => write!(f, "*"),
TokenType::DateTime => write!(f, "t\""),
TokenType::True => write!(f, "true"),
TokenType::Unknown => write!(f, "?"),
TokenType::Void => write!(f, "()"),

View file

@ -1,5 +1,5 @@
use crate::errors::ValueError;
use chrono::{DateTime, Utc};
use chrono::{DateTime, Local, Utc};
use std::cmp::Ordering;
use std::collections::HashMap;
use std::fmt::{Display, Formatter};
@ -23,7 +23,7 @@ pub enum Value {
String(String),
Char(char),
Bool(bool),
Date(DateTime<Utc>),
DateTime(DateTime<Utc>),
Enum,
List(Vec<Value>),
Map(HashMap<Value, Value>),
@ -144,7 +144,7 @@ impl Into<Value> for bool {
impl Into<Value> for DateTime<Utc> {
fn into(self) -> Value {
Value::Date(self)
Value::DateTime(self)
}
}
@ -160,7 +160,7 @@ impl Display for Value {
&Value::F32(v) => write!(f, "{}", v),
&Value::F64(v) => write!(f, "{}", v),
&Value::Char(v) => write!(f, "{}", v),
&Value::Date(v) => write!(f, "{}", v),
&Value::DateTime(v) => write!(f, "{}", v),
&Value::Enum => write!(f, "enum"),
&Value::ObjectType(o) => write!(f, "{}: {:?}", o.definition, o.fields),
&Value::List(v) => write!(f, "{:?}", v),
@ -383,7 +383,7 @@ impl PartialEq for Value {
(Value::Bool(a), Value::Bool(b)) => a == b,
(Value::String(a), Value::String(b)) => a == b,
(Value::Char(a), Value::Char(b)) => a == b,
(Value::Date(a), Value::Date(b)) => a == b,
(Value::DateTime(a), Value::DateTime(b)) => a == b,
(Value::List(a), Value::List(b)) => a == b,
(Value::Map(a), Value::Map(b)) => {
let mut equal = true;
@ -415,7 +415,7 @@ impl PartialOrd for Value {
(Value::F64(a), Value::F64(b)) => Some(a.partial_cmp(b)?),
(Value::String(a), Value::String(b)) => Some(a.partial_cmp(b)?),
(Value::Char(a), Value::Char(b)) => Some(a.partial_cmp(b)?),
(Value::Date(a), Value::Date(b)) => Some(a.partial_cmp(b)?),
(Value::DateTime(a), Value::DateTime(b)) => Some(a.partial_cmp(b)?),
_ => None,
}
}
@ -436,7 +436,7 @@ impl Hash for Value {
Value::String(s) => s.hash(state),
Value::Char(c) => c.hash(state),
Value::Bool(b) => b.hash(state),
Value::Date(d) => d.hash(state),
Value::DateTime(d) => d.hash(state),
Value::List(l) => l.hash(state),
_ => {}
}