diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-04-26 13:00:51 +1200 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-04-26 13:00:51 +1200 |
commit | e5447e2568e24db9a5218bbe452b856266ca39ae (patch) | |
tree | e5425bf49fb7ff93b8c46a80b8742a85ecf19fe4 /src/stages/semantic.rs | |
parent | 83e5107684a37aa825d626c19a2af7fd6bfc231a (diff) | |
download | torque-asm-e5447e2568e24db9a5218bbe452b856266ca39ae.zip |
Implement first-class string literals
This feature promotes strings to a first-class type in the language.
If a string is passed to an invocation via the new string-type argument,
the string will be passed as a whole value. String arguments can still
be passed to an invocation via an integer-type argument, in which case
they'll be broken apart into individual characters with the macro being
invoked once per character.
String-type macro arguments are declared like "name".
Diffstat (limited to 'src/stages/semantic.rs')
-rw-r--r-- | src/stages/semantic.rs | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/src/stages/semantic.rs b/src/stages/semantic.rs index ec2f704..6cd83f8 100644 --- a/src/stages/semantic.rs +++ b/src/stages/semantic.rs @@ -144,6 +144,11 @@ impl SemanticParser { MacroDefinitionBody::Block(mut tokens) => { block_tokens.append(&mut tokens); } + MacroDefinitionBody::String(string) => { + let error = SemanticError::ExpectedBlock(location); + let tracked = Tracked::from(error, string.source); + self.errors.push(tracked); + } MacroDefinitionBody::Invocation(invocation) => { // Convert invocation to a block invocation. let token = BlockToken::Invocation(invocation.value); @@ -178,10 +183,10 @@ impl SemanticParser { let tracked = Tracked::from(token, source); Some(MacroDefinitionBody::Integer(tracked)) } - SyntacticToken::StringLiteral(_) => { - let error = SemanticError::MisplacedStringLiteral; - self.errors.push(Tracked::from(error, source)); - None + SyntacticToken::StringLiteral(value) => { + let token = StringToken::StringLiteral(value); + let tracked = Tracked::from(token, source); + Some(MacroDefinitionBody::String(tracked)) } SyntacticToken::WordTemplate(word_template) => { let token = BlockToken::WordTemplate(word_template); @@ -260,6 +265,11 @@ impl SemanticParser { self.errors.push(Tracked::from(error, token.source)); None } + MacroDefinitionBody::String(string) => { + let error = SemanticError::ExpectedInteger(location); + self.errors.push(Tracked::from(error, string.source)); + None + } } } @@ -281,6 +291,11 @@ impl SemanticParser { self.errors.push(Tracked::from(error, integer.source)); None } + MacroDefinitionBody::String(string) => { + let error = SemanticError::ExpectedBlock(location); + self.errors.push(Tracked::from(error, string.source)); + None + } } } @@ -357,7 +372,8 @@ impl SemanticParser { let source = token.source; match token.value { SyntacticToken::StringLiteral(string_literal) => { - let argument = InvocationArgument::String(string_literal); + let string = StringToken::StringLiteral(string_literal); + let argument = InvocationArgument::StringToken(string); Some(Tracked::from(argument, source)) } SyntacticToken::IntegerLiteral(value) => { @@ -430,6 +446,12 @@ impl SemanticParser { } } } + SyntacticToken::StringLiteral(string) => { + let variant = ArgumentType::String; + let name = string.string; + let definition = ArgumentDefinition { name, variant }; + return Some(Tracked::from(definition, source)); + } _ => (), }; let error = SemanticError::InvalidArgumentDefinition; |