Compare commits

..

No commits in common. "f614d00575eb8f42fc9115b8759afda26c7542e8" and "c606432be2d482e806e8970fe8ec750e9de6b34a" have entirely different histories.

15 changed files with 511 additions and 1468 deletions

View File

@ -1,5 +1,17 @@
ns greeter; ns greeter
fn main(x: String) {
let x = 'Hello';
let y = 'World';
{
let test = 'test';
let x = 'x';
let y = 'y';
let z = 'z';
let test = 'oops.';
};
}
pub mod test {
fn main(args: Array<String>) {
println(args);
} }

View File

@ -1,7 +0,0 @@
ns std::core;
class Array<T> {}
class String {}
platform fn println(msg: Any) -> Void;

View File

@ -1 +1,3 @@
use std::core::println;
use std::core::*;
use std::core::{print, println}; use std::core::{print, println};

View File

@ -55,9 +55,7 @@ fn build_fqn(file_id: usize, fqn_pair: Pair<Rule>) -> FullyQualifiedName {
fn build_type_use(file_id: usize, type_use_pair: Pair<Rule>) -> TypeUse { fn build_type_use(file_id: usize, type_use_pair: Pair<Rule>) -> TypeUse {
let inner_pair = type_use_pair.into_inner().next().unwrap(); let inner_pair = type_use_pair.into_inner().next().unwrap();
match inner_pair.as_rule() { match inner_pair.as_rule() {
Rule::PrimitiveType => { Rule::Void => TypeUse::Void,
TypeUse::Primitive(build_primitive_type(file_id, inner_pair))
},
Rule::InterfaceOrClassTypeUse => { Rule::InterfaceOrClassTypeUse => {
TypeUse::InterfaceOrClass(build_interface_or_class_type_use(file_id, inner_pair)) TypeUse::InterfaceOrClass(build_interface_or_class_type_use(file_id, inner_pair))
} }
@ -67,35 +65,6 @@ fn build_type_use(file_id: usize, type_use_pair: Pair<Rule>) -> TypeUse {
} }
} }
fn build_primitive_type(
file_id: usize,
primitive_type_pair: Pair<Rule>,
) -> PrimitiveTypeUse {
let mut inner = primitive_type_pair.into_inner();
match inner.next().unwrap().as_rule() {
Rule::Byte => PrimitiveTypeUse::Byte,
Rule::Short => PrimitiveTypeUse::Short,
Rule::Char => PrimitiveTypeUse::Char,
Rule::Int => PrimitiveTypeUse::Int,
Rule::Long => PrimitiveTypeUse::Long,
Rule::Double => PrimitiveTypeUse::Double,
Rule::Bool => PrimitiveTypeUse::Bool,
Rule::String => PrimitiveTypeUse::String,
Rule::Array => {
if let Some(generic_arguments_pair) = inner.next() {
PrimitiveTypeUse::Array(
Some(Box::new(build_generic_arguments(file_id, generic_arguments_pair)))
)
} else {
PrimitiveTypeUse::Array(None)
}
}
Rule::Any => PrimitiveTypeUse::Any,
Rule::Void => PrimitiveTypeUse::Void,
_ => unreachable!(),
}
}
fn build_interface_or_class_type_use(file_id: usize, pair: Pair<Rule>) -> InterfaceOrClassTypeUse { fn build_interface_or_class_type_use(file_id: usize, pair: Pair<Rule>) -> InterfaceOrClassTypeUse {
let mut borrow_count = 0; let mut borrow_count = 0;
let mut is_mutable = false; let mut is_mutable = false;

View File

@ -10,8 +10,7 @@ pub mod build;
pub mod named; pub mod named;
pub mod pretty_print; pub mod pretty_print;
pub mod unparse; pub mod unparse;
// Operators
/* Operators */
#[derive(Debug)] #[derive(Debug)]
pub enum Operator { pub enum Operator {
@ -57,13 +56,13 @@ pub enum SuffixUnaryOperator {
/* Names */ /* Names */
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Identifier { pub struct Identifier {
name: String, pub name: String,
file_id: usize, pub file_id: usize,
range: Range<usize>, pub range: Range<usize>,
scope_id: Option<usize>, scope_id: Option<usize>,
saved_symbol: Option<Symbol>, symbol: Option<Symbol>,
} }
impl Identifier { impl Identifier {
@ -73,18 +72,38 @@ impl Identifier {
file_id, file_id,
range, range,
scope_id: None, scope_id: None,
saved_symbol: None, symbol: None,
} }
} }
pub fn set_scope_id(&mut self, id: usize) {
self.scope_id = Some(id);
}
pub fn scope_id(&self) -> Option<usize> {
self.scope_id
}
pub fn set_symbol(&mut self, symbol: Symbol) {
self.symbol = Some(symbol);
}
pub fn symbol(&self) -> &Option<Symbol> {
&self.symbol
}
pub fn symbol_mut(&mut self) -> Option<Symbol> {
self.symbol.clone()
}
} }
#[derive(Debug)] #[derive(Debug)]
pub struct FullyQualifiedName { pub struct FullyQualifiedName {
identifiers: Vec<Identifier>, pub identifiers: Vec<Identifier>,
file_id: usize, pub file_id: usize,
range: Range<usize>, pub range: Range<usize>,
scope_id: Option<usize>, scope_id: Option<usize>,
saved_symbol: Option<Symbol>, symbol: Option<Symbol>,
} }
impl FullyQualifiedName { impl FullyQualifiedName {
@ -94,25 +113,24 @@ impl FullyQualifiedName {
range, range,
file_id, file_id,
scope_id: None, scope_id: None,
saved_symbol: None, symbol: None,
} }
} }
pub fn last(&self) -> &Identifier { pub fn set_scope_id(&mut self, scope_id: usize) {
&self.identifiers[self.identifiers.len() - 1] self.scope_id = Some(scope_id);
} }
pub fn last_mut(&mut self) -> &mut Identifier { pub fn scope_id(&self) -> Option<usize> {
let last_index = self.identifiers.len() - 1; self.scope_id
&mut self.identifiers[last_index]
} }
pub fn len(&self) -> usize { pub fn set_symbol(&mut self, symbol: Symbol) {
self.identifiers.len() self.symbol = Some(symbol);
} }
pub fn is_single_identifier(&self) -> bool { pub fn symbol(&self) -> &Option<Symbol> {
self.identifiers.len() == 1 &self.symbol
} }
} }
@ -120,27 +138,12 @@ impl FullyQualifiedName {
#[derive(Debug)] #[derive(Debug)]
pub enum TypeUse { pub enum TypeUse {
Primitive(PrimitiveTypeUse), Void,
InterfaceOrClass(InterfaceOrClassTypeUse), InterfaceOrClass(InterfaceOrClassTypeUse),
Tuple(TupleTypeUse), Tuple(TupleTypeUse),
Function(FunctionTypeUse), Function(FunctionTypeUse),
} }
#[derive(Debug)]
pub enum PrimitiveTypeUse {
Byte,
Short,
Char,
Int,
Long,
Double,
Bool,
String,
Array(Option<Box<GenericArguments>>),
Any,
Void,
}
#[derive(Debug)] #[derive(Debug)]
pub struct InterfaceOrClassTypeUse { pub struct InterfaceOrClassTypeUse {
pub borrow_count: usize, pub borrow_count: usize,
@ -165,7 +168,7 @@ pub struct FunctionTypeUse {
pub return_type: ReturnType, pub return_type: ReturnType,
} }
/* Generic arguments */ // Generic arguments
#[derive(Debug)] #[derive(Debug)]
pub struct GenericArguments(pub Vec<TypeUse>); pub struct GenericArguments(pub Vec<TypeUse>);
@ -265,7 +268,7 @@ pub struct ReturnType {
impl ReturnType { impl ReturnType {
pub fn void() -> Self { pub fn void() -> Self {
ReturnType { ReturnType {
declared_type: Box::new(TypeUse::Primitive(PrimitiveTypeUse::Void)), declared_type: Box::new(TypeUse::Void),
references: References::default(), references: References::default(),
} }
} }
@ -299,68 +302,7 @@ pub struct CompilationUnit {
pub declarations: Vec<ModuleLevelDeclaration>, pub declarations: Vec<ModuleLevelDeclaration>,
} }
/* Use Statement */ // Declarations allowed in each level
#[derive(Debug)]
pub struct UseStatement {
pub identifiers: Vec<Identifier>,
pub last: UseStatementLast,
pub file_id: usize,
pub range: Range<usize>,
}
impl UseStatement {
pub fn new(
identifiers: Vec<Identifier>,
last: UseStatementLast,
file_id: usize,
range: Range<usize>,
) -> Self {
UseStatement {
identifiers,
last,
file_id,
range,
}
}
pub fn base_name(&self) -> Cow<'_, str> {
use UseStatementLast::*;
if self.identifiers.is_empty() {
match &self.last {
Identifier(_) => Cow::from(""),
Star | Identifiers(_) => panic!(), // should never get here because of grammar
}
} else if self.identifiers.len() == 1 {
self.identifiers[0].name()
} else {
let mut acc = String::new();
for (i, identifier) in self.identifiers.iter().enumerate() {
acc.push_str(&identifier.name());
if i != self.identifiers.len() - 1 {
acc.push_str("::");
}
}
Cow::from(acc)
}
}
pub fn is_star(&self) -> bool {
match &self.last {
UseStatementLast::Star => true,
_ => false,
}
}
}
#[derive(Debug)]
pub enum UseStatementLast {
Identifier(Rc<RefCell<Identifier>>),
Identifiers(Vec<Rc<RefCell<Identifier>>>),
Star,
}
/* Declarations allowed in each level */
#[derive(Debug)] #[derive(Debug)]
pub enum ModuleLevelDeclaration { pub enum ModuleLevelDeclaration {
@ -392,7 +334,7 @@ pub enum ClassLevelDeclaration {
Field(FieldDeclaration), Field(FieldDeclaration),
} }
/* Main Declarations */ // Declarations
#[derive(Debug)] #[derive(Debug)]
pub struct ModuleDeclaration { pub struct ModuleDeclaration {
@ -420,7 +362,7 @@ pub struct ClassDeclaration {
pub declarations: Vec<ClassLevelDeclaration>, pub declarations: Vec<ClassLevelDeclaration>,
} }
/* Function declarations and components */ // Function declarations and components
#[derive(Debug)] #[derive(Debug)]
pub struct FunctionDefinition { pub struct FunctionDefinition {
@ -490,7 +432,7 @@ pub enum FunctionBody {
Alias(Identifier), Alias(Identifier),
} }
/* Class components */ // Class components
#[derive(Debug)] #[derive(Debug)]
pub struct ClassConstructor(pub Vec<ClassConstructorParameter>); pub struct ClassConstructor(pub Vec<ClassConstructorParameter>);
@ -515,7 +457,92 @@ pub struct FieldDeclaration {
pub declared_type: TypeUse, pub declared_type: TypeUse,
} }
/* Statements */ // Statements
#[derive(Debug)]
pub struct UseStatement {
pub identifiers: Vec<Identifier>,
pub last: UseStatementLast,
pub file_id: usize,
pub range: Range<usize>,
scope_id: Option<usize>,
symbol: Option<Symbol>,
}
pub struct UseStatementImport<'a> {
pub declared_name: String,
pub fqn: String,
pub identifier: &'a mut Identifier,
}
impl UseStatement {
pub fn new(
identifiers: Vec<Identifier>,
last: UseStatementLast,
file_id: usize,
range: Range<usize>,
) -> Self {
UseStatement {
identifiers,
last,
file_id,
range,
scope_id: None,
symbol: None,
}
}
pub fn base_name(&self) -> Cow<'_, str> {
use UseStatementLast::*;
if self.identifiers.is_empty() {
match &self.last {
Identifier(_) => Cow::from(""),
Star | Identifiers(_) => panic!(), // should never get here because of grammar
}
} else if self.identifiers.len() == 1 {
self.identifiers[0].name()
} else {
let mut acc = String::new();
for (i, identifier) in self.identifiers.iter().enumerate() {
acc.push_str(&identifier.name());
if i != self.identifiers.len() - 1 {
acc.push_str("::");
}
}
Cow::from(acc)
}
}
pub fn is_star(&self) -> bool {
match &self.last {
UseStatementLast::Star => true,
_ => false,
}
}
pub fn set_scope_id(&mut self, scope_id: usize) {
self.scope_id = Some(scope_id);
}
pub fn scope_id(&self) -> Option<usize> {
self.scope_id
}
pub fn set_symbol(&mut self, symbol: Symbol) {
self.symbol = Some(symbol);
}
pub fn symbol(&self) -> &Option<Symbol> {
&self.symbol
}
}
#[derive(Debug)]
pub enum UseStatementLast {
Identifier(Rc<RefCell<Identifier>>),
Identifiers(Vec<Rc<RefCell<Identifier>>>),
Star,
}
#[derive(Debug)] #[derive(Debug)]
pub struct BlockStatement { pub struct BlockStatement {
@ -588,7 +615,7 @@ pub struct ForStatement {
pub body: BlockStatement, pub body: BlockStatement,
} }
/* Expressions */ // Expressions
#[derive(Debug)] #[derive(Debug)]
pub enum Expression { pub enum Expression {

View File

@ -1,49 +1,14 @@
use crate::ast::{FullyQualifiedName, Identifier}; use crate::ast::{FullyQualifiedName, Identifier};
use crate::name_analysis::symbol::Symbol;
use std::borrow::Cow; use std::borrow::Cow;
use std::range::Range;
pub trait Named { pub trait Named {
fn name(&self) -> Cow<'_, str>; fn name(&self) -> Cow<'_, str>;
fn file_id(&self) -> usize;
fn range(&self) -> Range<usize>;
fn set_scope_id(&mut self, scope_id: usize);
fn scope_id(&self) -> Option<usize>;
fn set_saved_symbol(&mut self, symbol: Symbol);
fn saved_symbol(&self) -> Option<Symbol>;
} }
impl Named for Identifier { impl Named for Identifier {
fn name(&self) -> Cow<'_, str> { fn name(&self) -> Cow<'_, str> {
Cow::Borrowed(&self.name) Cow::Borrowed(&self.name)
} }
fn file_id(&self) -> usize {
self.file_id
}
fn range(&self) -> Range<usize> {
self.range
}
fn set_scope_id(&mut self, id: usize) {
self.scope_id = Some(id);
}
fn scope_id(&self) -> Option<usize> {
self.scope_id
}
fn set_saved_symbol(&mut self, saved_symbol: Symbol) {
self.saved_symbol = Some(saved_symbol);
}
fn saved_symbol(&self) -> Option<Symbol> {
self.saved_symbol.clone()
}
} }
impl Named for FullyQualifiedName { impl Named for FullyQualifiedName {
@ -61,28 +26,4 @@ impl Named for FullyQualifiedName {
Cow::Owned(acc) Cow::Owned(acc)
} }
} }
fn file_id(&self) -> usize {
self.file_id
}
fn range(&self) -> Range<usize> {
self.range
}
fn set_scope_id(&mut self, id: usize) {
self.scope_id = Some(id);
}
fn scope_id(&self) -> Option<usize> {
self.scope_id
}
fn set_saved_symbol(&mut self, symbol: Symbol) {
self.saved_symbol = Some(symbol);
}
fn saved_symbol(&self) -> Option<Symbol> {
self.saved_symbol.clone()
}
} }

View File

@ -7,7 +7,6 @@ use deimos::name_analysis::symbol_table::SymbolTable;
use deimos::parser::{DeimosParser, Rule}; use deimos::parser::{DeimosParser, Rule};
use pest::Parser; use pest::Parser;
use std::path::PathBuf; use std::path::PathBuf;
use deimos::std_core::add_std_core_symbols;
pub fn name_analysis(paths: &Vec<PathBuf>) -> Result<(), Box<dyn std::error::Error>> { pub fn name_analysis(paths: &Vec<PathBuf>) -> Result<(), Box<dyn std::error::Error>> {
let mut compilation_units = vec![]; let mut compilation_units = vec![];
@ -30,7 +29,6 @@ pub fn name_analysis(paths: &Vec<PathBuf>) -> Result<(), Box<dyn std::error::Err
} }
let mut symbol_table = SymbolTable::new(); let mut symbol_table = SymbolTable::new();
add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols.");
let diagnostics = analyze_names(&mut compilation_units, &mut symbol_table); let diagnostics = analyze_names(&mut compilation_units, &mut symbol_table);
if diagnostics.is_empty() { if diagnostics.is_empty() {

View File

@ -6,6 +6,6 @@ pub mod module;
pub mod name_analysis; pub mod name_analysis;
pub mod object_file; pub mod object_file;
pub mod parser; pub mod parser;
pub mod std_core; mod std_core;
pub mod util; pub mod util;
pub mod vm; pub mod vm;

View File

@ -6,7 +6,6 @@ use crate::name_analysis::symbol::*;
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable};
use codespan_reporting::diagnostic::{Diagnostic, Label}; use codespan_reporting::diagnostic::{Diagnostic, Label};
use std::cell::RefCell; use std::cell::RefCell;
use std::ops::DerefMut;
use std::range::Range; use std::range::Range;
use std::rc::Rc; use std::rc::Rc;
@ -42,21 +41,13 @@ fn handle_insert_error(
} }
} }
/* Names */
fn gather_identifier(identifier: &mut Identifier, symbol_table: &mut SymbolTable) {
identifier.set_scope_id(symbol_table.current_scope_id());
}
fn gather_fully_qualified_name( fn gather_fully_qualified_name(
fully_qualified_name: &mut FullyQualifiedName, fully_qualified_name: &mut FullyQualifiedName,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
) { ) {
gather_identifier(fully_qualified_name.last_mut(), symbol_table); fully_qualified_name.set_scope_id(symbol_table.current_scope_id());
} }
/* Type Use */
fn gather_type_use( fn gather_type_use(
type_use: &mut TypeUse, type_use: &mut TypeUse,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -64,9 +55,7 @@ fn gather_type_use(
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
match type_use { match type_use {
TypeUse::Primitive(primitive_type_use) => { TypeUse::Void => {}
gather_primitive_type_use(primitive_type_use, symbol_table, fqn_context, diagnostics)
}
TypeUse::InterfaceOrClass(interface_or_class_type_use) => { TypeUse::InterfaceOrClass(interface_or_class_type_use) => {
gather_interface_or_class_type_use( gather_interface_or_class_type_use(
interface_or_class_type_use, interface_or_class_type_use,
@ -84,22 +73,6 @@ fn gather_type_use(
} }
} }
fn gather_primitive_type_use(
primitive_type_use: &mut PrimitiveTypeUse,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match primitive_type_use {
PrimitiveTypeUse::Array(generic_arguments_opt) => {
if let Some(generic_arguments) = generic_arguments_opt {
gather_generic_arguments(generic_arguments, symbol_table, fqn_context, diagnostics);
}
}
_ => {}
}
}
fn gather_interface_or_class_type_use( fn gather_interface_or_class_type_use(
interface_or_class_type_use: &mut InterfaceOrClassTypeUse, interface_or_class_type_use: &mut InterfaceOrClassTypeUse,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -132,28 +105,9 @@ fn gather_function_type_use(
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
gather_generic_parameters( todo!()
&mut function_type_use.generics,
symbol_table,
fqn_context,
diagnostics,
);
gather_parameters(
&mut function_type_use.parameters,
symbol_table,
fqn_context,
diagnostics,
);
gather_return_type(
&mut function_type_use.return_type,
symbol_table,
fqn_context,
diagnostics,
);
} }
/* Generic Arguments */
fn gather_generic_arguments( fn gather_generic_arguments(
generic_arguments: &mut GenericArguments, generic_arguments: &mut GenericArguments,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -165,123 +119,6 @@ fn gather_generic_arguments(
} }
} }
/* Generic Parameters */
fn gather_generic_parameters(
generic_parameters: &mut GenericParameters,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!("Add each Identifier as a type to the current scope; make sure caller's push/pop before/after")
}
/* Implements List */
fn gather_implements_list(
implements_list: &mut ImplementsList,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
for type_use in &mut implements_list.0 {
gather_type_use(type_use, symbol_table, fqn_context, diagnostics);
}
}
/* Function Parameters */
fn gather_parameters(
parameters: &mut Parameters,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) -> Option<Vec<Rc<ParameterSymbol>>> {
parameters
.0
.iter_mut()
.map(|parameter| gather_parameter(parameter, symbol_table, fqn_context, diagnostics))
.collect()
}
fn gather_parameter(
parameter: &mut Parameter,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) -> Option<Rc<ParameterSymbol>> {
let parameter_name = parameter.identifier.name();
let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new(
&parameter_name,
Some(&parameter.identifier),
));
match insert_result {
Ok(parameter_symbol) => {
parameter
.identifier
.set_scope_id(symbol_table.current_scope_id());
gather_type_use(
&mut parameter.type_use,
symbol_table,
fqn_context,
diagnostics,
);
Some(parameter_symbol)
}
Err(err) => {
handle_insert_error(
err,
&parameter_name,
parameter.identifier.file_id(),
parameter.identifier.range(),
"function/variable",
diagnostics,
);
None
}
}
}
/* Return Type */
fn gather_return_type(
return_type: &mut ReturnType,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
gather_type_use(
&mut return_type.declared_type,
symbol_table,
fqn_context,
diagnostics,
);
gather_references(
&mut return_type.references,
symbol_table,
fqn_context,
diagnostics,
);
}
/* References */
fn gather_references(
references: &mut References,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
for identifier in &mut references.0 {
gather_identifier(identifier, symbol_table);
}
}
/* Compilation Unit/Top-level construct */
pub(super) fn gather_compilation_unit( pub(super) fn gather_compilation_unit(
compilation_unit: &mut CompilationUnit, compilation_unit: &mut CompilationUnit,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -303,8 +140,6 @@ pub(super) fn gather_compilation_unit(
assert_eq!(symbol_table.current_scope_id(), 0); assert_eq!(symbol_table.current_scope_id(), 0);
} }
/* Use Statement */
fn handle_use_statement_import( fn handle_use_statement_import(
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
base_name: &str, base_name: &str,
@ -318,29 +153,28 @@ fn handle_use_statement_import(
&declared_name, &declared_name,
Some(identifier.clone()), Some(identifier.clone()),
)); ));
if let Err(err) = insert_result {
match insert_result { handle_insert_error(
Ok(use_statement_symbol) => { err,
drop(borrowed_identifier); &declared_name,
borrowed_identifier.file_id,
let mut mutable_borrowed_identifier = identifier.borrow_mut(); borrowed_identifier.range,
"Use statement",
gather_identifier(mutable_borrowed_identifier.deref_mut(), symbol_table); diagnostics,
);
mutable_borrowed_identifier
.set_saved_symbol(Symbol::UseStatement(use_statement_symbol));
}
Err(err) => {
handle_insert_error(
err,
&declared_name,
borrowed_identifier.file_id(),
borrowed_identifier.range(),
"Use statement",
diagnostics,
);
}
} }
drop(borrowed_identifier);
let mut mutable_borrowed_identifier = identifier.borrow_mut();
mutable_borrowed_identifier.set_scope_id(symbol_table.current_scope_id());
let use_statement_symbol = symbol_table
.lookup(
&declared_name,
mutable_borrowed_identifier.scope_id().unwrap(),
)
.unwrap();
mutable_borrowed_identifier.set_symbol(use_statement_symbol);
} }
fn gather_use_statement( fn gather_use_statement(
@ -371,8 +205,6 @@ fn gather_use_statement(
} }
} }
/* Declarations allowed in each level */
fn gather_module_level_declaration( fn gather_module_level_declaration(
declaration: &mut ModuleLevelDeclaration, declaration: &mut ModuleLevelDeclaration,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -402,26 +234,6 @@ fn gather_module_level_declaration(
} }
} }
fn gather_interface_level_declaration(
declaration: &mut InterfaceLevelDeclaration,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn gather_class_level_declaration(
declaration: &mut ClassLevelDeclaration,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
/* Main Declarations */
fn gather_module_declaration( fn gather_module_declaration(
declaration: &mut ModuleDeclaration, declaration: &mut ModuleDeclaration,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -447,8 +259,8 @@ fn gather_module_declaration(
handle_insert_error( handle_insert_error(
err, err,
&module_name, &module_name,
declaration.identifier.file_id(), declaration.identifier.file_id,
declaration.identifier.range(), declaration.identifier.range,
"module/type", "module/type",
diagnostics, diagnostics,
) )
@ -482,8 +294,8 @@ fn gather_class_declaration(
handle_insert_error( handle_insert_error(
err, err,
&declared_name, &declared_name,
class_declaration.identifier.file_id(), class_declaration.identifier.file_id,
class_declaration.identifier.range(), class_declaration.identifier.range,
"interface/class", "interface/class",
diagnostics, diagnostics,
); );
@ -492,8 +304,6 @@ fn gather_class_declaration(
// todo: scopes, generics, etc. // todo: scopes, generics, etc.
} }
/* Function declarations and components */
fn gather_function_definition( fn gather_function_definition(
function: &mut FunctionDefinition, function: &mut FunctionDefinition,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -511,64 +321,30 @@ fn gather_function_definition(
Some(&function.identifier), Some(&function.identifier),
)); ));
match insert_result { if let Err(err) = insert_result {
Ok(function_symbol) => { handle_insert_error(
function err,
.identifier &declared_name,
.set_scope_id(symbol_table.current_scope_id()); function.identifier.file_id,
function.identifier.range,
symbol_table.push_scope(&format!("FunctionParameterScope({})", resolved_name)); "function/variable",
diagnostics,
let parameters_result = gather_parameters( )
&mut function.parameters,
symbol_table,
fqn_context,
diagnostics,
);
match parameters_result {
Some(parameter_symbols) => {
function_symbol
.borrow_mut()
.set_parameters(parameter_symbols);
}
None => {}
}
gather_return_type(
&mut function.return_type,
symbol_table,
fqn_context,
diagnostics,
);
symbol_table.push_scope(&format!("FunctionBodyScope({})", resolved_name));
gather_function_body(&mut function.body, symbol_table, fqn_context, diagnostics);
symbol_table.pop_scope(); // body
symbol_table.pop_scope(); // parameters
}
Err(err) => {
handle_insert_error(
err,
&declared_name,
function.identifier.file_id(),
function.identifier.range(),
"function/variable",
diagnostics,
);
}
} }
}
fn gather_operator_function_definition( function
operator_function_definition: &mut OperatorFunctionDefinition, .identifier
symbol_table: &mut SymbolTable, .set_scope_id(symbol_table.current_scope_id());
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, symbol_table.push_scope(&format!("FunctionScope({})", resolved_name));
) { gather_parameters(
todo!() &mut function.parameters,
symbol_table,
fqn_context,
diagnostics,
);
gather_function_body(&mut function.body, symbol_table, fqn_context, diagnostics);
symbol_table.pop_scope();
} }
fn gather_platform_function_definition( fn gather_platform_function_definition(
@ -588,74 +364,78 @@ fn gather_platform_function_definition(
Some(&platform_function_declaration.identifier), Some(&platform_function_declaration.identifier),
)); ));
match insert_result { if let Err(err) = insert_result {
Ok(function_symbol) => { handle_insert_error(
let declared_name_as_string = err,
platform_function_declaration.identifier.name().to_string(); &declared_name,
platform_function_declaration.identifier.file_id,
platform_function_declaration.identifier.range,
"(Platform-) Function",
diagnostics,
);
}
platform_function_declaration let declared_name_as_string = platform_function_declaration.identifier.name().to_string();
.identifier
.set_scope_id(symbol_table.current_scope_id());
symbol_table.push_scope(&format!( platform_function_declaration
"FunctionParameterScope({})", .identifier
declared_name_as_string .set_scope_id(symbol_table.current_scope_id());
));
let parameter_symbols_result = gather_parameters( symbol_table.push_scope(&format!("FunctionScope({})", declared_name_as_string));
&mut platform_function_declaration.parameters, gather_parameters(
symbol_table, &mut platform_function_declaration.parameters,
fqn_context, symbol_table,
diagnostics, fqn_context,
); diagnostics,
);
symbol_table.pop_scope();
}
match parameter_symbols_result { fn gather_parameters(
Some(parameter_symbols) => { parameters: &mut Parameters,
function_symbol symbol_table: &mut SymbolTable,
.borrow_mut() fqn_context: &mut FqnContext,
.set_parameters(parameter_symbols); diagnostics: &mut Vec<DmDiagnostic>,
} ) {
None => {} for parameter in &mut parameters.0 {
} gather_parameter(parameter, symbol_table, fqn_context, diagnostics);
gather_return_type(
&mut platform_function_declaration.return_type,
symbol_table,
fqn_context,
diagnostics,
);
symbol_table.pop_scope();
}
Err(err) => {
handle_insert_error(
err,
&declared_name,
platform_function_declaration.identifier.file_id(),
platform_function_declaration.identifier.range(),
"(Platform-) Function",
diagnostics,
);
}
} }
} }
fn gather_interface_function_declaration( fn gather_parameter(
declaration: &mut InterfaceFunctionDeclaration, parameter: &mut Parameter,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
todo!() let parameter_name = parameter.identifier.name();
}
fn gather_interface_operator_function_declaration( let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new(
declaration: &mut InterfaceOperatorFunctionDeclaration, &parameter_name,
symbol_table: &mut SymbolTable, Some(&parameter.identifier),
fqn_context: &mut FqnContext, ));
diagnostics: &mut Vec<DmDiagnostic>,
) { if let Err(err) = insert_result {
todo!() handle_insert_error(
err,
&parameter_name,
parameter.identifier.file_id,
parameter.identifier.range,
"function/variable",
diagnostics,
)
}
parameter
.identifier
.set_scope_id(symbol_table.current_scope_id());
gather_type_use(
&mut parameter.type_use,
symbol_table,
fqn_context,
diagnostics,
)
} }
fn gather_function_body( fn gather_function_body(
@ -671,37 +451,6 @@ fn gather_function_body(
} }
} }
/* Class Components */
fn gather_class_constructor(
class_constructor: &mut ClassConstructor,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn gather_property_declaration(
property_declaration: &mut PropertyDeclaration,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn gather_field_declaration(
field_declaration: &mut FieldDeclaration,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
/* Statements */
fn gather_block_statement( fn gather_block_statement(
block: &mut BlockStatement, block: &mut BlockStatement,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -768,8 +517,8 @@ fn gather_variable_declaration(
handle_insert_error( handle_insert_error(
err, err,
&variable_name, &variable_name,
variable_declaration.identifier.file_id(), variable_declaration.identifier.file_id,
variable_declaration.identifier.range(), variable_declaration.identifier.range,
"function/variable", "function/variable",
diagnostics, diagnostics,
) )
@ -802,55 +551,6 @@ fn gather_call_statement(
gather_expression(&mut call_statement.0, symbol_table, diagnostics); gather_expression(&mut call_statement.0, symbol_table, diagnostics);
} }
fn gather_return_statement(
return_statement: &mut ReturnStatement,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
if let Some(expression) = &mut return_statement.0 {
gather_expression(expression, symbol_table, diagnostics);
}
}
fn gather_if_statement(
if_statement: &mut IfStatement,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn gather_if_else_statement(
if_else_statement: &mut IfElseStatement,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn gather_while_statement(
while_statement: &mut WhileStatement,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn gather_for_statement(
for_statement: &mut ForStatement,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
/* Expressions */
fn gather_expression( fn gather_expression(
expression: &mut Expression, expression: &mut Expression,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -973,8 +673,7 @@ fn gather_object_access(
gather_expression(index_expression, symbol_table, diagnostics); gather_expression(index_expression, symbol_table, diagnostics);
} }
ObjectNavigation::Identifier(identifier) => { ObjectNavigation::Identifier(identifier) => {
// TODO: use a special gather for names belonging to a struct identifier.set_scope_id(symbol_table.current_scope_id());
gather_identifier(identifier, symbol_table);
} }
} }
} }
@ -986,18 +685,8 @@ fn gather_literal(
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
match literal { match literal {
Literal::DString(d_string) => gather_d_string(d_string, symbol_table, diagnostics), Literal::DString(d_string) => todo!(),
Literal::BacktickString(backtick_string) => { Literal::BacktickString(backtick_string) => todo!(),
gather_d_string(backtick_string, symbol_table, diagnostics)
}
_ => {} _ => {}
} }
} }
fn gather_d_string(
d_string: &mut DString,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}

View File

@ -1,24 +1,3 @@
/*!
# Name Analysis
There are two phases in name analysis.
## 1. Gather
The gather phases has three responsibilities:
1. Add all declared symbols to the symbol table.
2. Set the `scope_id` property of all identifiers and fully-qualified-names.
3. For the main identifiers of `UseStatement`s (i.e., the last identifier in the `UseStatement`):
set a 'linking' symbol on the identifier, which will later be filled in with the linked-to
symbol (probably in another file, or from the standard library).
## 2. Resolve
The resolve phase has one main responsibility: resolve all references based on the identifier's
`scope_id` property.
*/
use crate::ast::named::Named; use crate::ast::named::Named;
use crate::ast::CompilationUnit; use crate::ast::CompilationUnit;
use crate::diagnostic::DmDiagnostic; use crate::diagnostic::DmDiagnostic;
@ -64,11 +43,7 @@ mod tests {
use pest::Parser; use pest::Parser;
use std::collections::HashMap; use std::collections::HashMap;
fn assert_number_of_diagnostics( fn assert_no_diagnostics(sources: HashMap<&str, &str>) -> SymbolTable {
sources: HashMap<&str, &str>,
symbol_table: &mut SymbolTable,
n_diagnostics: usize,
) {
let mut files = SimpleFiles::new(); let mut files = SimpleFiles::new();
let mut compilation_units = vec![]; let mut compilation_units = vec![];
@ -86,7 +61,10 @@ mod tests {
compilation_units.push(build_ast(file_name, file_id, pairs.next().unwrap())) compilation_units.push(build_ast(file_name, file_id, pairs.next().unwrap()))
} }
let diagnostics = analyze_names(&mut compilation_units, symbol_table); let mut symbol_table = SymbolTable::new();
add_std_core_symbols(&mut symbol_table).expect("Failed to add std_core_symbols");
let diagnostics = analyze_names(&mut compilation_units, &mut symbol_table);
if !diagnostics.is_empty() { if !diagnostics.is_empty() {
let writer = StandardStream::stderr(ColorChoice::Always); let writer = StandardStream::stderr(ColorChoice::Always);
@ -97,17 +75,14 @@ mod tests {
} }
eprintln!("{}", symbol_table); eprintln!("{}", symbol_table);
panic!("Diagnostics was not empty!");
} }
assert_eq!(n_diagnostics, diagnostics.len());
for compilation_unit in &compilation_units { for compilation_unit in &compilation_units {
dbg!(compilation_unit); dbg!(compilation_unit);
} }
}
fn assert_no_diagnostics(sources: HashMap<&str, &str>, symbol_table: &mut SymbolTable) { symbol_table
assert_number_of_diagnostics(sources, symbol_table, 0);
} }
#[test] #[test]
@ -120,7 +95,7 @@ mod tests {
}"}, }"},
)]); )]);
assert_no_diagnostics(sources, &mut SymbolTable::new()); assert_no_diagnostics(sources);
} }
#[test] #[test]
@ -130,6 +105,10 @@ mod tests {
"main.dm", "main.dm",
indoc! {" indoc! {"
use test::Greeter; use test::Greeter;
fn main(args: Array<String>) {
println(\"Hello, World!\");
}
"}, "},
), ),
( (
@ -142,81 +121,6 @@ mod tests {
), ),
]); ]);
assert_no_diagnostics(sources, &mut SymbolTable::new()); assert_no_diagnostics(sources);
}
#[test]
fn sees_std_core_println() {
let sources: HashMap<&str, &str> = HashMap::from([(
"main.dm",
indoc! {"
fn main(args: Array<String>) {
println(args)
}
"},
)]);
let mut symbol_table = SymbolTable::new();
add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols.");
assert_no_diagnostics(sources, &mut symbol_table);
}
#[test]
fn sees_duplicate_fn() {
let sources: HashMap<&str, &str> = HashMap::from([(
"main.dm",
indoc! {"
fn main(args: Array<String>) {}
fn main(args: Array<String>) {}
"},
)]);
assert_number_of_diagnostics(sources, &mut SymbolTable::new(), 1);
}
#[test]
fn use_class_from_other_file() {
let sources: HashMap<&str, &str> = HashMap::from([
(
"main.dm",
indoc! {"
use greeter::Greeter;
fn test(greeter: Greeter) {}
"},
),
(
"greeter.dm",
indoc! {"
ns greeter;
class Greeter {}
"},
),
]);
let mut symbol_table = SymbolTable::new();
assert_no_diagnostics(sources, &mut symbol_table);
}
#[test]
fn shadow_import() {
let sources: HashMap<&str, &str> = HashMap::from([
(
"main.dm",
indoc! {"
use greeter::Greeter;
class Greeter {}
"}
),
(
"greeter.dm",
indoc! {"
ns greeter;
class Greeter {}
"}
)
]);
assert_number_of_diagnostics(sources, &mut SymbolTable::new(), 1);
} }
} }

View File

@ -1,14 +1,38 @@
use crate::ast::named::Named; use crate::ast::named::Named;
use crate::ast::*; use crate::ast::*;
use crate::diagnostic::DmDiagnostic; use crate::diagnostic::DmDiagnostic;
use crate::name_analysis::symbol::Symbol; use crate::name_analysis::symbol_table::SymbolTable;
use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable};
use codespan_reporting::diagnostic::{Diagnostic, Label}; use codespan_reporting::diagnostic::{Diagnostic, Label};
use std::cell::RefCell;
use std::range::Range;
use std::rc::Rc;
/* Type Use */ fn resolve_fully_qualified_name(
fully_qualified_name: &mut FullyQualifiedName,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let lookup_result = symbol_table.lookup(
fully_qualified_name.name().as_ref(),
fully_qualified_name.scope_id().expect(&format!(
"FullyQualifiedName has no scope_id set: {:?}",
fully_qualified_name
)),
);
match lookup_result {
Ok(symbol) => {
fully_qualified_name.set_symbol(symbol.clone());
}
Err(e) => diagnostics.push(
Diagnostic::error()
.with_message(format!(
"No symbol with name '{}' found in current scope.",
fully_qualified_name.name()
))
.with_label(Label::primary(
fully_qualified_name.file_id,
fully_qualified_name.range,
)),
),
}
}
fn resolve_type_use( fn resolve_type_use(
type_use: &mut TypeUse, type_use: &mut TypeUse,
@ -16,9 +40,7 @@ fn resolve_type_use(
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
match type_use { match type_use {
TypeUse::Primitive(primitive_type_use) => { TypeUse::Void => {}
resolve_primitive_type_use(primitive_type_use, symbol_table, diagnostics)
}
TypeUse::InterfaceOrClass(interface_or_class_type_use) => { TypeUse::InterfaceOrClass(interface_or_class_type_use) => {
resolve_interface_or_class_type_use( resolve_interface_or_class_type_use(
interface_or_class_type_use, interface_or_class_type_use,
@ -35,56 +57,16 @@ fn resolve_type_use(
} }
} }
fn resolve_primitive_type_use(
primitive_type_use: &mut PrimitiveTypeUse,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match primitive_type_use {
PrimitiveTypeUse::Array(generic_arguments_opt) => {
if let Some(generic_arguments) = generic_arguments_opt {
resolve_generic_arguments(generic_arguments, symbol_table, diagnostics);
}
}
_ => {}
}
}
fn resolve_interface_or_class_type_use( fn resolve_interface_or_class_type_use(
interface_or_class_type_use: &mut InterfaceOrClassTypeUse, interface_or_class_type_use: &mut InterfaceOrClassTypeUse,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
// 1. handle main name resolve_fully_qualified_name(
let fqn = &mut interface_or_class_type_use.fqn; &mut interface_or_class_type_use.fqn,
let lookup_result = if fqn.is_single_identifier() { symbol_table,
let identifier = fqn.last(); diagnostics,
symbol_table.lookup_type_by_declared_name( );
&identifier.name(),
identifier
.scope_id()
.expect("Identifier's scope id not set."),
)
} else {
todo!("Fully-qualified-name type uses sensitive to imports and so on")
};
match lookup_result {
Ok(type_symbol) => {
fqn.last_mut().set_saved_symbol(Symbol::Type(type_symbol));
}
Err(_) => {
diagnostics.push(
Diagnostic::error()
.with_message(&format!(
"No type symbol '{}' found in current scope.",
fqn.name()
))
.with_label(Label::primary(fqn.file_id(), fqn.range())),
);
}
}
// 2. generics
resolve_generic_arguments( resolve_generic_arguments(
&mut interface_or_class_type_use.generics, &mut interface_or_class_type_use.generics,
symbol_table, symbol_table,
@ -113,8 +95,6 @@ fn resolve_function_type_use(
); );
} }
/* Generic arguments */
fn resolve_generic_arguments( fn resolve_generic_arguments(
generic_arguments: &mut GenericArguments, generic_arguments: &mut GenericArguments,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -125,10 +105,6 @@ fn resolve_generic_arguments(
} }
} }
/* Generic parameters: todo: no resolution needed? */
/* Tuple arguments */
fn resolve_tuple_arguments( fn resolve_tuple_arguments(
tuple_type_use: &mut TupleArguments, tuple_type_use: &mut TupleArguments,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -139,8 +115,6 @@ fn resolve_tuple_arguments(
} }
} }
/* Implements list */
fn resolve_implements_list( fn resolve_implements_list(
implements_list: &mut ImplementsList, implements_list: &mut ImplementsList,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -149,8 +123,6 @@ fn resolve_implements_list(
todo!() todo!()
} }
/* Function parameters */
fn resolve_parameters( fn resolve_parameters(
parameters: &mut Parameters, parameters: &mut Parameters,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -161,8 +133,6 @@ fn resolve_parameters(
} }
} }
/* Return Type */
fn resolve_return_type( fn resolve_return_type(
return_type: &mut ReturnType, return_type: &mut ReturnType,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -172,8 +142,6 @@ fn resolve_return_type(
resolve_references(&mut return_type.references, symbol_table, diagnostics); resolve_references(&mut return_type.references, symbol_table, diagnostics);
} }
/* References */
fn resolve_references( fn resolve_references(
references: &mut References, references: &mut References,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -184,7 +152,46 @@ fn resolve_references(
} }
} }
/* Compilation Unit/Top-level construct */ fn resolve_use_statement(
use_statement: &mut UseStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
if use_statement.is_star() {
todo!()
}
let base_name = use_statement.base_name().to_string();
match &use_statement.last {
UseStatementLast::Identifier(identifier) => {
let borrowed_identifier = identifier.borrow();
let declared_name = borrowed_identifier.name().to_string();
let fqn = format!("{}::{}", &base_name, &declared_name);
let lookup_result =
symbol_table.lookup_usable_by_fqn(&fqn, borrowed_identifier.scope_id().unwrap());
drop(borrowed_identifier);
if let Err(_) = lookup_result {
diagnostics.push(
Diagnostic::error()
.with_message(&format!("Unable to find symbol '{}'.", fqn))
.with_label(Label::primary(use_statement.file_id, use_statement.range)),
);
} else {
let mut mutable_borrowed_identifier = identifier.borrow_mut();
let use_statement_symbol = mutable_borrowed_identifier
.symbol_mut()
.unwrap()
.unwrap_use_statement_symbol();
let mut mutable_borrowed_use_statement_symbol = use_statement_symbol.borrow_mut();
mutable_borrowed_use_statement_symbol.set_referenced_symbol(lookup_result.unwrap())
}
}
UseStatementLast::Identifiers(identifiers) => {}
UseStatementLast::Star => panic!(),
}
}
pub(super) fn resolve_compilation_unit( pub(super) fn resolve_compilation_unit(
compilation_unit: &mut CompilationUnit, compilation_unit: &mut CompilationUnit,
@ -199,79 +206,7 @@ pub(super) fn resolve_compilation_unit(
} }
} }
/* Use Statement */ pub(super) fn resolve_module_level_declaration(
fn handle_use_statement_identifier(
identifier: Rc<RefCell<Identifier>>,
base_name: &str,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
file_id: usize,
error_range: Range<usize>,
) {
let borrowed_identifier = identifier.borrow();
let declared_name = borrowed_identifier.name().to_string();
let fqn = format!("{}::{}", base_name, &declared_name);
let lookup_result =
symbol_table.lookup_usable_by_fqn(&fqn, borrowed_identifier.scope_id().unwrap());
match lookup_result {
Ok(referenced_symbol) => {
let saved_symbol = borrowed_identifier
.saved_symbol()
.expect("Identifier's saved_symbol is not set.");
let use_statement_symbol = saved_symbol.unwrap_use_statement_symbol();
use_statement_symbol
.borrow_mut()
.set_referenced_symbol(referenced_symbol);
}
Err(_) => {
diagnostics.push(
Diagnostic::error()
.with_message(&format!("Unable to find symbol '{}'.", fqn))
.with_label(Label::primary(file_id, error_range)),
);
}
}
}
fn resolve_use_statement(
use_statement: &mut UseStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let base_name = use_statement.base_name().to_string();
match &use_statement.last {
UseStatementLast::Identifier(identifier) => {
handle_use_statement_identifier(
identifier.clone(),
&base_name,
symbol_table,
diagnostics,
use_statement.file_id,
use_statement.range,
);
}
UseStatementLast::Identifiers(identifiers) => {
for identifier in identifiers {
handle_use_statement_identifier(
identifier.clone(),
&base_name,
symbol_table,
diagnostics,
use_statement.file_id,
identifier.borrow().range(),
)
}
}
UseStatementLast::Star => todo!("star imports"),
}
}
/* Declarations allowed in each level */
fn resolve_module_level_declaration(
declaration: &mut ModuleLevelDeclaration, declaration: &mut ModuleLevelDeclaration,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -293,65 +228,6 @@ fn resolve_module_level_declaration(
} }
} }
fn resolve_interface_level_declaration(
declaration: &mut InterfaceLevelDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_class_level_declaration(
declaration: &mut ClassLevelDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
/* Main Declarations */
fn resolve_module_declaration(
module_declaration: &mut ModuleDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
for declaration in &mut module_declaration.declarations {
resolve_module_level_declaration(declaration, symbol_table, diagnostics);
}
}
fn resolve_interface_declaration(
interface_declaration: &mut InterfaceDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
resolve_implements_list(
&mut interface_declaration.implements,
symbol_table,
diagnostics,
);
for declaration in &mut interface_declaration.declarations {
resolve_interface_level_declaration(declaration, symbol_table, diagnostics);
}
}
fn resolve_class_declaration(
class_declaration: &mut ClassDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
if let Some(class_constructor) = &mut class_declaration.class_constructor {
resolve_class_constructor(class_constructor, symbol_table, diagnostics);
}
resolve_implements_list(&mut class_declaration.implements, symbol_table, diagnostics);
for declaration in &mut class_declaration.declarations {
resolve_class_level_declaration(declaration, symbol_table, diagnostics);
}
}
/* Function declarations and components */
fn resolve_function_definition( fn resolve_function_definition(
function_definition: &mut FunctionDefinition, function_definition: &mut FunctionDefinition,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -370,14 +246,6 @@ fn resolve_function_definition(
resolve_function_body(&mut function_definition.body, symbol_table, diagnostics); resolve_function_body(&mut function_definition.body, symbol_table, diagnostics);
} }
fn resolve_operator_function_definition(
operator_function_definition: &mut OperatorFunctionDefinition,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_platform_function_declaration( fn resolve_platform_function_declaration(
platform_function_declaration: &mut PlatformFunctionDeclaration, platform_function_declaration: &mut PlatformFunctionDeclaration,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -395,22 +263,6 @@ fn resolve_platform_function_declaration(
); );
} }
fn resolve_interface_function_declaration(
interface_function_declaration: &mut InterfaceFunctionDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_interface_operator_function_declaration(
interface_operator_function_declaration: &mut InterfaceOperatorFunctionDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_function_body( fn resolve_function_body(
function_body: &mut FunctionBody, function_body: &mut FunctionBody,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -418,49 +270,12 @@ fn resolve_function_body(
) { ) {
use crate::ast::FunctionBody::*; use crate::ast::FunctionBody::*;
match function_body { match function_body {
Equals(expression) => resolve_expression(expression, symbol_table, diagnostics), Block(block) => resolve_block(block, symbol_table, diagnostics),
Block(block) => resolve_block_statement(block, symbol_table, diagnostics), _ => todo!(),
Alias(identifier) => resolve_function_alias(identifier, symbol_table, diagnostics),
} }
} }
fn resolve_function_alias( fn resolve_block(
identifier: &mut Identifier,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
/* Class components */
fn resolve_class_constructor(
class_constructor: &mut ClassConstructor,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_property_declaration(
property_declaration: &mut PropertyDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_field_declaration(
field_declaration: &mut FieldDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
/* Statements */
fn resolve_block_statement(
block_statement: &mut BlockStatement, block_statement: &mut BlockStatement,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -480,7 +295,7 @@ fn resolve_statement(
) { ) {
use crate::ast::Statement::*; use crate::ast::Statement::*;
match statement { match statement {
BlockStatement(block) => resolve_block_statement(block, symbol_table, diagnostics), BlockStatement(block) => resolve_block(block, symbol_table, diagnostics),
VariableDeclarationStatement(variable_declaration) => { VariableDeclarationStatement(variable_declaration) => {
resolve_variable_declaration(variable_declaration, symbol_table, diagnostics) resolve_variable_declaration(variable_declaration, symbol_table, diagnostics)
} }
@ -521,42 +336,6 @@ fn resolve_call_statement(
resolve_expression(&mut call_statement.0, symbol_table, diagnostics) resolve_expression(&mut call_statement.0, symbol_table, diagnostics)
} }
fn resolve_return_statement(
return_statement: &mut ReturnStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
if let Some(expression) = &mut return_statement.0 {
resolve_expression(expression, symbol_table, diagnostics);
}
}
fn resolve_if_statement(
if_statement: &mut IfStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_while_statement(
while_statement: &mut WhileStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_for_statement(
for_statement: &mut ForStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
/* Expressions */
fn resolve_expression( fn resolve_expression(
expression: &mut Expression, expression: &mut Expression,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -582,13 +361,7 @@ fn resolve_expression(
ObjectAccess(object_access) => { ObjectAccess(object_access) => {
resolve_object_access(object_access, symbol_table, diagnostics); resolve_object_access(object_access, symbol_table, diagnostics);
} }
FullyQualifiedName(fqn) => { FullyQualifiedName(fqn) => resolve_fully_qualified_name(fqn, symbol_table, diagnostics),
if fqn.is_single_identifier() {
resolve_identifier_expression(fqn.last_mut(), symbol_table, diagnostics);
} else {
resolve_fqn_expression(fqn, symbol_table, diagnostics);
}
}
Literal(literal) => { Literal(literal) => {
resolve_literal(literal, symbol_table, diagnostics); resolve_literal(literal, symbol_table, diagnostics);
} }
@ -598,48 +371,6 @@ fn resolve_expression(
} }
} }
fn handle_named_lookup_result(
lookup_result: Result<Symbol, SymbolLookupError>,
named: &mut impl Named,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match lookup_result {
Ok(referenced_symbol) => {
named.set_saved_symbol(referenced_symbol);
}
Err(_) => {
diagnostics.push(
DmDiagnostic::error()
.with_message(&format!(
"Unable to find expressible symbol {} in current scope.",
named.name()
))
.with_label(Label::primary(named.file_id(), named.range())),
);
}
}
}
fn resolve_identifier_expression(
identifier: &mut Identifier,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let lookup_result = symbol_table
.lookup_expressible_by_declared_name(&identifier.name(), identifier.scope_id().unwrap());
handle_named_lookup_result(lookup_result, identifier, diagnostics);
}
fn resolve_fqn_expression(
fqn: &mut FullyQualifiedName,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let lookup_result =
symbol_table.lookup_expressible_by_fqn(&fqn.name(), fqn.last().scope_id().unwrap());
handle_named_lookup_result(lookup_result, fqn, diagnostics);
}
fn resolve_ternary_expression( fn resolve_ternary_expression(
ternary_expression: &mut TernaryExpression, ternary_expression: &mut TernaryExpression,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -700,7 +431,7 @@ fn resolve_turbo_fish(
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
resolve_generic_arguments(&mut turbo_fish.0, symbol_table, diagnostics); todo!()
} }
fn resolve_call_arguments( fn resolve_call_arguments(

View File

@ -1,9 +1,8 @@
use crate::ast::{Identifier, UseStatement};
use std::cell::RefCell; use std::cell::RefCell;
use std::fmt::{Debug, Display, Formatter}; use crate::ast::{Identifier, UseStatement};
use std::fmt::Display;
use std::range::Range; use std::range::Range;
use std::rc::Rc; use std::rc::Rc;
use crate::ast::named::Named;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct SourceDefinition { pub struct SourceDefinition {
@ -14,16 +13,16 @@ pub struct SourceDefinition {
impl SourceDefinition { impl SourceDefinition {
pub fn from_identifier(identifier: &Identifier) -> Self { pub fn from_identifier(identifier: &Identifier) -> Self {
SourceDefinition { SourceDefinition {
file_id: identifier.file_id(), file_id: identifier.file_id,
range: identifier.range(), range: identifier.range,
} }
} }
pub fn from_identifier_rc(identifier: Rc<RefCell<Identifier>>) -> Self { pub fn from_identifier_rc(identifier: Rc<RefCell<Identifier>>) -> Self {
let borrowed = identifier.borrow(); let borrowed = identifier.borrow();
SourceDefinition { SourceDefinition {
file_id: borrowed.file_id(), file_id: borrowed.file_id,
range: borrowed.range(), range: borrowed.range,
} }
} }
@ -56,7 +55,7 @@ pub enum Symbol {
UseStatement(Rc<RefCell<UseStatementSymbol>>), UseStatement(Rc<RefCell<UseStatementSymbol>>),
Module(Rc<ModuleSymbol>), Module(Rc<ModuleSymbol>),
Type(Rc<TypeSymbol>), Type(Rc<TypeSymbol>),
Function(Rc<RefCell<FunctionSymbol>>), Function(Rc<FunctionSymbol>),
Parameter(Rc<ParameterSymbol>), Parameter(Rc<ParameterSymbol>),
Variable(Rc<VariableSymbol>), Variable(Rc<VariableSymbol>),
} }
@ -64,10 +63,10 @@ pub enum Symbol {
impl Symbol { impl Symbol {
pub fn definition(&self) -> Option<SourceDefinition> { pub fn definition(&self) -> Option<SourceDefinition> {
match self { match self {
Symbol::UseStatement(s) => s.borrow().definition(), Symbol::UseStatement(s) => s.borrow().definition.clone(),
Symbol::Module(s) => s.definition(), Symbol::Module(s) => s.definition(),
Symbol::Type(s) => s.definition(), Symbol::Type(s) => s.definition(),
Symbol::Function(s) => s.borrow().definition(), Symbol::Function(s) => s.definition(),
Symbol::Parameter(s) => s.definition(), Symbol::Parameter(s) => s.definition(),
Symbol::Variable(s) => s.definition(), Symbol::Variable(s) => s.definition(),
} }
@ -81,21 +80,32 @@ impl Symbol {
} }
} }
impl Display for Symbol {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
use Symbol::*;
match self {
UseStatement(use_statement_symbol) => write!(f, "{}", use_statement_symbol.borrow()),
Module(module_symbol) => write!(f, "{}", module_symbol),
Type(class_symbol) => write!(f, "{}", class_symbol),
Function(function_symbol) => write!(f, "{}", function_symbol),
Parameter(parameter_symbol) => write!(f, "{}", parameter_symbol),
Variable(variable_symbol) => write!(f, "{}", variable_symbol),
}
}
}
/* Use-statement */ /* Use-statement */
#[derive(Debug, Clone)]
pub struct UseStatementSymbol { pub struct UseStatementSymbol {
pub fqn: String, pub fqn: String,
pub declared_name: String, pub declared_name: String,
definition: Option<SourceDefinition>, definition: Option<SourceDefinition>,
referenced_symbol: Option<Box<Symbol>>, referenced_symbol: Option<Box<Symbol>>
} }
impl UseStatementSymbol { impl UseStatementSymbol {
pub fn new( pub fn new(fqn: &str, declared_name: &str, identifier: Option<Rc<RefCell<Identifier>>>) -> Self {
fqn: &str,
declared_name: &str,
identifier: Option<Rc<RefCell<Identifier>>>,
) -> Self {
UseStatementSymbol { UseStatementSymbol {
fqn: fqn.to_string(), fqn: fqn.to_string(),
declared_name: declared_name.to_string(), declared_name: declared_name.to_string(),
@ -123,18 +133,20 @@ impl SymbolInner for UseStatementSymbol {
} }
} }
impl Debug for UseStatementSymbol { impl Display for UseStatementSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("UseStatementSymbol") write!(
.field("fqn", &self.fqn) f,
.field("declared_name", &self.declared_name) "UseStatementSymbol(fqn = {}, declared_name = {})",
.field("referenced_symbol", &self.referenced_symbol) self.fqn, self.declared_name
.finish() )
} }
} }
/* Module */ /* Module */
#[derive(Debug)]
pub struct ModuleSymbol { pub struct ModuleSymbol {
fqn: String, fqn: String,
declared_name: String, declared_name: String,
@ -168,18 +180,19 @@ impl SymbolInner for ModuleSymbol {
} }
} }
impl Debug for ModuleSymbol { impl Display for ModuleSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("ModuleSymbol") write!(
.field("fqn", &self.fqn) f,
.field("declared_name", &self.declared_name) "ModuleSymbol(name = {}, is_public = {})",
.field("is_public", &self.is_public) self.fqn, self.is_public
.finish() )
} }
} }
/* TypeSymbol */ /* Class */
#[derive(Debug)]
pub struct TypeSymbol { pub struct TypeSymbol {
fqn: String, fqn: String,
declared_name: String, declared_name: String,
@ -188,12 +201,7 @@ pub struct TypeSymbol {
} }
impl TypeSymbol { impl TypeSymbol {
pub fn new( pub fn new(fqn: &str, declared_name: &str, is_public: bool, identifier: Option<&Identifier>) -> Self {
fqn: &str,
declared_name: &str,
is_public: bool,
identifier: Option<&Identifier>,
) -> Self {
TypeSymbol { TypeSymbol {
fqn: fqn.to_string(), fqn: fqn.to_string(),
declared_name: declared_name.to_string(), declared_name: declared_name.to_string(),
@ -221,26 +229,25 @@ impl SymbolInner for TypeSymbol {
} }
} }
impl Debug for TypeSymbol { impl Display for TypeSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("TypeSymbol") write!(
.field("fqn", &self.fqn) f,
.field("declared_name", &self.declared_name) "TypeSymbol(fqn = {}, declared_name = {})",
.field("is_public", &self.is_public) self.fqn, self.declared_name
.finish() )
} }
} }
/* Function */ /* Function */
#[derive(Debug)]
pub struct FunctionSymbol { pub struct FunctionSymbol {
fqn: String, fqn: String,
declared_name: String, declared_name: String,
is_public: bool, is_public: bool,
is_platform: bool, is_platform: bool,
definition: Option<SourceDefinition>, definition: Option<SourceDefinition>,
parameters: Vec<Rc<ParameterSymbol>>,
return_type: Option<Rc<TypeSymbol>>,
} }
impl FunctionSymbol { impl FunctionSymbol {
@ -257,49 +264,12 @@ impl FunctionSymbol {
is_public, is_public,
is_platform, is_platform,
definition: identifier.map(SourceDefinition::from_identifier), definition: identifier.map(SourceDefinition::from_identifier),
parameters: Vec::new(),
return_type: None,
}
}
pub fn with_parameters(self, parameters: Vec<ParameterSymbol>) -> Self {
Self {
fqn: self.fqn,
declared_name: self.declared_name,
is_public: self.is_public,
is_platform: self.is_platform,
definition: self.definition,
parameters: parameters
.into_iter()
.map(|parameter| Rc::new(parameter))
.collect(),
return_type: self.return_type,
}
}
pub fn with_return_type(self, return_type: TypeSymbol) -> Self {
Self {
fqn: self.fqn,
declared_name: self.declared_name,
is_public: self.is_public,
is_platform: self.is_platform,
definition: self.definition,
parameters: self.parameters,
return_type: Some(Rc::new(return_type)),
} }
} }
pub fn fqn(&self) -> &str { pub fn fqn(&self) -> &str {
&self.fqn &self.fqn
} }
pub fn set_parameters(&mut self, parameters: Vec<Rc<ParameterSymbol>>) {
self.parameters = parameters;
}
pub fn set_return_type(&mut self, return_type: Rc<TypeSymbol>) {
self.return_type = Some(return_type);
}
} }
impl SymbolInner for FunctionSymbol { impl SymbolInner for FunctionSymbol {
@ -312,21 +282,19 @@ impl SymbolInner for FunctionSymbol {
} }
} }
impl Debug for FunctionSymbol { impl Display for FunctionSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("FunctionSymbol") write!(
.field("fqn", &self.fqn) f,
.field("declared_name", &self.declared_name) "FunctionSymbol(fqn = {}, declared_name = {}, is_public = {})",
.field("is_public", &self.is_public) self.fqn, self.declared_name, self.is_public
.field("is_platform", &self.is_platform) )
.field("parameters", &self.parameters)
.field("return_type", &self.return_type)
.finish()
} }
} }
/* Parameter */ /* Parameter */
#[derive(Debug)]
pub struct ParameterSymbol { pub struct ParameterSymbol {
declared_name: String, declared_name: String,
definition: Option<SourceDefinition>, definition: Option<SourceDefinition>,
@ -351,16 +319,19 @@ impl SymbolInner for ParameterSymbol {
} }
} }
impl Debug for ParameterSymbol { impl Display for ParameterSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("ParameterSymbol") write!(
.field("declared_name", &self.declared_name) f,
.finish() "ParameterSymbol({})",
self.declared_name
)
} }
} }
/* Variable */ /* Variable */
#[derive(Debug)]
pub struct VariableSymbol { pub struct VariableSymbol {
declared_name: String, declared_name: String,
is_mutable: bool, is_mutable: bool,
@ -387,11 +358,12 @@ impl SymbolInner for VariableSymbol {
} }
} }
impl Debug for VariableSymbol { impl Display for VariableSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("VariableSymbol") write!(
.field("declared_name", &self.declared_name) f,
.field("is_mutable", &self.is_mutable) "VariableSymbol(name = {}, is_mutable = {})",
.finish() self.declared_name, self.is_mutable
)
} }
} }

View File

@ -1,10 +1,10 @@
use std::cell::RefCell;
use crate::name_analysis::symbol::{ use crate::name_analysis::symbol::{
FunctionSymbol, ModuleSymbol, ParameterSymbol, Symbol, SymbolInner, TypeSymbol, FunctionSymbol, ModuleSymbol, ParameterSymbol, Symbol, SymbolInner, TypeSymbol,
UseStatementSymbol, VariableSymbol, UseStatementSymbol, VariableSymbol,
}; };
use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined; use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined;
use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition; use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition;
use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt::Display; use std::fmt::Display;
use std::rc::Rc; use std::rc::Rc;
@ -16,7 +16,7 @@ struct Scope {
use_statement_symbols: HashMap<String, Rc<RefCell<UseStatementSymbol>>>, use_statement_symbols: HashMap<String, Rc<RefCell<UseStatementSymbol>>>,
module_symbols: HashMap<String, Rc<ModuleSymbol>>, module_symbols: HashMap<String, Rc<ModuleSymbol>>,
type_symbols: HashMap<String, Rc<TypeSymbol>>, type_symbols: HashMap<String, Rc<TypeSymbol>>,
function_symbols: HashMap<String, Rc<RefCell<FunctionSymbol>>>, function_symbols: HashMap<String, Rc<FunctionSymbol>>,
parameter_symbols: HashMap<String, Rc<ParameterSymbol>>, parameter_symbols: HashMap<String, Rc<ParameterSymbol>>,
variable_symbols: HashMap<String, Rc<VariableSymbol>>, variable_symbols: HashMap<String, Rc<VariableSymbol>>,
debug_name: String, debug_name: String,
@ -37,34 +37,13 @@ impl Scope {
} }
fn get_any_symbol(&self, name: &str) -> Option<Symbol> { fn get_any_symbol(&self, name: &str) -> Option<Symbol> {
self.variable_symbols self.variable_symbols.get(name)
.get(name)
.map(|s| Symbol::Variable(s.clone())) .map(|s| Symbol::Variable(s.clone()))
.or_else(|| { .or_else(|| self.parameter_symbols.get(name).map(|s| Symbol::Parameter(s.clone())))
self.parameter_symbols .or_else(|| self.function_symbols.get(name).map(|s| Symbol::Function(s.clone())))
.get(name) .or_else(|| self.type_symbols.get(name).map(|ts| Symbol::Type(ts.clone())))
.map(|s| Symbol::Parameter(s.clone())) .or_else(|| self.module_symbols.get(name).map(|ms| Symbol::Module(ms.clone())))
}) .or_else(|| self.use_statement_symbols.get(name).map(|us| Symbol::UseStatement(us.clone())))
.or_else(|| {
self.function_symbols
.get(name)
.map(|s| Symbol::Function(s.clone()))
})
.or_else(|| {
self.type_symbols
.get(name)
.map(|ts| Symbol::Type(ts.clone()))
})
.or_else(|| {
self.module_symbols
.get(name)
.map(|ms| Symbol::Module(ms.clone()))
})
.or_else(|| {
self.use_statement_symbols
.get(name)
.map(|us| Symbol::UseStatement(us.clone()))
})
} }
fn get_module_symbol_by_declared_name(&self, name: &str) -> Option<Rc<ModuleSymbol>> { fn get_module_symbol_by_declared_name(&self, name: &str) -> Option<Rc<ModuleSymbol>> {
@ -76,32 +55,9 @@ impl Scope {
None None
} }
fn get_type_symbol_by_declared_name(&self, declared_name: &str) -> Option<Rc<TypeSymbol>> {
if let Some(type_symbol) = self.type_symbols.get(declared_name) {
Some(type_symbol.clone())
} else {
for use_statement_symbol in self.use_statement_symbols.values() {
let borrowed = use_statement_symbol.borrow();
if borrowed.declared_name() == declared_name {
if let Some(referenced_symbol) = borrowed.referenced_symbol() {
match *referenced_symbol {
Symbol::Type(type_symbol) => return Some(type_symbol.clone()),
_ => continue,
}
}
}
}
None
}
}
fn get_type_symbol_by_fqn(&self, fqn: &str) -> Option<Rc<TypeSymbol>> {
self.type_symbols.values().find(|s| s.fqn() == fqn).cloned()
}
fn get_usable_symbol_by_fqn(&self, fqn: &str) -> Option<Symbol> { fn get_usable_symbol_by_fqn(&self, fqn: &str) -> Option<Symbol> {
for function_symbol in self.function_symbols.values() { for function_symbol in self.function_symbols.values() {
if function_symbol.borrow().fqn() == fqn { if function_symbol.fqn() == fqn {
return Some(Symbol::Function(function_symbol.clone())); return Some(Symbol::Function(function_symbol.clone()));
} }
} }
@ -115,7 +71,7 @@ impl Scope {
fn get_usable_symbol_by_declared_name(&self, declared_name: &str) -> Option<Symbol> { fn get_usable_symbol_by_declared_name(&self, declared_name: &str) -> Option<Symbol> {
for function_symbol in self.function_symbols.values() { for function_symbol in self.function_symbols.values() {
if function_symbol.borrow().declared_name() == declared_name { if function_symbol.declared_name() == declared_name {
return Some(Symbol::Function(function_symbol.clone())); return Some(Symbol::Function(function_symbol.clone()));
} }
} }
@ -140,45 +96,6 @@ impl Scope {
} }
None None
} }
fn get_expressible_by_declared_name(&self, declared_name: &str) -> Option<Symbol> {
self.variable_symbols
.get(declared_name)
.map(|s| Symbol::Variable(s.clone()))
.or_else(|| {
self.parameter_symbols
.get(declared_name)
.map(|p| Symbol::Parameter(p.clone()))
})
.or_else(|| {
self.function_symbols
.get(declared_name)
.map(|f| Symbol::Function(f.clone()))
})
.or_else(|| {
self.type_symbols
.get(declared_name)
.map(|t| Symbol::Type(t.clone()))
})
.or_else(|| {
self.use_statement_symbols
.get(declared_name)
.map(|us| Symbol::UseStatement(us.clone()))
})
}
fn get_expressible_by_fqn(&self, fqn: &str) -> Option<Symbol> {
self.function_symbols
.values()
.find(|fs| fs.borrow().fqn() == fqn)
.map(|f| Symbol::Function(f.clone()))
.or_else(|| {
self.type_symbols
.values()
.find(|ts| ts.fqn() == fqn)
.map(|ts| Symbol::Type(ts.clone()))
})
}
} }
/* Symbol table */ /* Symbol table */
@ -235,20 +152,18 @@ impl SymbolTable {
pub fn insert_use_statement_symbol( pub fn insert_use_statement_symbol(
&mut self, &mut self,
use_statement_symbol: UseStatementSymbol, use_statement_symbol: UseStatementSymbol,
) -> Result<Rc<RefCell<UseStatementSymbol>>, SymbolInsertError> { ) -> Result<(), SymbolInsertError> {
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
if let Some(defined_symbol) = if let Some(defined_symbol) =
current_scope.get_usable_symbol_by_declared_name(use_statement_symbol.declared_name()) current_scope.get_usable_symbol_by_declared_name(use_statement_symbol.declared_name())
{ {
Err(SymbolAlreadyDefined(defined_symbol)) Err(SymbolAlreadyDefined(defined_symbol))
} else { } else {
let declared_name = use_statement_symbol.declared_name().to_string(); current_scope.use_statement_symbols.insert(
let to_insert = Rc::new(RefCell::new(use_statement_symbol)); use_statement_symbol.declared_name().to_string(),
let to_return = to_insert.clone(); Rc::new(RefCell::new(use_statement_symbol)),
current_scope );
.use_statement_symbols Ok(())
.insert(declared_name, to_insert);
Ok(to_return)
} }
} }
@ -288,39 +203,36 @@ impl SymbolTable {
pub fn insert_function_symbol( pub fn insert_function_symbol(
&mut self, &mut self,
function_symbol: FunctionSymbol, function_symbol: FunctionSymbol,
) -> Result<Rc<RefCell<FunctionSymbol>>, SymbolInsertError> { ) -> Result<(), SymbolInsertError> {
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
if let Some(defined_symbol) = if let Some(defined_symbol) =
current_scope.get_usable_symbol_by_declared_name(function_symbol.declared_name()) current_scope.get_usable_symbol_by_declared_name(function_symbol.declared_name())
{ {
Err(SymbolAlreadyDefined(defined_symbol)) Err(SymbolAlreadyDefined(defined_symbol))
} else { } else {
let declared_name = function_symbol.declared_name().to_string(); current_scope.function_symbols.insert(
let to_insert = Rc::new(RefCell::new(function_symbol)); function_symbol.declared_name().to_string(),
let to_return = to_insert.clone(); Rc::new(function_symbol),
current_scope );
.function_symbols Ok(())
.insert(declared_name, to_insert);
Ok(to_return)
} }
} }
pub fn insert_parameter_symbol( pub fn insert_parameter_symbol(
&mut self, &mut self,
parameter_symbol: ParameterSymbol, parameter_symbol: ParameterSymbol,
) -> Result<Rc<ParameterSymbol>, SymbolInsertError> { ) -> Result<(), SymbolInsertError> {
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
if let Some(defined_symbol) = if let Some(defined_symbol) =
current_scope.get_value_symbol_by_declared_name(parameter_symbol.declared_name()) current_scope.get_value_symbol_by_declared_name(parameter_symbol.declared_name())
{ {
Err(SymbolAlreadyDefined(defined_symbol)) Err(SymbolAlreadyDefined(defined_symbol))
} else { } else {
let to_insert = Rc::new(parameter_symbol); current_scope.parameter_symbols.insert(
let to_return = to_insert.clone(); parameter_symbol.declared_name().to_string(),
current_scope Rc::new(parameter_symbol),
.parameter_symbols );
.insert(to_insert.declared_name().to_string(), to_insert); Ok(())
Ok(to_return)
} }
} }
@ -342,7 +254,6 @@ impl SymbolTable {
} }
} }
#[deprecated(note = "Use more specific lookup methods.")]
pub fn lookup(&self, name: &str, scope_id: usize) -> Result<Symbol, SymbolLookupError> { pub fn lookup(&self, name: &str, scope_id: usize) -> Result<Symbol, SymbolLookupError> {
let mut scope_opt = Some(&self.scopes[scope_id]); let mut scope_opt = Some(&self.scopes[scope_id]);
while let Some(scope) = scope_opt { while let Some(scope) = scope_opt {
@ -358,44 +269,6 @@ impl SymbolTable {
Err(NoDefinition) Err(NoDefinition)
} }
pub fn lookup_type_by_declared_name(
&self,
declared_name: &str,
scope_id: usize,
) -> Result<Rc<TypeSymbol>, SymbolLookupError> {
let mut scope_opt = Some(&self.scopes[scope_id]);
while let Some(scope) = scope_opt {
if let Some(symbol) = scope.get_type_symbol_by_declared_name(declared_name) {
return Ok(symbol);
}
scope_opt = if let Some(parent_id) = scope.parent {
Some(&self.scopes[parent_id])
} else {
None
}
}
Err(NoDefinition)
}
pub fn lookup_type_by_fqn(
&self,
fqn: &str,
scope_id: usize,
) -> Result<Rc<TypeSymbol>, SymbolLookupError> {
let mut scope_opt = Some(&self.scopes[scope_id]);
while let Some(scope) = scope_opt {
if let Some(symbol) = scope.get_type_symbol_by_fqn(fqn) {
return Ok(symbol);
}
scope_opt = if let Some(parent_id) = scope.parent {
Some(&self.scopes[parent_id])
} else {
None
}
}
Err(NoDefinition)
}
pub fn lookup_usable_by_fqn( pub fn lookup_usable_by_fqn(
&self, &self,
fully_qualified_name: &str, fully_qualified_name: &str,
@ -408,68 +281,27 @@ impl SymbolTable {
} }
Err(NoDefinition) Err(NoDefinition)
} }
pub fn lookup_expressible_by_declared_name(
&self,
declared_name: &str,
scope_id: usize,
) -> Result<Symbol, SymbolLookupError> {
let mut scope_opt = Some(&self.scopes[scope_id]);
while let Some(scope) = scope_opt {
if let Some(symbol) = scope.get_expressible_by_declared_name(declared_name) {
return Ok(symbol);
}
scope_opt = if let Some(parent_id) = scope.parent {
Some(&self.scopes[parent_id])
} else {
None
}
}
Err(NoDefinition)
}
pub fn lookup_expressible_by_fqn(
&self,
fqn: &str,
scope_id: usize,
) -> Result<Symbol, SymbolLookupError> {
let mut scope_opt = Some(&self.scopes[scope_id]);
while let Some(scope) = scope_opt {
if let Some(symbol) = scope.get_expressible_by_fqn(fqn) {
return Ok(symbol);
}
scope_opt = if let Some(parent_id) = scope.parent {
Some(&self.scopes[parent_id])
} else {
None
}
}
Err(NoDefinition)
}
} }
impl Display for SymbolTable { impl Display for SymbolTable {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
writeln!(f, "SymbolTable(current_scope = {})", self.current_scope_id)?; writeln!(f, "SymbolTable(current_scope = {})", self.current_scope_id)?;
for (i, scope) in self.scopes.iter().enumerate() { for (i, scope) in self.scopes.iter().enumerate() {
writeln!(f, "----Scope {} {}----", i, scope.debug_name)?; writeln!(f, "Scope {} {}", i, scope.debug_name)?;
for symbol in scope.use_statement_symbols.values() { for (name, symbol) in &scope.use_statement_symbols {
writeln!(f, "{:#?}", symbol.borrow())?; writeln!(f, " {}({})", name, symbol.borrow())?;
} }
for symbol in scope.module_symbols.values() { for (name, symbol) in &scope.module_symbols {
writeln!(f, "{:#?}", symbol)?; writeln!(f, " {}({})", name, symbol)?;
} }
for symbol in scope.type_symbols.values() { for (name, symbol) in &scope.type_symbols {
writeln!(f, "{:#?}", symbol)?; writeln!(f, " {}({})", name, symbol)?;
} }
for symbol in scope.function_symbols.values() { for (name, symbol) in &scope.function_symbols {
writeln!(f, "{:#?}", symbol.borrow())?; writeln!(f, " {}({})", name, symbol)?;
} }
for symbol in scope.parameter_symbols.values() { for (name, symbol) in &scope.variable_symbols {
writeln!(f, "{:#?}", symbol)?; writeln!(f, " {}({})", name, symbol)?;
}
for symbol in scope.variable_symbols.values() {
writeln!(f, "{:#?}", symbol)?;
} }
} }
Ok(()) Ok(())

View File

@ -2,7 +2,7 @@
Ns = { "ns" } Ns = { "ns" }
TypeKw = { "type" } TypeKw = { "type" }
Mod = { "mod" } Mod = { "mod" }
IntKw = { "int" } Int = { "int" }
ClassKw = { "class" } ClassKw = { "class" }
Platform = { "platform" } Platform = { "platform" }
Pub = { "pub" } Pub = { "pub" }
@ -15,6 +15,7 @@ Ref = { "ref" }
Def = { "def" } Def = { "def" }
Where = { "where" } Where = { "where" }
Infer = { "infer" } Infer = { "infer" }
Void = { "Void" }
Delegate = { "delegate" } Delegate = { "delegate" }
Let = { "let" } Let = { "let" }
Fn = { "fn" } Fn = { "fn" }
@ -31,25 +32,12 @@ True = { "true" }
False = { "false" } False = { "false" }
Use = { "use" } Use = { "use" }
// Keywords: primitive types
Byte = { "Byte" }
Short = { "Short" }
Char = { "Char" }
Int = { "Int" }
Long = { "Long" }
Double = { "Double" }
Bool = { "Bool" }
String = { "String" }
Array = { "Array" }
Any = { "Any" }
Void = { "Void" }
// Keywords as a rule (for preventing identifiers with keywords, etc.) // Keywords as a rule (for preventing identifiers with keywords, etc.)
Keyword = { Keyword = {
Ns Ns
| TypeKw | TypeKw
| Mod | Mod
| IntKw | Int
| ClassKw | ClassKw
| Platform | Platform
| Pub | Pub
@ -62,6 +50,7 @@ Keyword = {
| Def | Def
| Where | Where
| Infer | Infer
| Void
| Delegate | Delegate
| Let | Let
| Fn | Fn
@ -77,17 +66,6 @@ Keyword = {
| True | True
| False | False
| Use | Use
| Byte
| Short
| Char
| Int
| Long
| Double
| Bool
| String
| Array
| Any
| Void
} }
// Symbols // Symbols
@ -202,26 +180,12 @@ ParenthesesOptionalTypeUseList = {
// Parameters = declaration // Parameters = declaration
TypeUse = { TypeUse = {
PrimitiveType Void
| InterfaceOrClassTypeUse | InterfaceOrClassTypeUse
| TupleTypeUse | TupleTypeUse
| FunctionTypeUse | FunctionTypeUse
} }
PrimitiveType = {
Byte
| Short
| Char
| Int
| Long
| Double
| Bool
| String
| Array ~ GenericArguments?
| Any
| Void
}
InterfaceOrClassTypeUse = { InterfaceOrClassTypeUse = {
Borrow* Borrow*
~ Mut? ~ Mut?
@ -371,7 +335,7 @@ Module = {
Interface = { Interface = {
Pub? Pub?
~ IntKw ~ Int
~ Identifier ~ Identifier
~ GenericParameters? ~ GenericParameters?
~ ImplementsList? ~ ImplementsList?

View File

@ -1,14 +1,23 @@
use crate::name_analysis::symbol::{FunctionSymbol, ParameterSymbol, TypeSymbol}; use crate::name_analysis::symbol::{FunctionSymbol, TypeSymbol};
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable};
pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> { pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> {
symbol_table.insert_function_symbol( symbol_table.insert_type_symbol(TypeSymbol::new("std::core:Array", "Array", true, None))?;
FunctionSymbol::new("std::core::println", "println", true, true, None) // todo: make this primitive
.with_parameters(vec![ParameterSymbol::new("msg", None)]), symbol_table.insert_type_symbol(TypeSymbol::new("std::core::String", "String", true, None))?;
)?; symbol_table.insert_function_symbol(FunctionSymbol::new(
symbol_table.insert_function_symbol( "std::core::println",
FunctionSymbol::new("std::core::print", "print", true, true, None) "println",
.with_parameters(vec![ParameterSymbol::new("msg", None)]), true,
)?; true,
None,
))?;
symbol_table.insert_function_symbol(FunctionSymbol::new(
"std::core::print",
"print",
true,
true,
None,
))?;
Ok(()) Ok(())
} }