summaryrefslogtreecommitdiff
path: root/src/tokens/semantic.rs
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2025-03-06 20:33:27 +1300
committerBen Bridle <ben@derelict.engineering>2025-03-11 16:59:26 +1300
commit1ecee352f5844b0809d7ae66df52e34f42b44c8e (patch)
tree472b6fd57ff7f64ac3f8cd676cbe7a113ba01f05 /src/tokens/semantic.rs
parentf2ed89083f5326a7a6f0a1720033d3388aa431fb (diff)
downloadtorque-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.rs192
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),
- };
- }
- }
-}