summaryrefslogtreecommitdiff
path: root/src/tokens/semantic.rs
blob: 66db7b2090f93161e7b7ec22370c331e91be4232 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use crate::*;


/// The entire semantic program, ready to generate bytecode.
pub struct Program {
    pub definitions: Vec<Definition>,
    pub invocations: Vec<Invocation>,
    pub errors: Vec<ParseError>,
}

/// A symbol definition.
pub struct Definition {
    pub name: String,
    pub source: SourceSpan,
    pub arguments: Vec<ArgumentDefinition>,
    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<BlockToken>,
    pub errors: Vec<ParseError>,
}

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<DefinitionVariant>,
}

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!();
        }
    }
}