From ab29612ca8b3096d6d836832dd9b2e47015158c4 Mon Sep 17 00:00:00 2001 From: Alvin <524715@vistacollege.nl> Date: Wed, 10 Sep 2025 13:31:19 +0200 Subject: [PATCH] Feat: Add string concatenation feature and example --- examples/string_manipulation.tralla | 16 ++++ src/main.rs | 141 ++++++++++++++++++++++++++-- 2 files changed, 151 insertions(+), 6 deletions(-) create mode 100644 examples/string_manipulation.tralla diff --git a/examples/string_manipulation.tralla b/examples/string_manipulation.tralla new file mode 100644 index 0000000..0d2a072 --- /dev/null +++ b/examples/string_manipulation.tralla @@ -0,0 +1,16 @@ +// string_manipulation.tralla +// This example demonstrates string concatenation. + +let greeting = "Hello"; +let name = "World"; + +Unire Corde full_greeting greeting name; +print("Concatenated string:", full_greeting); // Expected: Concatenated string: HelloWorld + +Unire Corde message "This is a " "test."; +print("Another concatenated string:", message); // Expected: Another concatenated string: This is a test. + +let space = " "; +Unire Corde spaced_greeting greeting space; +Unire Corde final_greeting spaced_greeting name; +print("Concatenated with space:", final_greeting); // Expected: Concatenated with space: Hello World diff --git a/src/main.rs b/src/main.rs index 70de80d..8c7ae46 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,14 @@ use std::env; use std::fs; use std::collections::HashMap; +#[derive(Debug, Clone)] +struct Function { + name: String, + args: Vec, + body_start: usize, + body_end: usize, +} + fn main() { let args: Vec = env::args().collect(); if args.len() < 2 { @@ -25,10 +33,64 @@ fn main() { } let mut variables: HashMap = HashMap::new(); - let mut pc = 1; // Program counter starts after "Tralalero Tralala" + let mut functions: HashMap = HashMap::new(); + // First pass: collect function definitions + let mut pc = 1; while pc < lines.len() - 1 { - pc = parse_and_execute(pc, &lines, &mut variables); + let line = lines[pc].trim(); + let mut words = line.split_whitespace(); + if let Some(keyword) = words.next() { + if keyword == "Lirili" { + if let Some(word2) = words.next() { + if word2 == "Larila" { + if let Some(fn_name) = words.next() { + let args_str = words.collect::>().join(" "); + let args = args_str + .trim_start_matches('(') + .trim_end_matches(')') + .split(',') + .map(|s| s.trim().to_string()) + .collect(); + + let body_start = pc + 2; + let mut body_end = body_start; + let mut brace_count = 1; + + for i in body_start..lines.len() { + if lines[i].trim() == "{" { + brace_count += 1; + } + if lines[i].trim() == "}" { + brace_count -= 1; + if brace_count == 0 { + body_end = i; + break; + } + } + } + + let function = Function { + name: fn_name.to_string(), + args, + body_start, + body_end, + }; + functions.insert(fn_name.to_string(), function); + pc = body_end + 1; + continue; + } + } + } + } + } + pc += 1; + } + + // Second pass: execute the code + pc = 1; + while pc < lines.len() - 1 { + pc = parse_and_execute(pc, &lines, &mut variables, &functions); } } @@ -42,11 +104,28 @@ fn get_value(s: &str, variables: &HashMap) -> Option { } } -fn parse_and_execute(pc: usize, lines: &Vec<&str>, variables: &mut HashMap) -> usize { +fn parse_and_execute(pc: usize, lines: &Vec<&str>, variables: &mut HashMap, functions: &HashMap) -> usize { let line = lines[pc].trim(); let mut words = line.split_whitespace(); if let Some(keyword) = words.next() { + if keyword == "Lirili" { // Skip function definitions + let mut brace_count = 1; + let mut end_pc = pc + 2; + for i in (pc + 2)..lines.len() { + if lines[i].trim() == "{" { + brace_count += 1; + } + if lines[i].trim() == "}" { + brace_count -= 1; + if brace_count == 0 { + end_pc = i; + break; + } + } + } + return end_pc + 1; + } if keyword == "Biscottini" { if let Some(var_name) = words.next() { let value = words.collect::>().join(" "); @@ -87,7 +166,7 @@ fn parse_and_execute(pc: usize, lines: &Vec<&str>, variables: &mut HashMap, variables: &mut HashMap, variables: &mut HashMap, variables: &mut HashMap = fn_call_str.splitn(2, '(').collect(); + if parts.len() == 2 { + let fn_name = parts[0]; + if let Some(function) = functions.get(fn_name).cloned() { + let args_str = parts[1].trim_end_matches(')'); + let arg_values: Vec<&str> = args_str.split(',').map(|s| s.trim()).collect(); + + let mut local_vars = variables.clone(); + for (i, arg_name) in function.args.iter().enumerate() { + if let Some(arg_value) = arg_values.get(i) { + local_vars.insert(arg_name.clone(), arg_value.to_string()); + } + } + + let mut inner_pc = function.body_start; + while inner_pc < function.body_end { + inner_pc = parse_and_execute(inner_pc, lines, &mut local_vars, functions); + } + } + } + } + } + } } } pc + 1