Added support for compile-time constant hash expressions
This commit is contained in:
@@ -1256,17 +1256,47 @@ impl<'a> Parser<'a> {
|
||||
));
|
||||
}
|
||||
|
||||
// literal value
|
||||
// literal or syscall, making sure the syscall is supported in hash
|
||||
self.assign_next()?;
|
||||
let lit = self.spanned(|p| p.literal())?;
|
||||
// cache the current token location
|
||||
let current_token_index = self.tokenizer.loc();
|
||||
|
||||
Ok(ConstDeclarationExpression {
|
||||
name: Spanned {
|
||||
span: ident_span,
|
||||
node: ident,
|
||||
},
|
||||
value: lit,
|
||||
})
|
||||
if let Ok(lit) = self.spanned(|p| p.literal()) {
|
||||
Ok(ConstDeclarationExpression {
|
||||
name: Spanned {
|
||||
span: ident_span,
|
||||
node: ident,
|
||||
},
|
||||
value: LiteralOr::Literal(lit),
|
||||
})
|
||||
} else {
|
||||
// we need to rewind our tokenizer to our previous location
|
||||
self.tokenizer.seek(SeekFrom::Current(
|
||||
self.tokenizer.loc() - current_token_index,
|
||||
))?;
|
||||
let syscall = self.spanned(|p| p.syscall())?;
|
||||
|
||||
if !matches!(
|
||||
syscall,
|
||||
Spanned {
|
||||
node: SysCall::System(sys_call::System::Hash(_)),
|
||||
..
|
||||
}
|
||||
) {
|
||||
return Err(Error::UnexpectedToken(
|
||||
syscall.span,
|
||||
self.current_token.clone().ok_or(Error::UnexpectedEOF)?,
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ConstDeclarationExpression {
|
||||
name: Spanned {
|
||||
span: ident_span,
|
||||
node: ident,
|
||||
},
|
||||
value: LiteralOr::Or(syscall),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn declaration(&mut self) -> Result<Expression, Error> {
|
||||
|
||||
@@ -144,3 +144,10 @@ fn test_binary_expression() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_const_hash_expression() -> Result<()> {
|
||||
let expr = parser!(r#"const i = hash("item")"#).parse()?.unwrap();
|
||||
assert_eq!("(const i = hash(\"item\"))", expr.to_string());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::sys_call;
|
||||
|
||||
use super::sys_call::SysCall;
|
||||
use tokenizer::token::Number;
|
||||
|
||||
@@ -10,6 +12,21 @@ pub enum Literal {
|
||||
Boolean(bool),
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub enum LiteralOr<T> {
|
||||
Literal(Spanned<Literal>),
|
||||
Or(Spanned<T>),
|
||||
}
|
||||
|
||||
impl<T: std::fmt::Display> std::fmt::Display for LiteralOr<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Literal(l) => write!(f, "{l}"),
|
||||
Self::Or(o) => write!(f, "{o}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Literal {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
@@ -198,7 +215,14 @@ impl std::fmt::Display for LiteralOrVariable {
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct ConstDeclarationExpression {
|
||||
pub name: Spanned<String>,
|
||||
pub value: Spanned<Literal>,
|
||||
pub value: LiteralOr<SysCall>,
|
||||
}
|
||||
|
||||
impl ConstDeclarationExpression {
|
||||
pub fn is_syscall_supported(call: &SysCall) -> bool {
|
||||
use sys_call::System;
|
||||
matches!(call, SysCall::System(sys) if matches!(sys, System::Hash(_)))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ConstDeclarationExpression {
|
||||
|
||||
Reference in New Issue
Block a user