diff --git a/server/src/lang/ast/mod.rs b/server/src/lang/ast/mod.rs index 656e5e94..ef1e90ea 100644 --- a/server/src/lang/ast/mod.rs +++ b/server/src/lang/ast/mod.rs @@ -1,5 +1,7 @@ use std::rc::Rc; +use rustc_hash::FxHashMap; + use self::{ expr::{Expr, ExprId}, stmt::{Stmt, StmtId}, @@ -14,6 +16,7 @@ pub enum Literal { Num(f64), Bool(bool), Undefined, + Object(FxHashMap), NaN, Null, } diff --git a/server/src/lang/parser.rs b/server/src/lang/parser.rs index 503773e3..da5ad79d 100644 --- a/server/src/lang/parser.rs +++ b/server/src/lang/parser.rs @@ -1,3 +1,4 @@ +use rustc_hash::FxHashMap; use super::ast::expr::{Expr, ExprId}; use super::ast::sql::{ SelectCore, SqlCompoundOperator, SqlDistinct, SqlExpr, SqlFrom, SqlOrdering, SqlProjection, @@ -669,6 +670,24 @@ impl<'a> Parser<'a> { let tok = self.peek_bw(0); self.current += 1; match &tok.tok_type { + TokenType::Symbol(LeftBrace) => { + let mut obj_literal: FxHashMap = FxHashMap::default(); + while !self.cmp_tok(&sym!(RightBrace)) { + let key = self.expected(Identifier { dollar: false })?.clone(); + self.expected(sym!(Colon))?; + let value = self.expression()?; + obj_literal.insert(key.lexeme.unwrap(), value); + if !self.match_next(sym!(Comma)) { + break; + } + } + self.expected(sym!(RightBrace))?; + Ok(self.arena.expression(Expr::Literal { + value: Literal::Object(obj_literal), + raw: "".to_string(), + span: self.get_merged_span(&tok.span, &self.peek_bw(0).span), + })) + } True => Ok(self.arena.expression(Expr::Literal { value: Literal::Bool(true), raw: "true".to_string(), diff --git a/server/src/lang/token.rs b/server/src/lang/token.rs index c5e0c93d..e9a14c13 100644 --- a/server/src/lang/token.rs +++ b/server/src/lang/token.rs @@ -6,6 +6,7 @@ use super::ast::Literal; #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] pub enum Symbol { Comma, + Colon, Semicolon, LeftParen, RightParen, @@ -168,6 +169,7 @@ pub static SYMBOLS: phf::Map = phf_map! { '{' => sym!(Symbol::LeftBrace), '}' => sym!(Symbol::RightBrace), ',' => sym!(Symbol::Comma), + ':' => sym!(Symbol::Colon), '.' => sym!(Symbol::Dot), '-' => sym!(Symbol::Minus), '+' => sym!(Symbol::Plus), diff --git a/server/src/runtime/interpreter.rs b/server/src/runtime/interpreter.rs index 75e85bb2..a823a189 100644 --- a/server/src/runtime/interpreter.rs +++ b/server/src/runtime/interpreter.rs @@ -1,3 +1,5 @@ +use rustc_hash::FxHashMap; + use super::eval::{coerce2number, eval_binary, is_value_truthy}; use super::resolver::Resolver; use crate::lang::ast::expr::{Expr, ExprId}; @@ -214,7 +216,7 @@ impl Interpreter { ret } - pub fn literal_to_rv(&self, literal: &Literal) -> RV { + pub fn literal_to_rv(&mut self, literal: &Literal) -> RV { match literal { Literal::Str(s) => RV::Str(Rc::clone(s)), Literal::Num(n) => RV::Num(*n), @@ -222,6 +224,13 @@ impl Interpreter { Literal::Undefined => RV::Undefined, Literal::NaN => RV::NaN, Literal::Null => RV::Null, + Literal::Object(map) => { + let mut new_map = FxHashMap::default(); + for (k, v) in map.iter() { + new_map.insert(k.clone(), self.visit_expr(*v).unwrap()); + } + RV::Object(new_map) + } } } }