diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-03-06 20:33:27 +1300 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-03-11 16:59:26 +1300 |
commit | 1ecee352f5844b0809d7ae66df52e34f42b44c8e (patch) | |
tree | 472b6fd57ff7f64ac3f8cd676cbe7a113ba01f05 /src/tokens/semantic.rs | |
parent | f2ed89083f5326a7a6f0a1720033d3388aa431fb (diff) | |
download | torque-asm-1ecee352f5844b0809d7ae66df52e34f42b44c8e.zip |
Rewrite entire assembler
The language is now more general, the code is better structured, error
reporting is more detailed, and many new language features have
been implemented:
- conditional blocks
- first-class strings
- more expression operators
- binary literals
- negative values
- invocations in constant expressions
Diffstat (limited to 'src/tokens/semantic.rs')
-rw-r--r-- | src/tokens/semantic.rs | 192 |
1 files changed, 0 insertions, 192 deletions
diff --git a/src/tokens/semantic.rs b/src/tokens/semantic.rs deleted file mode 100644 index 225cd6b..0000000 --- a/src/tokens/semantic.rs +++ /dev/null @@ -1,192 +0,0 @@ -use crate::*; - -use indexmap::IndexMap; - - -/// The entire semantic program, ready to generate bytecode. -pub struct SemanticProgram { - pub macro_definitions: IndexMap<String, MacroDefinition>, - pub label_definitions: IndexMap<String, LabelDefinition>, - pub body: Vec<SemanticToken>, -} - -/// A symbol definition. -pub struct MacroDefinition { - pub source: SourceSpan, - pub arguments: Vec<ArgumentDefinition>, - pub value: Value, - pub errors: Vec<SemanticParseError>, -} - -pub struct ArgumentDefinition { - pub name: String, - pub source: SourceSpan, - pub variant: ArgumentVariant, -} - -#[derive(PartialEq, Clone, Copy, Debug)] -pub enum ArgumentVariant { - Integer, - Block, -} - -pub struct ArgumentInvocation { - pub source: SourceSpan, - pub value: Value, -} - -pub enum Value { - Integer(Integer), - Block(Vec<SemanticToken>), - Invocation(Invocation), -} - -pub enum Integer { - Literal(TrackedInteger), - String(TrackedString), - Expression(Expression), - LabelReference(Tracked<String>), -} - -pub enum SemanticToken { - Word(PackedBinaryLiteral), - Invocation(Invocation), - LabelDefinition(LabelDefinition), - PinnedAddress(PinnedAddress), - Error(SemanticParseError), -} - -pub struct Invocation { - pub name: String, - pub source: SourceSpan, - pub arguments: Vec<ArgumentInvocation>, - pub errors: Vec<SemanticParseError>, -} - -#[derive(Clone)] -pub struct LabelDefinition { - pub source: SourceSpan, - pub name: String, -} - -#[derive(Clone)] -pub struct PinnedAddress { - pub source: SourceSpan, - pub address: usize, -} - -pub struct SemanticParseError { - pub source: SourceSpan, - pub variant: SemanticParseErrorVariant, -} - -pub enum SemanticParseErrorVariant { - UnterminatedMacroDefinition(String), - UnterminatedBlock, - InvalidToken, -} - - -impl std::fmt::Display for ArgumentVariant { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - match self { - ArgumentVariant::Integer => write!(f, "integer"), - ArgumentVariant::Block => write!(f, "block"), - } - } -} - -// ------------------------------------------------------------------------ // - -macro_rules! indent { - ($indent:expr => $($tokens:tt)*) => {{ - for _ in 0..$indent { print!(" "); } - println!($($tokens)*); - }}; -} - -impl SemanticProgram { - pub fn print_definitions(&self) { - for (name, definition) in &self.macro_definitions { - let variant = match &definition.value { - Value::Integer(_) => "INTEGER", - Value::Block(_) => "BLOCK", - Value::Invocation(_) => "INVOCATION", - }; - println!("DEFINE {variant} '{name}'"); - for argument in &definition.arguments { - self.print_argument_definition(argument); - } - match &definition.value { - Value::Integer(integer) => - self.print_integer(1, integer), - Value::Block(block) => - self.print_block(1, block), - Value::Invocation(invocation) => - indent!(1 => "INVOCATION '{}'", invocation.name), - }; - println!(); - } - - println!("LABELS"); - for (name, _) in &self.label_definitions { - println!(" @{name}"); - } - println!(); - - self.print_block(0, &self.body); - } - - fn print_argument_definition(&self, argument: &ArgumentDefinition) { - let variant = match argument.variant { - ArgumentVariant::Integer => "INTEGER", - ArgumentVariant::Block => "BLOCK", - }; - println!(" ARGUMENT {variant} '{}'", argument.name); - } - - fn print_integer(&self, indent: usize, integer: &Integer) { - match &integer { - Integer::Literal(value) => - indent!(indent => "LITERAL {value}"), - Integer::Expression(expr) => - indent!(indent => "EXPRESSION [{expr:?}]"), - Integer::String(string) => - indent!(indent => "STRING '{string}'"), - Integer::LabelReference(name) => - indent!(indent => "LABEL REFERENCE '{name}'"), - } - } - - fn print_block(&self, indent: usize, block: &[SemanticToken]) { - indent!(indent => "BLOCK"); - for semantic_token in block { - match &semantic_token { - SemanticToken::Word(word) => - indent!(indent+1 => "WORD #{word}"), - SemanticToken::Invocation(invocation) => - self.print_invocation(indent+1, invocation), - SemanticToken::LabelDefinition(definition) => - indent!(indent+1 => "LABEL DEFINITION @{}", definition.name), - SemanticToken::PinnedAddress(addr) => - indent!(indent+1 => "PINNED ADDRESS {}", addr.address), - SemanticToken::Error(_) => - indent!(indent+1 => "ERROR"), - } - } - } - - fn print_invocation(&self, indent: usize, invocation: &Invocation) { - indent!(indent => "INVOCATION '{}'", invocation.name); - for argument in &invocation.arguments { - match &argument.value { - Value::Integer(integer) => - self.print_integer(indent+1, integer), - Value::Block(block) => - self.print_block(indent+1, block), - Value::Invocation(invocation) => - self.print_invocation(indent+1, invocation), - }; - } - } -} |