From 6f4824efac9ffdb6055e32117eecade841fc5d0e Mon Sep 17 00:00:00 2001 From: Shautvast Date: Mon, 10 Nov 2025 11:09:55 +0100 Subject: [PATCH] adding map access was easy --- src/ast_compiler.rs | 29 +++++++++++++++++------------ src/bytecode_compiler.rs | 20 ++++---------------- src/compiler_tests.rs | 22 ++++++++++++++++++---- src/repl.rs | 2 -- src/symbol_builder.rs | 6 +----- src/value.rs | 2 +- 6 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/ast_compiler.rs b/src/ast_compiler.rs index c04eed2..72e72a0 100644 --- a/src/ast_compiler.rs +++ b/src/ast_compiler.rs @@ -520,35 +520,39 @@ impl AstCompiler { ) -> Result { let get = (match &operand { Expression::Map { .. } => MapGet { + map: Box::new(operand), key: Box::new(index), }, Expression::List { .. } => ListGet { list: Box::new(operand), index: Box::new(index), }, - Variable { var_type, .. } => { - if var_type == &ListType { - ListGet { - list: Box::new(operand), - index: Box::new(index), - } - } else { + Variable { var_type, .. } => match var_type { + ListType => ListGet { + list: Box::new(operand), + index: Box::new(index), + }, + MapType => MapGet { + map: Box::new(operand), + key: Box::new(index), + }, + _ => { return Err(self.raise(CompilerError::IllegalTypeToIndex(var_type.to_string()))); } - } + }, _ => return Err(self.raise(CompilerError::IllegalTypeToIndex("Unknown".to_string()))), }); self.consume(RightBracket, Expected("']' after index."))?; Ok(get) } + // work in progress fn field( &mut self, - operand: Expression, + _operand: Expression, index: Token, ) -> Result { - //TODO? - Ok(Expression::FieldGet { + Ok(FieldGet { field: index.lexeme.clone(), }) } @@ -635,7 +639,7 @@ impl AstCompiler { &self.previous().lexeme, "%Y-%m-%d %H:%M:%S%.3f %z", ) - .map_err(|e| self.raise(ParseError(self.previous().lexeme.clone())))? + .map_err(|_| self.raise(ParseError(self.previous().lexeme.clone())))? .into(), ), } @@ -945,6 +949,7 @@ pub enum Expression { value: Box, }, MapGet { + map: Box, key: Box, }, ListGet { diff --git a/src/bytecode_compiler.rs b/src/bytecode_compiler.rs index 434189f..79fb24d 100644 --- a/src/bytecode_compiler.rs +++ b/src/bytecode_compiler.rs @@ -102,17 +102,11 @@ impl Compiler { self.current_line = statement.line(); match statement { Statement::VarStmt { - name, - var_type, - initializer, + name, initializer, .. } => { let name = name.lexeme.as_str(); let var = symbols.get(name); - if let Some(Symbol::Variable { - var_type, - .. - }) = var - { + if let Some(Symbol::Variable { var_type, .. }) = var { let inferred_type = infer_type(initializer, symbols); let calculated_type = calculate_type(var_type, &inferred_type) .map_err(|e| CompilerErrorAtLine::raise(e, statement.line()))?; @@ -189,13 +183,7 @@ impl Compiler { .find_constant(&name) .unwrap_or_else(|| self.chunk.add_constant(Value::String(name.to_string()))); let function = symbols.get(name); - if let Some(Symbol::Function { - name, - parameters, - return_type, - body, - }) = function - { + if let Some(Symbol::Function { parameters, .. }) = function { for parameter in parameters { for argument in arguments { if let NamedParameter { name, .. } = argument { @@ -295,7 +283,7 @@ impl Compiler { Expression::Stop { .. } => {} // Expression::PathMatch { line, .. } => {} NamedParameter { .. } => {} - Expression::ListGet { index, list} => { + Expression::ListGet { index, list } => { self.compile_expression(namespace, list, symbols, registry)?; self.compile_expression(namespace, index, symbols, registry)?; self.emit_byte(OP_LIST_GET); diff --git a/src/compiler_tests.rs b/src/compiler_tests.rs index 39246a1..03c1271 100644 --- a/src/compiler_tests.rs +++ b/src/compiler_tests.rs @@ -2,7 +2,7 @@ mod tests { use crate::value::Value; use crate::{compile, run}; - use chrono::{DateTime}; + use chrono::DateTime; #[test] fn literal_int() { @@ -42,8 +42,11 @@ mod tests { #[test] fn index_in_list_as_var() { - assert_eq!(run(r#"let a:list = ["abc","def"] -a[1]"#), Ok(Value::String("def".into()))) + assert_eq!( + run(r#"let a:list = ["abc","def"] +a[1]"#), + Ok(Value::String("def".into())) + ) } #[test] @@ -163,7 +166,7 @@ object Person: } #[test] - fn define_map() { + fn assign_map() { let result = run(r#"let m = {"name": "Dent"} m"#); @@ -176,6 +179,17 @@ m"#); } } + #[test] + fn access_map() { + let result = run(r#"let m = {"name": "Dent"} +m["name"]"#); + + let result = result.unwrap(); + if let Value::String(v) = result { + assert_eq!(v.as_str(), "Dent"); + } + } + #[test] fn keyword_error() { let result = run(r#"let map = {"name": "Dent"}"#); diff --git a/src/repl.rs b/src/repl.rs index 99d05d9..480c693 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -49,8 +49,6 @@ pub fn start(registry: Arc>>) -> Result<(), CrudL // break; // } } - // println!("-- Crudlang -- REPL exited"); - Ok(()) } fn list_endpoints(registry: Arc>) { diff --git a/src/symbol_builder.rs b/src/symbol_builder.rs index 340bd7e..018ae80 100644 --- a/src/symbol_builder.rs +++ b/src/symbol_builder.rs @@ -38,11 +38,7 @@ fn make_qname(path: &str, name: &Token) -> String { pub fn build(path: &str, ast: &[Statement], symbols: &mut HashMap) { for statement in ast { match statement { - Statement::VarStmt { - name, - var_type, - initializer, - } => { + Statement::VarStmt { name, var_type, .. } => { let key = make_qname(path, name); if !symbols.contains_key(&key) { // surely there's a better way to do this? diff --git a/src/value.rs b/src/value.rs index 34ceb67..518c416 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,5 +1,5 @@ use crate::errors::ValueError; -use chrono::{DateTime, Local, Utc}; +use chrono::{DateTime, Utc}; use std::cmp::Ordering; use std::collections::HashMap; use std::fmt::{Display, Formatter};