use crate::*; /// The entire semantic program, ready to generate bytecode. pub struct Program { pub definitions: Vec, pub invocations: Vec, pub errors: Vec, } /// A symbol definition. pub struct Definition { pub name: String, pub source: SourceSpan, pub arguments: Vec, pub variant: DefinitionVariant, } pub struct ArgumentDefinition { pub name: String, pub source: SourceSpan, pub variant: ArgumentDefinitionVariant, } pub enum ArgumentDefinitionVariant { Integer, Block, } pub enum DefinitionVariant { Integer(IntegerDefinition), Block(BlockDefinition), Reference(ReferenceDefinition), } pub struct IntegerDefinition { pub source: SourceSpan, pub variant: IntegerDefinitionVariant, } pub enum IntegerDefinitionVariant { Literal(usize), Constant(ConstantExpression), } pub struct BlockDefinition { pub tokens: Vec, pub errors: Vec, } pub struct BlockToken { pub source: SourceSpan, pub variant: BlockTokenVariant, } pub enum BlockTokenVariant { Invocation(Invocation), Comment(String), Word(PackedBinaryLiteral), } /// References aren't necessarily an integer or a block pub struct ReferenceDefinition { pub source: SourceSpan, pub name: String, } pub struct Invocation { pub name: String, pub arguments: Vec, } pub struct ParseError { pub source: SourceSpan, pub variant: ParseErrorVariant, } pub enum ParseErrorVariant { UnterminatedMacroDefinition, UnterminatedBlockDefinition, /// Name of the macro. InvalidArgumentDefinition(String), InvalidToken, } // ------------------------------------------------------------------------ // impl Program { pub fn print_definitions(&self) { for definition in &self.definitions { let variant = match definition.variant { DefinitionVariant::Integer(_) => "integer", DefinitionVariant::Block(_) => "block", DefinitionVariant::Reference(_) => "reference", }; println!("DEFINE {} ({variant})", definition.name); for argument in &definition.arguments { let variant = match argument.variant { ArgumentDefinitionVariant::Integer => "integer", ArgumentDefinitionVariant::Block => "block", }; println!(" ARGUMENT {} ({variant})", argument.name); } let variant = match &definition.variant { DefinitionVariant::Integer(integer) => todo!(), DefinitionVariant::Block(block) => todo!(), DefinitionVariant::Reference(reference) => todo!() }; println!(); } } }