From 0f32d50293ffb1a990acf9eec128415ba54a9561 Mon Sep 17 00:00:00 2001 From: Ben Bridle Date: Mon, 13 Oct 2025 18:14:51 +1300 Subject: Implement lists as a first-class type Previously, strings were implemented as lists of integers, but there was no way to create an arbitrary list of integers to pass to a macro invocation. This commit extends the []-delimited expression syntax, treating expressions that contain only integers and invocations as lists of integers. Strings are implemented as a sub-type of list. --- src/stages/semantic.rs | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) (limited to 'src/stages/semantic.rs') diff --git a/src/stages/semantic.rs b/src/stages/semantic.rs index b72cfa8..fdd1766 100644 --- a/src/stages/semantic.rs +++ b/src/stages/semantic.rs @@ -144,9 +144,9 @@ impl SemanticParser { MacroDefinitionBody::Block(mut tokens) => { block_tokens.append(&mut tokens); } - MacroDefinitionBody::String(string) => { + MacroDefinitionBody::List(list) => { let error = SemanticError::ExpectedBlock(location); - let tracked = Tracked::from(error, string.source); + let tracked = Tracked::from(error, list.source); self.errors.push(tracked); } MacroDefinitionBody::Invocation(invocation) => { @@ -184,9 +184,9 @@ impl SemanticParser { Some(MacroDefinitionBody::Integer(tracked)) } SyntacticToken::StringLiteral(value) => { - let token = StringToken::StringLiteral(value); + let token = ListToken::StringLiteral(value); let tracked = Tracked::from(token, source); - Some(MacroDefinitionBody::String(tracked)) + Some(MacroDefinitionBody::List(tracked)) } SyntacticToken::WordTemplate(word_template) => { let token = BlockToken::WordTemplate(word_template); @@ -205,9 +205,16 @@ impl SemanticParser { let mut parser = SemanticParser::from(tokens, self.namespace.clone()); let expression = parser.parse_expression(); self.pull_from(parser); - let token = IntegerToken::Expression(expression); - let tracked = Tracked::from(token, source); - Some(MacroDefinitionBody::Integer(tracked)) + if expression.is_list() { + let list = expression.to_list(); + let token = ListToken::ListLiteral(list); + let tracked = Tracked::from(token, source); + Some(MacroDefinitionBody::List(tracked)) + } else { + let token = IntegerToken::Expression(expression); + let tracked = Tracked::from(token, source); + Some(MacroDefinitionBody::Integer(tracked)) + } } SyntacticToken::Symbol(symbol) => { let name = self.resolve_symbol_name(symbol, &source)?; @@ -265,9 +272,9 @@ impl SemanticParser { self.errors.push(Tracked::from(error, token.source)); None } - MacroDefinitionBody::String(string) => { + MacroDefinitionBody::List(list) => { let error = SemanticError::ExpectedInteger(location); - self.errors.push(Tracked::from(error, string.source)); + self.errors.push(Tracked::from(error, list.source)); None } } @@ -291,9 +298,9 @@ impl SemanticParser { self.errors.push(Tracked::from(error, integer.source)); None } - MacroDefinitionBody::String(string) => { + MacroDefinitionBody::List(list) => { let error = SemanticError::ExpectedBlock(location); - self.errors.push(Tracked::from(error, string.source)); + self.errors.push(Tracked::from(error, list.source)); None } } @@ -372,8 +379,8 @@ impl SemanticParser { let source = token.source; match token.value { SyntacticToken::StringLiteral(string_literal) => { - let string = StringToken::StringLiteral(string_literal); - let argument = InvocationArgument::StringToken(string); + let string = ListToken::StringLiteral(string_literal); + let argument = InvocationArgument::ListToken(string); Some(Tracked::from(argument, source)) } SyntacticToken::IntegerLiteral(value) => { @@ -385,9 +392,16 @@ impl SemanticParser { let mut parser = SemanticParser::from(tokens, self.namespace.clone()); let expression = parser.parse_expression(); self.pull_from(parser); - let integer = IntegerToken::Expression(expression); - let argument = InvocationArgument::IntegerToken(integer); - Some(Tracked::from(argument, source)) + if expression.is_list() { + let list = expression.to_list(); + let token = ListToken::ListLiteral(list); + let argument = InvocationArgument::ListToken(token); + Some(Tracked::from(argument, source)) + } else { + let integer = IntegerToken::Expression(expression); + let argument = InvocationArgument::IntegerToken(integer); + Some(Tracked::from(argument, source)) + } } SyntacticToken::BlockLiteral(tokens) => { let mut parser = SemanticParser::from(tokens, self.namespace.clone()); -- cgit v1.2.3-70-g09d2