adding map access was easy

This commit is contained in:
Shautvast 2025-11-10 11:09:55 +01:00
parent cbc7f6ce7a
commit 6f4824efac
6 changed files with 41 additions and 40 deletions

View file

@ -520,35 +520,39 @@ impl AstCompiler {
) -> Result<Expression, CompilerErrorAtLine> { ) -> Result<Expression, CompilerErrorAtLine> {
let get = (match &operand { let get = (match &operand {
Expression::Map { .. } => MapGet { Expression::Map { .. } => MapGet {
map: Box::new(operand),
key: Box::new(index), key: Box::new(index),
}, },
Expression::List { .. } => ListGet { Expression::List { .. } => ListGet {
list: Box::new(operand), list: Box::new(operand),
index: Box::new(index), index: Box::new(index),
}, },
Variable { var_type, .. } => { Variable { var_type, .. } => match var_type {
if var_type == &ListType { ListType => ListGet {
ListGet { list: Box::new(operand),
list: Box::new(operand), index: Box::new(index),
index: Box::new(index), },
} MapType => MapGet {
} else { map: Box::new(operand),
key: Box::new(index),
},
_ => {
return Err(self.raise(CompilerError::IllegalTypeToIndex(var_type.to_string()))); return Err(self.raise(CompilerError::IllegalTypeToIndex(var_type.to_string())));
} }
} },
_ => return Err(self.raise(CompilerError::IllegalTypeToIndex("Unknown".to_string()))), _ => return Err(self.raise(CompilerError::IllegalTypeToIndex("Unknown".to_string()))),
}); });
self.consume(RightBracket, Expected("']' after index."))?; self.consume(RightBracket, Expected("']' after index."))?;
Ok(get) Ok(get)
} }
// work in progress
fn field( fn field(
&mut self, &mut self,
operand: Expression, _operand: Expression,
index: Token, index: Token,
) -> Result<Expression, CompilerErrorAtLine> { ) -> Result<Expression, CompilerErrorAtLine> {
//TODO? Ok(FieldGet {
Ok(Expression::FieldGet {
field: index.lexeme.clone(), field: index.lexeme.clone(),
}) })
} }
@ -635,7 +639,7 @@ impl AstCompiler {
&self.previous().lexeme, &self.previous().lexeme,
"%Y-%m-%d %H:%M:%S%.3f %z", "%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(), .into(),
), ),
} }
@ -945,6 +949,7 @@ pub enum Expression {
value: Box<Expression>, value: Box<Expression>,
}, },
MapGet { MapGet {
map: Box<Expression>,
key: Box<Expression>, key: Box<Expression>,
}, },
ListGet { ListGet {

View file

@ -102,17 +102,11 @@ impl Compiler {
self.current_line = statement.line(); self.current_line = statement.line();
match statement { match statement {
Statement::VarStmt { Statement::VarStmt {
name, name, initializer, ..
var_type,
initializer,
} => { } => {
let name = name.lexeme.as_str(); let name = name.lexeme.as_str();
let var = symbols.get(name); let var = symbols.get(name);
if let Some(Symbol::Variable { if let Some(Symbol::Variable { var_type, .. }) = var {
var_type,
..
}) = var
{
let inferred_type = infer_type(initializer, symbols); let inferred_type = infer_type(initializer, symbols);
let calculated_type = calculate_type(var_type, &inferred_type) let calculated_type = calculate_type(var_type, &inferred_type)
.map_err(|e| CompilerErrorAtLine::raise(e, statement.line()))?; .map_err(|e| CompilerErrorAtLine::raise(e, statement.line()))?;
@ -189,13 +183,7 @@ impl Compiler {
.find_constant(&name) .find_constant(&name)
.unwrap_or_else(|| self.chunk.add_constant(Value::String(name.to_string()))); .unwrap_or_else(|| self.chunk.add_constant(Value::String(name.to_string())));
let function = symbols.get(name); let function = symbols.get(name);
if let Some(Symbol::Function { if let Some(Symbol::Function { parameters, .. }) = function {
name,
parameters,
return_type,
body,
}) = function
{
for parameter in parameters { for parameter in parameters {
for argument in arguments { for argument in arguments {
if let NamedParameter { name, .. } = argument { if let NamedParameter { name, .. } = argument {
@ -295,7 +283,7 @@ impl Compiler {
Expression::Stop { .. } => {} Expression::Stop { .. } => {}
// Expression::PathMatch { line, .. } => {} // Expression::PathMatch { line, .. } => {}
NamedParameter { .. } => {} NamedParameter { .. } => {}
Expression::ListGet { index, list} => { Expression::ListGet { index, list } => {
self.compile_expression(namespace, list, symbols, registry)?; self.compile_expression(namespace, list, symbols, registry)?;
self.compile_expression(namespace, index, symbols, registry)?; self.compile_expression(namespace, index, symbols, registry)?;
self.emit_byte(OP_LIST_GET); self.emit_byte(OP_LIST_GET);

View file

@ -2,7 +2,7 @@
mod tests { mod tests {
use crate::value::Value; use crate::value::Value;
use crate::{compile, run}; use crate::{compile, run};
use chrono::{DateTime}; use chrono::DateTime;
#[test] #[test]
fn literal_int() { fn literal_int() {
@ -42,8 +42,11 @@ mod tests {
#[test] #[test]
fn index_in_list_as_var() { fn index_in_list_as_var() {
assert_eq!(run(r#"let a:list = ["abc","def"] assert_eq!(
a[1]"#), Ok(Value::String("def".into()))) run(r#"let a:list = ["abc","def"]
a[1]"#),
Ok(Value::String("def".into()))
)
} }
#[test] #[test]
@ -163,7 +166,7 @@ object Person:
} }
#[test] #[test]
fn define_map() { fn assign_map() {
let result = run(r#"let m = {"name": "Dent"} let result = run(r#"let m = {"name": "Dent"}
m"#); 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] #[test]
fn keyword_error() { fn keyword_error() {
let result = run(r#"let map = {"name": "Dent"}"#); let result = run(r#"let map = {"name": "Dent"}"#);

View file

@ -49,8 +49,6 @@ pub fn start(registry: Arc<ArcSwap<HashMap<String, Chunk>>>) -> Result<(), CrudL
// break; // break;
// } // }
} }
// println!("-- Crudlang -- REPL exited");
Ok(())
} }
fn list_endpoints(registry: Arc<HashMap<String, Chunk>>) { fn list_endpoints(registry: Arc<HashMap<String, Chunk>>) {

View file

@ -38,11 +38,7 @@ fn make_qname(path: &str, name: &Token) -> String {
pub fn build(path: &str, ast: &[Statement], symbols: &mut HashMap<String, Symbol>) { pub fn build(path: &str, ast: &[Statement], symbols: &mut HashMap<String, Symbol>) {
for statement in ast { for statement in ast {
match statement { match statement {
Statement::VarStmt { Statement::VarStmt { name, var_type, .. } => {
name,
var_type,
initializer,
} => {
let key = make_qname(path, name); let key = make_qname(path, name);
if !symbols.contains_key(&key) { if !symbols.contains_key(&key) {
// surely there's a better way to do this? // surely there's a better way to do this?

View file

@ -1,5 +1,5 @@
use crate::errors::ValueError; use crate::errors::ValueError;
use chrono::{DateTime, Local, Utc}; use chrono::{DateTime, Utc};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};