Files
@ fc987660fdee
Branch filter:
Location: CSY/reowolf/src/protocol/parser/mod.rs - annotation
fc987660fdee
11.8 KiB
application/rls-services+xml
WIP on compiler rearchitecting
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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 | 33ea10021de4 9774ef9fe888 7f25ee16c39b 9774ef9fe888 ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa f091e98ceccd b194b811d0cc a23c6c8e99e9 cd546710a6c9 33ea10021de4 33ea10021de4 ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa a23c6c8e99e9 a23c6c8e99e9 6ec2e0261a03 fdaf709bf0ca 33ea10021de4 06f259bf8031 ddddcd3cc9aa 06f259bf8031 06f259bf8031 33ea10021de4 729feec4d37a 06f259bf8031 fc987660fdee fc987660fdee fc987660fdee fc987660fdee ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa ddddcd3cc9aa 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 9774ef9fe888 06f259bf8031 06f259bf8031 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 9774ef9fe888 9774ef9fe888 06f259bf8031 06f259bf8031 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 9774ef9fe888 9774ef9fe888 9774ef9fe888 b826e300c566 06f259bf8031 06f259bf8031 c87205ed6292 33ea10021de4 33ea10021de4 33ea10021de4 06f259bf8031 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 06f259bf8031 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 c87205ed6292 33ea10021de4 33ea10021de4 33ea10021de4 06f259bf8031 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 c87205ed6292 33ea10021de4 33ea10021de4 33ea10021de4 06f259bf8031 33ea10021de4 33ea10021de4 33ea10021de4 06f259bf8031 06f259bf8031 06f259bf8031 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 06f259bf8031 33ea10021de4 33ea10021de4 06f259bf8031 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 c87205ed6292 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 06f259bf8031 06f259bf8031 c87205ed6292 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 9774ef9fe888 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 06f259bf8031 06f259bf8031 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 06f259bf8031 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 ddddcd3cc9aa 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 ddddcd3cc9aa 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 28df9835906f 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 33ea10021de4 06f259bf8031 06f259bf8031 e406c61b1158 e406c61b1158 06f259bf8031 06f259bf8031 33ea10021de4 33ea10021de4 9774ef9fe888 9774ef9fe888 b194b811d0cc 9774ef9fe888 06f259bf8031 06f259bf8031 c87205ed6292 9774ef9fe888 6717437470eb 9774ef9fe888 6717437470eb 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 6ec2e0261a03 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 6ec2e0261a03 6ec2e0261a03 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 6ec2e0261a03 729feec4d37a 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 9774ef9fe888 c87205ed6292 9774ef9fe888 06f259bf8031 6717437470eb 3c33e2928fb4 3c33e2928fb4 3c33e2928fb4 ca97483c6ec7 9774ef9fe888 06f259bf8031 06f259bf8031 33ea10021de4 6717437470eb 729feec4d37a 729feec4d37a 729feec4d37a 729feec4d37a 729feec4d37a 729feec4d37a ca97483c6ec7 729feec4d37a 729feec4d37a 06f259bf8031 6717437470eb 6717437470eb 06f259bf8031 06f259bf8031 06f259bf8031 33ea10021de4 33ea10021de4 06f259bf8031 9774ef9fe888 | mod depth_visitor;
pub(crate) mod symbol_table;
pub(crate) mod symbol_table2;
pub(crate) mod type_table;
pub(crate) mod tokens;
pub(crate) mod token_parsing;
pub(crate) mod pass_tokenizer;
pub(crate) mod pass_symbols;
pub(crate) mod pass_imports;
pub(crate) mod pass_definitions;
mod type_resolver;
mod visitor;
mod visitor_linker;
mod utils;
use depth_visitor::*;
use tokens::*;
use crate::collections::*;
use symbol_table2::SymbolTable;
use visitor::Visitor2;
use visitor_linker::ValidityAndLinkerVisitor;
use type_resolver::{TypeResolvingVisitor, ResolveQueue};
use type_table::{TypeTable, TypeCtx};
use crate::protocol::ast::*;
use crate::protocol::input_source2::{InputSource2 as InputSource};
use crate::protocol::lexer::*;
use std::collections::HashMap;
use crate::protocol::ast_printer::ASTWriter;
pub(crate) const LIMIT_NUM_TYPE_NODES: usize = 64;
pub(crate) const LIMIT_NUM_POLY_VARS: usize = 64;
pub(crate) const LIMIT_NUM_PROC_ARGS: usize = 64;
#[derive(PartialEq, Eq)]
pub enum ModuleCompilationPhase {
Source, // only source is set
Tokenized, // source is tokenized
SymbolsScanned, // all definitions are linked to their type class
ImportsResolved, // all imports are added to the symbol table
DefinitionsParsed, // produced the AST for the entire module
ValidatedAndLinked, // AST is traversed and has linked the required AST nodes
Typed, // Type inference and checking has been performed
}
pub struct Module {
// Buffers
source: InputSource,
tokens: TokenBuffer,
// Identifiers
root_id: RootId,
name: Option<(PragmaId, StringRef<'static>)>,
version: Option<(PragmaId, i64)>,
phase: ModuleCompilationPhase,
}
pub struct PassCtx<'a> {
heap: &'a mut Heap,
symbols: &'a mut SymbolTable,
pool: &'a mut StringPool,
}
// TODO: @fixme, pub qualifier
pub(crate) struct LexedModule {
pub(crate) source: InputSource,
module_name: Vec<u8>,
version: Option<u64>,
pub(crate) root_id: RootId,
}
pub struct Parser {
pub(crate) heap: Heap,
pub(crate) modules: Vec<LexedModule>,
pub(crate) module_lookup: HashMap<Vec<u8>, usize>, // from (optional) module name to `modules` idx
pub(crate) symbol_table: SymbolTable,
pub(crate) type_table: TypeTable,
}
impl Parser {
pub fn new() -> Self {
Parser{
heap: Heap::new(),
modules: Vec::new(),
module_lookup: HashMap::new(),
symbol_table: SymbolTable::new(),
type_table: TypeTable::new(),
}
}
pub fn feed(&mut self, mut source: InputSource) -> Result<RootId, ParseError> {
// Lex the input source
let mut lex = Lexer::new(&mut source);
let pd = lex.consume_protocol_description(&mut self.heap)?;
// Seek the module name and version
let root = &self.heap[pd];
let mut module_name_pos = InputPosition::default();
let mut module_name = Vec::new();
let mut module_version_pos = InputPosition::default();
let mut module_version = None;
for pragma in &root.pragmas {
match &self.heap[*pragma] {
Pragma::Module(module) => {
if !module_name.is_empty() {
return Err(
ParseError::new_error(&source, module.position, "Double definition of module name in the same file")
.with_postfixed_info(&source, module_name_pos, "Previous definition was here")
)
}
module_name_pos = module.position.clone();
module_name = module.value.clone();
},
Pragma::Version(version) => {
if module_version.is_some() {
return Err(
ParseError::new_error(&source, version.position, "Double definition of module version")
.with_postfixed_info(&source, module_version_pos, "Previous definition was here")
)
}
module_version_pos = version.position.clone();
module_version = Some(version.version);
},
}
}
// Add module to list of modules and prevent naming conflicts
let cur_module_idx = self.modules.len();
if let Some(prev_module_idx) = self.module_lookup.get(&module_name) {
// Find `#module` statement in other module again
let prev_module = &self.modules[*prev_module_idx];
let prev_module_pos = self.heap[prev_module.root_id].pragmas
.iter()
.find_map(|p| {
match &self.heap[*p] {
Pragma::Module(module) => Some(module.position.clone()),
_ => None
}
})
.unwrap_or(InputPosition::default());
let module_name_msg = if module_name.is_empty() {
format!("a nameless module")
} else {
format!("module '{}'", String::from_utf8_lossy(&module_name))
};
return Err(
ParseError::new_error(&source, module_name_pos, &format!("Double definition of {} across files", module_name_msg))
.with_postfixed_info(&prev_module.source, prev_module_pos, "Other definition was here")
);
}
self.modules.push(LexedModule{
source,
module_name: module_name.clone(),
version: module_version,
root_id: pd
});
self.module_lookup.insert(module_name, cur_module_idx);
Ok(pd)
}
fn resolve_symbols_and_types(&mut self) -> Result<(), ParseError> {
// Construct the symbol table to resolve any imports and/or definitions,
// then use the symbol table to actually annotate all of the imports.
// If the type table is constructed correctly then all imports MUST be
// resolvable.
self.symbol_table.build(&self.heap, &self.modules)?;
// Not pretty, but we need to work around rust's borrowing rules, it is
// totally safe to mutate the contents of an AST element that we are
// not borrowing anywhere else.
let mut module_index = 0;
let mut import_index = 0;
loop {
if module_index >= self.modules.len() {
break;
}
let module_root_id = self.modules[module_index].root_id;
let import_id = {
let root = &self.heap[module_root_id];
if import_index >= root.imports.len() {
module_index += 1;
import_index = 0;
continue
}
root.imports[import_index]
};
let import = &mut self.heap[import_id];
match import {
Import::Module(import) => {
debug_assert!(import.module_id.is_none(), "module import already resolved");
let target_module_id = self.symbol_table.resolve_module(&import.module)
.expect("module import is resolved by symbol table");
import.module_id = Some(target_module_id)
},
Import::Symbols(import) => {
debug_assert!(import.module_id.is_none(), "module of symbol import already resolved");
let target_module_id = self.symbol_table.resolve_module(&import.module)
.expect("symbol import's module is resolved by symbol table");
import.module_id = Some(target_module_id);
for symbol in &mut import.symbols {
debug_assert!(symbol.definition_id.is_none(), "symbol import already resolved");
let (_, target_definition_id) = self.symbol_table.resolve_identifier(module_root_id, &symbol.alias)
.expect("symbol import is resolved by symbol table")
.as_definition()
.expect("symbol import does not resolve to namespace symbol");
symbol.definition_id = Some(target_definition_id);
}
}
}
import_index += 1;
}
// All imports in the AST are now annotated. We now use the symbol table
// to construct the type table.
let mut type_ctx = TypeCtx::new(&self.symbol_table, &mut self.heap, &self.modules);
self.type_table.build_base_types(&mut type_ctx)?;
Ok(())
}
pub fn parse(&mut self) -> Result<(), ParseError> {
self.resolve_symbols_and_types()?;
// Validate and link all modules
let mut visit = ValidityAndLinkerVisitor::new();
for module in &self.modules {
let mut ctx = visitor::Ctx{
heap: &mut self.heap,
module,
symbols: &mut self.symbol_table,
types: &mut self.type_table,
};
visit.visit_module(&mut ctx)?;
}
// Perform typechecking on all modules
let mut visit = TypeResolvingVisitor::new();
let mut queue = ResolveQueue::new();
for module in &self.modules {
let ctx = visitor::Ctx{
heap: &mut self.heap,
module,
symbols: &mut self.symbol_table,
types: &mut self.type_table,
};
TypeResolvingVisitor::queue_module_definitions(&ctx, &mut queue);
};
while !queue.is_empty() {
let top = queue.pop().unwrap();
let mut ctx = visitor::Ctx{
heap: &mut self.heap,
module: &self.modules[top.root_id.index as usize],
symbols: &mut self.symbol_table,
types: &mut self.type_table,
};
visit.handle_module_definition(&mut ctx, &mut queue, top)?;
}
// Perform remaining steps
// TODO: Phase out at some point
for module in &self.modules {
let root_id = module.root_id;
if let Err((position, message)) = Self::parse_inner(&mut self.heap, root_id) {
return Err(ParseError::new_error(&self.modules[0].source, position, &message))
}
}
// let mut writer = ASTWriter::new();
// let mut file = std::fs::File::create(std::path::Path::new("ast.txt")).unwrap();
// writer.write_ast(&mut file, &self.heap);
Ok(())
}
pub fn parse_inner(h: &mut Heap, pd: RootId) -> VisitorResult {
// TODO: @cleanup, slowly phasing out old compiler
// NestedSynchronousStatements::new().visit_protocol_description(h, pd)?;
// ChannelStatementOccurrences::new().visit_protocol_description(h, pd)?;
// FunctionStatementReturns::new().visit_protocol_description(h, pd)?;
// ComponentStatementReturnNew::new().visit_protocol_description(h, pd)?;
// CheckBuiltinOccurrences::new().visit_protocol_description(h, pd)?;
// BuildSymbolDeclarations::new().visit_protocol_description(h, pd)?;
// LinkCallExpressions::new().visit_protocol_description(h, pd)?;
// BuildScope::new().visit_protocol_description(h, pd)?;
// ResolveVariables::new().visit_protocol_description(h, pd)?;
LinkStatements::new().visit_protocol_description(h, pd)?;
// BuildLabels::new().visit_protocol_description(h, pd)?;
// ResolveLabels::new().visit_protocol_description(h, pd)?;
AssignableExpressions::new().visit_protocol_description(h, pd)?;
IndexableExpressions::new().visit_protocol_description(h, pd)?;
SelectableExpressions::new().visit_protocol_description(h, pd)?;
Ok(())
}
}
|