Compare commits
7 Commits
e578250ee6
...
d5ac6dfc2d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5ac6dfc2d | ||
|
|
36e28ae4a9 | ||
|
|
9731bb38fe | ||
|
|
8969186467 | ||
|
|
e879ad2d90 | ||
|
|
54882b187c | ||
|
|
1f5d17ef79 |
@ -36,8 +36,8 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
MemberChildBuild::Boolean(_) => None,
|
MemberChildBuild::Boolean(_) => None,
|
||||||
MemberChildBuild::Special(_) => None,
|
|
||||||
},
|
},
|
||||||
|
StructChild::Special(_) => None,
|
||||||
})
|
})
|
||||||
.filter(Option::is_some)
|
.filter(Option::is_some)
|
||||||
.map(Option::unwrap)
|
.map(Option::unwrap)
|
||||||
|
|||||||
@ -1,8 +1,44 @@
|
|||||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
||||||
use crate::spec::struct_spec::{MemberChildBuild, NodeMemberBuild, SpecialMemberBuild, StructChild, StructSpec, VecChild, VecChildBuild};
|
use crate::spec::struct_spec::{MemberChildBuild, NodeMemberBuild, SpecialChild, SpecialChildKind, StructChild, StructSpec, VecChild, VecChildBuild};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
fn make_preamble(spec: &StructSpec, pair_ident: &Ident) -> TokenStream {
|
||||||
|
if spec.children().any(StructChild::is_special) {
|
||||||
|
quote! {
|
||||||
|
let as_span = #pair_ident.as_span();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_special_children(spec: &StructSpec) -> Vec<TokenStream> {
|
||||||
|
spec.children()
|
||||||
|
.map(StructChild::unwrap_special)
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.map(|special_child| {
|
||||||
|
let child_ident = format_ident!("{}", special_child.name());
|
||||||
|
match special_child.kind() {
|
||||||
|
SpecialChildKind::FileId => {
|
||||||
|
quote! {
|
||||||
|
let #child_ident = file_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SpecialChildKind::Range => {
|
||||||
|
quote! {
|
||||||
|
let #child_ident = Range {
|
||||||
|
start: as_span.start(),
|
||||||
|
end: as_span.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
|
||||||
fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream {
|
fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream {
|
||||||
let child_ident = format_ident!("{}", vec_child.name());
|
let child_ident = format_ident!("{}", vec_child.name());
|
||||||
match vec_child.build() {
|
match vec_child.build() {
|
||||||
@ -44,8 +80,8 @@ fn make_child_holder(child_spec: &StructChild) -> Option<TokenStream> {
|
|||||||
Some(make_node_child_holder(member_child.name(), node_child))
|
Some(make_node_child_holder(member_child.name(), node_child))
|
||||||
}
|
}
|
||||||
MemberChildBuild::Boolean(_) => Some(make_boolean_child_holder(member_child.name())),
|
MemberChildBuild::Boolean(_) => Some(make_boolean_child_holder(member_child.name())),
|
||||||
MemberChildBuild::Special(_) => None,
|
|
||||||
},
|
},
|
||||||
|
StructChild::Special(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +120,12 @@ fn make_boolean_member_child_match_action(name: &str) -> TokenStream {
|
|||||||
|
|
||||||
fn make_rule_matcher(child_spec: &StructChild) -> Option<TokenStream> {
|
fn make_rule_matcher(child_spec: &StructChild) -> Option<TokenStream> {
|
||||||
match child_spec {
|
match child_spec {
|
||||||
StructChild::SkipChild(_) => None,
|
StructChild::SkipChild(skip_child) => {
|
||||||
|
let rule_ident = format_ident!("{}", skip_child.rule());
|
||||||
|
Some(quote! {
|
||||||
|
Rule::#rule_ident => {}
|
||||||
|
})
|
||||||
|
},
|
||||||
StructChild::VecChild(vec_child) => {
|
StructChild::VecChild(vec_child) => {
|
||||||
let rule_ident = format_ident!("{}", vec_child.rule());
|
let rule_ident = format_ident!("{}", vec_child.rule());
|
||||||
let action = make_vec_child_match_action(vec_child);
|
let action = make_vec_child_match_action(vec_child);
|
||||||
@ -111,9 +152,9 @@ fn make_rule_matcher(child_spec: &StructChild) -> Option<TokenStream> {
|
|||||||
Rule::#rule_ident => { #action }
|
Rule::#rule_ident => { #action }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
MemberChildBuild::Special(_) => None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
StructChild::Special(_) => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,6 +187,11 @@ fn make_boolean_member_child_arg(name: &str) -> TokenStream {
|
|||||||
quote! { #child_ident }
|
quote! { #child_ident }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_special_child_arg(special_child: &SpecialChild) -> TokenStream {
|
||||||
|
let child_ident = format_ident!("{}", special_child.name());
|
||||||
|
quote! { #child_ident }
|
||||||
|
}
|
||||||
|
|
||||||
fn make_child_arg(child_spec: &StructChild, pair_ident: &Ident) -> Option<TokenStream> {
|
fn make_child_arg(child_spec: &StructChild, pair_ident: &Ident) -> Option<TokenStream> {
|
||||||
match child_spec {
|
match child_spec {
|
||||||
StructChild::SkipChild(_) => None,
|
StructChild::SkipChild(_) => None,
|
||||||
@ -159,22 +205,8 @@ fn make_child_arg(child_spec: &StructChild, pair_ident: &Ident) -> Option<TokenS
|
|||||||
MemberChildBuild::Boolean(_) => {
|
MemberChildBuild::Boolean(_) => {
|
||||||
Some(make_boolean_member_child_arg(member_child.name()))
|
Some(make_boolean_member_child_arg(member_child.name()))
|
||||||
},
|
},
|
||||||
MemberChildBuild::Special(special_member_build) => {
|
|
||||||
match special_member_build {
|
|
||||||
SpecialMemberBuild::FileId => {
|
|
||||||
Some(quote! { file_id })
|
|
||||||
}
|
|
||||||
SpecialMemberBuild::Range => {
|
|
||||||
Some(quote! {
|
|
||||||
Range {
|
|
||||||
start: #pair_ident.as_span().start(),
|
|
||||||
end: #pair_ident.as_span().end(),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
StructChild::Special(special_child) => Some(make_special_child_arg(special_child)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,6 +231,10 @@ pub fn make_struct_build_fn(build_spec: &StructSpec) -> TokenStream {
|
|||||||
let pair_ident = format_ident!("{}", make_build_pair(build_spec.build()));
|
let pair_ident = format_ident!("{}", make_build_pair(build_spec.build()));
|
||||||
let return_type_ident = format_ident!("{}", build_spec.build());
|
let return_type_ident = format_ident!("{}", build_spec.build());
|
||||||
|
|
||||||
|
let preamble = make_preamble(build_spec, &pair_ident);
|
||||||
|
|
||||||
|
let special_children = make_special_children(build_spec);
|
||||||
|
|
||||||
let child_holders = build_spec
|
let child_holders = build_spec
|
||||||
.children()
|
.children()
|
||||||
.map(|child_spec| make_child_holder(child_spec))
|
.map(|child_spec| make_child_holder(child_spec))
|
||||||
@ -224,6 +260,10 @@ pub fn make_struct_build_fn(build_spec: &StructSpec) -> TokenStream {
|
|||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident {
|
fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||||
|
#preamble
|
||||||
|
|
||||||
|
#(#special_children;)*
|
||||||
|
|
||||||
#(#child_holders;)*
|
#(#child_holders;)*
|
||||||
|
|
||||||
#iter_stream
|
#iter_stream
|
||||||
|
|||||||
@ -56,12 +56,6 @@ fn deserialize_member_build(child_name: &str, rule: &str, props: &Yaml) -> Membe
|
|||||||
} else {
|
} else {
|
||||||
panic!("Expected 'on' in 'boolean' in 'build' in {}", child_name);
|
panic!("Expected 'on' in 'boolean' in 'build' in {}", child_name);
|
||||||
}
|
}
|
||||||
} else if props["special"].is_hash() {
|
|
||||||
match props["special"]["kind"].as_str().unwrap() {
|
|
||||||
"file_id" => MemberChildBuild::Special(SpecialMemberBuild::FileId),
|
|
||||||
"range" => MemberChildBuild::Special(SpecialMemberBuild::Range),
|
|
||||||
_ => panic!(),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
panic!(
|
panic!(
|
||||||
"Expected one of 'node', 'boolean', or 'special' in 'build' in {}",
|
"Expected one of 'node', 'boolean', or 'special' in 'build' in {}",
|
||||||
@ -98,6 +92,14 @@ fn deserialize_member_child(child_name: &str, props: &Yaml) -> StructChild {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_special_child(name: &str, props: &Yaml) -> StructChild {
|
||||||
|
match props["kind"].as_str().unwrap() {
|
||||||
|
"file_id" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::FileId)),
|
||||||
|
"range" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::Range)),
|
||||||
|
_ => panic!("Invalid special child kind {} in {}", props["kind"].as_str().unwrap(), name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild {
|
fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild {
|
||||||
if props["skip"].is_hash() {
|
if props["skip"].is_hash() {
|
||||||
deserialize_skip_child(&props["skip"])
|
deserialize_skip_child(&props["skip"])
|
||||||
@ -105,6 +107,8 @@ fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild {
|
|||||||
deserialize_vec_child(name, &props["vec"])
|
deserialize_vec_child(name, &props["vec"])
|
||||||
} else if props["member"].is_hash() {
|
} else if props["member"].is_hash() {
|
||||||
deserialize_member_child(name, &props["member"])
|
deserialize_member_child(name, &props["member"])
|
||||||
|
} else if props["special"].is_hash() {
|
||||||
|
deserialize_special_child(name, &props["special"])
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected 'skip' or 'vec' in 'member' in {}", name);
|
panic!("Expected 'skip' or 'vec' in 'member' in {}", name);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -231,8 +231,8 @@ fn make_struct_p2_impl(struct_build_spec: &StructSpec) -> TokenStream {
|
|||||||
writer.writeln_indented(&format!(#format_string, self.#child_ident()))?;
|
writer.writeln_indented(&format!(#format_string, self.#child_ident()))?;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
MemberChildBuild::Special(_) => None
|
|
||||||
},
|
},
|
||||||
|
StructChild::Special(_) => None
|
||||||
})
|
})
|
||||||
.filter(Option::is_some)
|
.filter(Option::is_some)
|
||||||
.map(Option::unwrap)
|
.map(Option::unwrap)
|
||||||
|
|||||||
@ -26,6 +26,25 @@ pub enum StructChild {
|
|||||||
SkipChild(SkipChild),
|
SkipChild(SkipChild),
|
||||||
VecChild(VecChild),
|
VecChild(VecChild),
|
||||||
MemberChild(MemberChild),
|
MemberChild(MemberChild),
|
||||||
|
Special(SpecialChild),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StructChild {
|
||||||
|
pub fn is_special(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
StructChild::Special(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unwrap_special(&self) -> Option<&SpecialChild> {
|
||||||
|
match self {
|
||||||
|
StructChild::Special(special_child) => {
|
||||||
|
Some(special_child)
|
||||||
|
},
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SkipChild {
|
pub struct SkipChild {
|
||||||
@ -160,7 +179,6 @@ impl MemberChild {
|
|||||||
pub enum MemberChildBuild {
|
pub enum MemberChildBuild {
|
||||||
Node(NodeMemberBuild),
|
Node(NodeMemberBuild),
|
||||||
Boolean(BooleanMemberBuild),
|
Boolean(BooleanMemberBuild),
|
||||||
Special(SpecialMemberBuild),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -215,7 +233,30 @@ pub enum BooleanMemberBuildOn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SpecialMemberBuild {
|
pub struct SpecialChild {
|
||||||
|
name: String,
|
||||||
|
kind: SpecialChildKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpecialChild {
|
||||||
|
pub fn new(name: &str, kind: SpecialChildKind) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &SpecialChildKind {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SpecialChildKind {
|
||||||
FileId,
|
FileId,
|
||||||
Range,
|
Range,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::spec::struct_spec::{
|
use crate::spec::struct_spec::{
|
||||||
MemberChild, MemberChildBuild, SpecialMemberBuild, StructChild, StructSpec, VecChild,
|
MemberChild, MemberChildBuild, SpecialChild, SpecialChildKind, StructChild, StructSpec,
|
||||||
VecChildBuild,
|
VecChild, VecChildBuild,
|
||||||
};
|
};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
@ -76,22 +76,26 @@ fn make_member_child_accessors(member_child: &MemberChild) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MemberChildBuild::Special(special_member_build) => match special_member_build {
|
}
|
||||||
SpecialMemberBuild::FileId => {
|
}
|
||||||
|
|
||||||
|
fn make_special_child_accessors(special_child: &SpecialChild) -> TokenStream {
|
||||||
|
let child_ident = format_ident!("{}", special_child.name());
|
||||||
|
match special_child.kind() {
|
||||||
|
SpecialChildKind::FileId => {
|
||||||
quote! {
|
quote! {
|
||||||
pub fn file_id(&self) -> usize {
|
pub fn #child_ident(&self) -> usize {
|
||||||
self.file_id
|
self.#child_ident
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SpecialMemberBuild::Range => {
|
SpecialChildKind::Range => {
|
||||||
quote! {
|
quote! {
|
||||||
pub fn range(&self) -> Range<usize> {
|
pub fn #child_ident(&self) -> Range<usize> {
|
||||||
self.range
|
self.#child_ident
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +104,7 @@ fn make_accessors(child: &StructChild) -> Option<TokenStream> {
|
|||||||
StructChild::SkipChild(_) => None,
|
StructChild::SkipChild(_) => None,
|
||||||
StructChild::VecChild(vec_child) => Some(make_vec_child_accessors(vec_child)),
|
StructChild::VecChild(vec_child) => Some(make_vec_child_accessors(vec_child)),
|
||||||
StructChild::MemberChild(member_child) => Some(make_member_child_accessors(member_child)),
|
StructChild::MemberChild(member_child) => Some(make_member_child_accessors(member_child)),
|
||||||
|
StructChild::Special(special_child) => Some(make_special_child_accessors(special_child)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,6 +113,7 @@ fn make_member_ident(child: &StructChild) -> Option<Ident> {
|
|||||||
StructChild::SkipChild(_) => None,
|
StructChild::SkipChild(_) => None,
|
||||||
StructChild::VecChild(vec_child) => Some(format_ident!("{}", vec_child.name())),
|
StructChild::VecChild(vec_child) => Some(format_ident!("{}", vec_child.name())),
|
||||||
StructChild::MemberChild(member_child) => Some(format_ident!("{}", member_child.name())),
|
StructChild::MemberChild(member_child) => Some(format_ident!("{}", member_child.name())),
|
||||||
|
StructChild::Special(special_child) => Some(format_ident!("{}", special_child.name())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,10 +141,6 @@ fn make_member_child_type_ident(member_child: &MemberChild) -> TokenStream {
|
|||||||
MemberChildBuild::Boolean(_) => {
|
MemberChildBuild::Boolean(_) => {
|
||||||
quote! { bool }
|
quote! { bool }
|
||||||
}
|
}
|
||||||
MemberChildBuild::Special(special_member_build) => match special_member_build {
|
|
||||||
SpecialMemberBuild::FileId => quote! { usize },
|
|
||||||
SpecialMemberBuild::Range => quote! { Range<usize> },
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +158,17 @@ fn make_member_child_annotated_member(member_child: &MemberChild) -> TokenStream
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_special_child_annotated_member(special_child: &SpecialChild) -> TokenStream {
|
||||||
|
let child_ident = format_ident!("{}", special_child.name());
|
||||||
|
let child_type_ident = match special_child.kind() {
|
||||||
|
SpecialChildKind::FileId => quote! { usize },
|
||||||
|
SpecialChildKind::Range => quote! { Range<usize> },
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
#child_ident: #child_type_ident
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn make_annotated_member(child: &StructChild) -> Option<TokenStream> {
|
fn make_annotated_member(child: &StructChild) -> Option<TokenStream> {
|
||||||
match child {
|
match child {
|
||||||
StructChild::SkipChild(_) => None,
|
StructChild::SkipChild(_) => None,
|
||||||
@ -163,6 +176,9 @@ fn make_annotated_member(child: &StructChild) -> Option<TokenStream> {
|
|||||||
StructChild::MemberChild(member_child) => {
|
StructChild::MemberChild(member_child) => {
|
||||||
Some(make_member_child_annotated_member(member_child))
|
Some(make_member_child_annotated_member(member_child))
|
||||||
}
|
}
|
||||||
|
StructChild::Special(special_child) => {
|
||||||
|
Some(make_special_child_annotated_member(special_child))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
fn main()
|
fn main()
|
||||||
1 + 2 * 3 + 4
|
let n = 1 + 2 * 3 + 4
|
||||||
|
println n
|
||||||
end
|
end
|
||||||
5
examples/op_prec.dvm_ir
Normal file
5
examples/op_prec.dvm_ir
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
fn main() -> Void
|
||||||
|
$0 = 2 * 3
|
||||||
|
$1 = 1 + $0
|
||||||
|
$2 = $1 + 4
|
||||||
|
call std::core::println($2)
|
||||||
89
examples/worlds.dvm_ir
Normal file
89
examples/worlds.dvm_ir
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
struct World
|
||||||
|
pub String* name
|
||||||
|
pub String* color
|
||||||
|
end
|
||||||
|
|
||||||
|
void World::ctor(World *self, String* name, String* color)
|
||||||
|
self.name = move name
|
||||||
|
self.color = move color
|
||||||
|
end
|
||||||
|
|
||||||
|
const String %s0 = 'Mercury'
|
||||||
|
const String %s1 = 'Red'
|
||||||
|
const String %s2 = 'Earth'
|
||||||
|
const String %s3 = 'Blue'
|
||||||
|
const String %s4 = 'Jupiter'
|
||||||
|
const String %s5 = 'Orange'
|
||||||
|
|
||||||
|
List<World> *getWorlds()
|
||||||
|
List<World> *$0 = alloc std::list::ArrayList
|
||||||
|
call std::list::ArrayList::ctor($0)
|
||||||
|
World *$1 = alloc World
|
||||||
|
call World::ctor($1, %s0, %s1)
|
||||||
|
call std::list::ArrayList::add($0, $1)
|
||||||
|
World *$2 = alloc World
|
||||||
|
call World::ctor($2, %s2, %s3)
|
||||||
|
call std::list::ArrayList::add($0, $2)
|
||||||
|
World *$3 = alloc World
|
||||||
|
call World::ctor($3, %s4, %s5)
|
||||||
|
call std::list::ArrayList::add($0, $3)
|
||||||
|
ret $0
|
||||||
|
end
|
||||||
|
|
||||||
|
struct __findWorldByColor__cl0_captures
|
||||||
|
pub String* color
|
||||||
|
end
|
||||||
|
|
||||||
|
Boolean __findWorldByColor_cl0(__findWorldByColor__cl0_captures *__captures, World *it)
|
||||||
|
String *$0 = it.color
|
||||||
|
String *$1 = __captures.color
|
||||||
|
Boolean $2 = *$0 == *$1
|
||||||
|
ret $2
|
||||||
|
end
|
||||||
|
|
||||||
|
String* __findWorldByColor_cl1(World* it)
|
||||||
|
$0 = it.name
|
||||||
|
ret $0
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
String *findWorldByColor(List<World> *worlds, String *color)
|
||||||
|
__findWorldByColor__cl0_captures *$0 = alloc __findWorldByColor__cl0_captures
|
||||||
|
$0.color = color
|
||||||
|
Closure(__findWorldByColor__cl0_captures*)(World*)<Boolean> $1
|
||||||
|
= closure(__findWorldByColor_cl0, $0)
|
||||||
|
List<World> $2 = call std::list::ArrayList_impl_Find::find(worlds, $1)
|
||||||
|
Closure()(World*)<String*> $3 = closure(__findWorldByColor_cl1)
|
||||||
|
Option<String*> $4 = call std::list::ArrayList_impl_Monad($2, $3)
|
||||||
|
|
||||||
|
Display*[1] $5 = alloc Display[1]
|
||||||
|
$5[0] = color
|
||||||
|
DString *$6 = alloc DString
|
||||||
|
call DString::ctor($6, { }, $5)
|
||||||
|
String *$7 = call DString::toString($6)
|
||||||
|
|
||||||
|
String* $8 = call option::Option::expect($4, $7)
|
||||||
|
|
||||||
|
drop $0
|
||||||
|
drop $1
|
||||||
|
drop $2
|
||||||
|
drop $3
|
||||||
|
drop $5
|
||||||
|
drop $6
|
||||||
|
|
||||||
|
ret $8
|
||||||
|
end
|
||||||
|
|
||||||
|
const String %s7 = 'Blue'
|
||||||
|
const String[2] %sa0 = { 'Hello, ', '!' }
|
||||||
|
|
||||||
|
void main()
|
||||||
|
List<World> *$0 = call getWorlds()
|
||||||
|
World *$1 = call findWorldByColor($0, %s7)
|
||||||
|
Display[1] $2 = alloc Display[1]
|
||||||
|
$2[0] = move $1
|
||||||
|
std::string::DString *$3 = alloc std::string::DString
|
||||||
|
call std::string::DString::ctor($3, %sa0, $2)
|
||||||
|
String *$4 = call std::DString::toString($3)
|
||||||
|
call std::core::println($4)
|
||||||
|
end
|
||||||
@ -5,13 +5,13 @@ use deimos::ast::build::build_ast;
|
|||||||
use deimos::name_analysis::analyze_names;
|
use deimos::name_analysis::analyze_names;
|
||||||
use deimos::name_analysis::symbol_table::SymbolTable;
|
use deimos::name_analysis::symbol_table::SymbolTable;
|
||||||
use deimos::parser::{DeimosParser, Rule};
|
use deimos::parser::{DeimosParser, Rule};
|
||||||
|
use deimos::std_core::add_std_core_symbols;
|
||||||
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![];
|
||||||
let mut files = SimpleFiles::new();
|
let mut files: SimpleFiles<String, String> = SimpleFiles::new();
|
||||||
|
|
||||||
for path in paths {
|
for path in paths {
|
||||||
let src = std::fs::read_to_string(path).unwrap();
|
let src = std::fs::read_to_string(path).unwrap();
|
||||||
@ -31,13 +31,10 @@ 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.");
|
add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols.");
|
||||||
|
|
||||||
let diagnostics = analyze_names(
|
let diagnostics = analyze_names(compilation_units.as_mut_slice(), &files, &mut symbol_table);
|
||||||
compilation_units.as_mut_slice(),
|
|
||||||
&mut symbol_table
|
|
||||||
);
|
|
||||||
if diagnostics.is_empty() {
|
if diagnostics.is_empty() {
|
||||||
println!("Name analysis complete.");
|
println!("Name analysis complete.");
|
||||||
println!("Symbol table\n-------\n{}", symbol_table);
|
println!("{}", symbol_table);
|
||||||
} else {
|
} else {
|
||||||
let writer = StandardStream::stderr(ColorChoice::Always);
|
let writer = StandardStream::stderr(ColorChoice::Always);
|
||||||
let config = term::Config::default();
|
let config = term::Config::default();
|
||||||
|
|||||||
199
src/ir/mod.rs
Normal file
199
src/ir/mod.rs
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
pub enum DvmIr {
|
||||||
|
Struct(Box<DvmIrStruct>),
|
||||||
|
Function(DvmIrFunction),
|
||||||
|
Const(DvmIrConst),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrStruct {
|
||||||
|
name: String,
|
||||||
|
kind: Box<DvmIrKind>,
|
||||||
|
is_public: bool,
|
||||||
|
members: Vec<Box<DvmIrStructMember>>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrStructMember {
|
||||||
|
name: String,
|
||||||
|
kind: Box<DvmIrKind>,
|
||||||
|
is_public: bool,
|
||||||
|
is_mut: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DvmIrKind {
|
||||||
|
Primitive(Box<DvmIrPrimitiveKind>),
|
||||||
|
Struct(Box<DvmIrStructKind>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DvmIrPrimitiveKind {
|
||||||
|
I8,
|
||||||
|
I16,
|
||||||
|
I32,
|
||||||
|
I64,
|
||||||
|
I128,
|
||||||
|
ISize,
|
||||||
|
U8,
|
||||||
|
U16,
|
||||||
|
U32,
|
||||||
|
U64,
|
||||||
|
U128,
|
||||||
|
USize,
|
||||||
|
Boolean,
|
||||||
|
Array(Box<DvmIrKind>),
|
||||||
|
String,
|
||||||
|
Closure(Box<DvmIrClosureKind>),
|
||||||
|
Ref(Box<DvmIrKind>),
|
||||||
|
Void,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrStructKind {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrClosureKind {
|
||||||
|
captures_name: String,
|
||||||
|
parameters: Vec<Box<DvmIrKind>>,
|
||||||
|
return_type: Box<DvmIrKind>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrFunction {
|
||||||
|
name: String,
|
||||||
|
parameters: Vec<Box<DvmIrKind>>,
|
||||||
|
return_type: Box<DvmIrKind>,
|
||||||
|
statements: Vec<Box<DvmIrStatement>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DvmIrStatement {
|
||||||
|
Alloc(DvmIrAlloc),
|
||||||
|
Call(DvmIrCallStmt),
|
||||||
|
Ret(DvmIrRet),
|
||||||
|
Assign(DvmIrAssign),
|
||||||
|
MakeClosure(DvmIrMakeClosure),
|
||||||
|
Drop(DvmIrDrop),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DvmIrAllocable {
|
||||||
|
Struct(Box<DvmIrStructKind>),
|
||||||
|
Array(Box<DvmIrArrayKind>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DvmIrArrayKind {
|
||||||
|
StaticSize(Box<DvmIrStaticArrayKind>),
|
||||||
|
DynamicSize(Box<DvmIrDynamicArrayKind>)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrStaticArrayKind {
|
||||||
|
inner_kind: Box<DvmIrKind>,
|
||||||
|
size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrDynamicArrayKind {
|
||||||
|
inner_kind: Box<DvmIrKind>,
|
||||||
|
size_expr: Box<DvmIrExpr>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrAlloc {
|
||||||
|
declared_kind: Box<DvmIrAllocable>,
|
||||||
|
name: String,
|
||||||
|
kind_to_alloc: Box<DvmIrAllocable>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DvmIrConst {
|
||||||
|
String(DvmIrStringConst),
|
||||||
|
StringArray(DvmIrStringArrayConst),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrStringConst {
|
||||||
|
name: String,
|
||||||
|
value: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrStringArrayConst {
|
||||||
|
name: String,
|
||||||
|
value: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DvmIrExpr {
|
||||||
|
Call(Box<DvmIrCallExpr>),
|
||||||
|
Variable(Box<DvmIrVariable>),
|
||||||
|
ConstRef(Box<DvmIrConstRef>),
|
||||||
|
Literal(Box<DvmIrLiteral>)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrVariable {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrConstRef {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DvmIrLiteral {
|
||||||
|
I8(i8),
|
||||||
|
I16(i16),
|
||||||
|
I32(i32),
|
||||||
|
I64(i64),
|
||||||
|
I128(i128),
|
||||||
|
ISize(isize),
|
||||||
|
U8(u8),
|
||||||
|
U16(u16),
|
||||||
|
U32(u32),
|
||||||
|
U64(u64),
|
||||||
|
U128(u128),
|
||||||
|
USize(usize),
|
||||||
|
Boolean(bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrCallStmt {
|
||||||
|
declared_type: Box<DvmIrKind>,
|
||||||
|
name: String,
|
||||||
|
call_expr: Box<DvmIrCallExpr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrCallExpr {
|
||||||
|
name: String,
|
||||||
|
arguments: Vec<Box<DvmIrExpr>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrAssign {
|
||||||
|
lhs: Box<DvmIrAssignLhs>,
|
||||||
|
rhs: Box<DvmIrExpr>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrAssignLhs {
|
||||||
|
base: Box<DvmIrVariable>,
|
||||||
|
suffixes: Vec<Box<DvmIrAssignLhsSuffix>>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DvmIrAssignLhsSuffix {
|
||||||
|
Index(DvmIrAssignLhsIndex),
|
||||||
|
Property(DvmIrAssignLhsProperty)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrAssignLhsIndex {
|
||||||
|
expr: Box<DvmIrExpr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrAssignLhsProperty {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrRet {
|
||||||
|
value: Box<DvmIrReturnable>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DvmIrReturnable {
|
||||||
|
Variable(DvmIrVariable),
|
||||||
|
Literal(DvmIrLiteral)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrMakeClosure {
|
||||||
|
captures_kind: Option<Box<DvmIrStructKind>>,
|
||||||
|
parameters: Vec<Box<DvmIrKind>>,
|
||||||
|
return_type: Box<DvmIrKind>,
|
||||||
|
name: String,
|
||||||
|
fn_name: String,
|
||||||
|
captures_variable: Box<DvmIrVariable>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrDrop {
|
||||||
|
variable: Box<DvmIrVariable>,
|
||||||
|
}
|
||||||
@ -11,3 +11,4 @@ pub mod parser;
|
|||||||
pub mod std_core;
|
pub mod std_core;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod vm;
|
pub mod vm;
|
||||||
|
pub mod ir;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pub(super) struct FqnContext {
|
pub struct FqnContext {
|
||||||
stack: Vec<String>,
|
stack: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,62 +1,76 @@
|
|||||||
use crate::ast::ast_node::{AstNode, AstNodeRef};
|
use crate::ast::ast_node::{AstNode, AstNodeRef};
|
||||||
use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix};
|
use crate::ast::node::{
|
||||||
|
Class, CompilationUnit, Function, FunctionBlockBody, FunctionBody, Identifier, Interface,
|
||||||
|
Module, Namespace, Statement, UseStatement, UseStatementSuffix, VariableDeclaration,
|
||||||
|
};
|
||||||
use crate::diagnostic::DmDiagnostic;
|
use crate::diagnostic::DmDiagnostic;
|
||||||
|
use crate::name_analysis::fqn_context::FqnContext;
|
||||||
|
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
|
||||||
|
use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
|
||||||
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||||
use crate::name_analysis::symbol::use_symbol::StarUseStatementSymbol;
|
use crate::name_analysis::symbol::type_symbol::{
|
||||||
use crate::name_analysis::symbol::UseStatementSymbol;
|
ConcreteTypeSymbol, ConcreteTypeSymbolKind, TypeSymbol,
|
||||||
use crate::name_analysis::symbol_table::SymbolTable;
|
};
|
||||||
use std::collections::HashMap;
|
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
|
||||||
|
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
|
||||||
|
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable};
|
||||||
|
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||||
|
use std::range::Range;
|
||||||
|
|
||||||
fn gather_identifier(
|
fn handle_insert_error(
|
||||||
identifier: &Identifier,
|
err: SymbolInsertError,
|
||||||
symbol_table: &SymbolTable,
|
error_symbol_name: &str,
|
||||||
identifier_scope_ids: &mut HashMap<Identifier, usize>,
|
error_file_id: usize,
|
||||||
) {
|
error_range: Range<usize>,
|
||||||
identifier_scope_ids.insert(identifier.clone(), symbol_table.current_scope_id());
|
symbol_types: &str,
|
||||||
}
|
|
||||||
|
|
||||||
fn gather_use_statement(
|
|
||||||
use_statement: &UseStatement,
|
|
||||||
symbol_table: &mut SymbolTable,
|
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
) {
|
) {
|
||||||
let mut fully_qualified_name = String::new();
|
match err {
|
||||||
for prefix in use_statement.prefixes() {
|
SymbolInsertError::SymbolAlreadyDefined(s) => {
|
||||||
fully_qualified_name.push_str(&format!("{}::", prefix.identifier().name()));
|
let mut diagnostic = Diagnostic::error()
|
||||||
}
|
.with_message(format!(
|
||||||
match use_statement.suffix() {
|
"{} symbol '{}' already defined in the current scope.",
|
||||||
UseStatementSuffix::Identifier(identifier) => {}
|
symbol_types, error_symbol_name,
|
||||||
UseStatementSuffix::Star => {
|
))
|
||||||
let symbol_inner = StarUseStatementSymbol::new(
|
.with_label(
|
||||||
&fully_qualified_name,
|
Label::primary(error_file_id, error_range)
|
||||||
Some(SourceDefinition::from_use_statement(use_statement)),
|
.with_message("Symbol duplicated here."),
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(source_definition) = s.definition() {
|
||||||
|
diagnostic = diagnostic.with_label(
|
||||||
|
Label::secondary(source_definition.file_id(), source_definition.range())
|
||||||
|
.with_message("Symbol defined here."),
|
||||||
);
|
);
|
||||||
let symbol = UseStatementSymbol::Star(symbol_inner);
|
|
||||||
symbol_table.insert_use_statement_symbol(symbol);
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
UseStatementSuffix::UseList(use_list) => {}
|
|
||||||
|
diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gather_node_children(
|
fn gather_node_children(
|
||||||
node: &impl AstNode,
|
node: &impl AstNode,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
) {
|
) {
|
||||||
for child in node.children() {
|
for child in node.children() {
|
||||||
gather_node(child, symbol_table, diagnostics);
|
gather_node(child, symbol_table, fqn_context, diagnostics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gather_node(
|
fn gather_node(
|
||||||
node: AstNodeRef,
|
node: AstNodeRef,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
) {
|
) {
|
||||||
match node {
|
match node {
|
||||||
AstNodeRef::Operator(_) => {}
|
AstNodeRef::Operator(_) => {}
|
||||||
AstNodeRef::Identifier(_) => {}
|
AstNodeRef::Identifier(_) => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
AstNodeRef::FullyQualifiedName(_) => {}
|
AstNodeRef::FullyQualifiedName(_) => {}
|
||||||
AstNodeRef::TypeUseList(_) => {}
|
AstNodeRef::TypeUseList(_) => {}
|
||||||
AstNodeRef::IdentifierList(_) => {}
|
AstNodeRef::IdentifierList(_) => {}
|
||||||
@ -75,36 +89,114 @@ fn gather_node(
|
|||||||
AstNodeRef::Parameter(_) => {}
|
AstNodeRef::Parameter(_) => {}
|
||||||
AstNodeRef::ReturnType(_) => {}
|
AstNodeRef::ReturnType(_) => {}
|
||||||
AstNodeRef::CompilationUnit(compilation_unit) => {
|
AstNodeRef::CompilationUnit(compilation_unit) => {
|
||||||
gather_node_children(compilation_unit, symbol_table, diagnostics);
|
gather_node_children(compilation_unit, symbol_table, fqn_context, diagnostics);
|
||||||
|
}
|
||||||
|
AstNodeRef::Namespace(namespace) => {
|
||||||
|
gather_namespace(namespace, fqn_context);
|
||||||
}
|
}
|
||||||
AstNodeRef::ParentMod(_) => {}
|
|
||||||
AstNodeRef::UseStatement(use_statement) => {
|
AstNodeRef::UseStatement(use_statement) => {
|
||||||
gather_use_statement(use_statement, symbol_table, diagnostics);
|
gather_use_statement(use_statement, symbol_table, diagnostics);
|
||||||
}
|
}
|
||||||
AstNodeRef::UseStatementPrefix(_) => {}
|
AstNodeRef::UseStatementPrefix(_) => {
|
||||||
AstNodeRef::UseStatementSuffix(_) => {}
|
unreachable!()
|
||||||
AstNodeRef::UseList(_) => {}
|
}
|
||||||
AstNodeRef::ModuleLevelDeclaration(_) => {}
|
AstNodeRef::UseStatementSuffix(_) => {
|
||||||
AstNodeRef::InterfaceLevelDeclaration(_) => {}
|
unreachable!()
|
||||||
AstNodeRef::ClassLevelDeclaration(_) => {}
|
}
|
||||||
AstNodeRef::Module(_) => {}
|
AstNodeRef::UseList(_) => {
|
||||||
AstNodeRef::CompanionModule(_) => {}
|
unreachable!()
|
||||||
AstNodeRef::Interface(_) => {}
|
}
|
||||||
AstNodeRef::Class(_) => {}
|
AstNodeRef::ModuleLevelDeclaration(module_level_declaration) => {
|
||||||
AstNodeRef::Function(_) => {}
|
gather_node_children(
|
||||||
|
module_level_declaration,
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
AstNodeRef::InterfaceLevelDeclaration(interface_level_declaration) => {
|
||||||
|
gather_node_children(
|
||||||
|
interface_level_declaration,
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
AstNodeRef::ClassLevelDeclaration(class_level_declaration) => {
|
||||||
|
gather_node_children(
|
||||||
|
class_level_declaration,
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
AstNodeRef::Module(module) => {
|
||||||
|
gather_module(module, symbol_table, fqn_context, diagnostics);
|
||||||
|
}
|
||||||
|
AstNodeRef::Interface(interface) => {
|
||||||
|
gather_interface(interface, symbol_table, fqn_context, diagnostics);
|
||||||
|
}
|
||||||
|
AstNodeRef::Class(class) => {
|
||||||
|
gather_class(class, symbol_table, fqn_context, diagnostics);
|
||||||
|
}
|
||||||
|
AstNodeRef::Function(function) => {
|
||||||
|
gather_function(function, symbol_table, fqn_context, diagnostics);
|
||||||
|
}
|
||||||
AstNodeRef::OperatorFunction(_) => {}
|
AstNodeRef::OperatorFunction(_) => {}
|
||||||
AstNodeRef::PlatformFunction(_) => {}
|
AstNodeRef::PlatformFunction(_) => {}
|
||||||
AstNodeRef::InterfaceFunction(_) => {}
|
AstNodeRef::InterfaceFunction(_) => {}
|
||||||
AstNodeRef::InterfaceDefaultFunction(_) => {}
|
AstNodeRef::InterfaceDefaultFunction(_) => {}
|
||||||
AstNodeRef::InterfaceOperatorFunction(_) => {}
|
AstNodeRef::InterfaceOperatorFunction(_) => {}
|
||||||
AstNodeRef::InterfaceDefaultOperatorFunction(_) => {}
|
AstNodeRef::InterfaceDefaultOperatorFunction(_) => {}
|
||||||
AstNodeRef::FunctionBody(_) => {}
|
AstNodeRef::FunctionBody(function_body) => match function_body {
|
||||||
|
FunctionBody::FunctionAliasBody(alias_body) => {
|
||||||
|
gather_node(
|
||||||
|
alias_body.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
FunctionBody::FunctionEqualsBody(equals_body) => {
|
||||||
|
gather_node(
|
||||||
|
equals_body.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
FunctionBody::FunctionBlockBody(block_body) => {
|
||||||
|
gather_node(
|
||||||
|
block_body.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
AstNodeRef::FunctionEqualsBody(_) => {}
|
AstNodeRef::FunctionEqualsBody(_) => {}
|
||||||
AstNodeRef::FunctionAliasBody(_) => {}
|
AstNodeRef::FunctionAliasBody(_) => {}
|
||||||
AstNodeRef::FunctionBlockBody(_) => {}
|
AstNodeRef::FunctionBlockBody(block_body) => {
|
||||||
|
gather_function_block_body(block_body, symbol_table, fqn_context, diagnostics);
|
||||||
|
}
|
||||||
AstNodeRef::ClassConstructor(_) => {}
|
AstNodeRef::ClassConstructor(_) => {}
|
||||||
AstNodeRef::Member(_) => {}
|
AstNodeRef::Member(_) => {}
|
||||||
AstNodeRef::Statement(_) => {}
|
AstNodeRef::Statement(statement) => match statement {
|
||||||
|
Statement::VariableDeclaration(variable_declaration) => {
|
||||||
|
gather_node(
|
||||||
|
variable_declaration.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Statement::AssignmentStatement(_) => {}
|
||||||
|
Statement::ExpressionStatement(_) => {}
|
||||||
|
Statement::UseStatement(_) => {}
|
||||||
|
Statement::IfStatement(_) => {}
|
||||||
|
Statement::WhileStatement(_) => {}
|
||||||
|
Statement::ForStatement(_) => {}
|
||||||
|
},
|
||||||
AstNodeRef::VariableDeclaration(_) => {}
|
AstNodeRef::VariableDeclaration(_) => {}
|
||||||
AstNodeRef::AssignmentStatement(_) => {}
|
AstNodeRef::AssignmentStatement(_) => {}
|
||||||
AstNodeRef::ExpressionStatement(_) => {}
|
AstNodeRef::ExpressionStatement(_) => {}
|
||||||
@ -157,9 +249,284 @@ fn gather_node(
|
|||||||
|
|
||||||
pub fn gather_compilation_unit(
|
pub fn gather_compilation_unit(
|
||||||
compilation_unit: &mut CompilationUnit,
|
compilation_unit: &mut CompilationUnit,
|
||||||
|
file_name: &str,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
identifier_scope_ids: &mut HashMap<Identifier, usize>,
|
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
) {
|
) {
|
||||||
gather_node(compilation_unit.as_node_ref(), symbol_table, diagnostics);
|
let mut fqn_context = FqnContext::new();
|
||||||
|
symbol_table.push_scope(&format!("FileScope {}", file_name));
|
||||||
|
gather_node(
|
||||||
|
compilation_unit.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
&mut fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
symbol_table.pop_scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_namespace(namespace: &Namespace, fqn_context: &mut FqnContext) {
|
||||||
|
for identifier in namespace.fqn().identifiers() {
|
||||||
|
fqn_context.push(identifier.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_use_statement(
|
||||||
|
use_statement: &UseStatement,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
let base_fqn = use_statement
|
||||||
|
.prefixes()
|
||||||
|
.map(|prefix| prefix.identifier().name())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("::");
|
||||||
|
|
||||||
|
match use_statement.suffix() {
|
||||||
|
UseStatementSuffix::Identifier(identifier) => {
|
||||||
|
gather_concrete_use_symbol(&base_fqn, identifier, symbol_table, diagnostics);
|
||||||
|
}
|
||||||
|
UseStatementSuffix::Star => {
|
||||||
|
let symbol = StarUseSymbol::new(
|
||||||
|
&base_fqn,
|
||||||
|
Some(SourceDefinition::from_use_statement(use_statement)),
|
||||||
|
);
|
||||||
|
let insert_result = symbol_table.insert_star_use_symbol(symbol);
|
||||||
|
if let Err(error) = insert_result {
|
||||||
|
handle_insert_error(
|
||||||
|
error,
|
||||||
|
&base_fqn,
|
||||||
|
use_statement.file_id(),
|
||||||
|
use_statement.range(),
|
||||||
|
"Use Statement",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UseStatementSuffix::UseList(use_list) => {
|
||||||
|
for identifier in use_list.identifiers() {
|
||||||
|
gather_concrete_use_symbol(&base_fqn, identifier, symbol_table, diagnostics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_concrete_use_symbol(
|
||||||
|
base_fqn: &str,
|
||||||
|
identifier: &Identifier,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
let symbol = ConcreteUseSymbol::new(
|
||||||
|
base_fqn,
|
||||||
|
identifier.name(),
|
||||||
|
Some(SourceDefinition::from_identifier(identifier)),
|
||||||
|
);
|
||||||
|
if let Err(insert_error) = symbol_table.insert_concrete_use_symbol(symbol) {
|
||||||
|
handle_insert_error(
|
||||||
|
insert_error,
|
||||||
|
&base_fqn,
|
||||||
|
identifier.file_id(),
|
||||||
|
identifier.range(),
|
||||||
|
"Use Statement",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_module(
|
||||||
|
module: &Module,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
let module_symbol = ModuleSymbol::new(
|
||||||
|
&fqn_context.resolve(module.identifier().name()),
|
||||||
|
module.identifier().name(),
|
||||||
|
module.is_public(),
|
||||||
|
Some(SourceDefinition::from_identifier(module.identifier())),
|
||||||
|
);
|
||||||
|
if let Err(symbol_insert_error) = symbol_table.insert_module_symbol(module_symbol) {
|
||||||
|
handle_insert_error(
|
||||||
|
symbol_insert_error,
|
||||||
|
module.identifier().name(),
|
||||||
|
module.identifier().file_id(),
|
||||||
|
module.identifier().range(),
|
||||||
|
"Module",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fqn_context.push(module.identifier().name());
|
||||||
|
symbol_table.push_scope(&format!("ModuleScope {}", module.identifier().name()));
|
||||||
|
|
||||||
|
for declaration in module.declarations() {
|
||||||
|
gather_node(
|
||||||
|
declaration.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol_table.pop_scope();
|
||||||
|
fqn_context.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_interface(
|
||||||
|
interface: &Interface,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
let type_symbol = ConcreteTypeSymbol::new(
|
||||||
|
&fqn_context.resolve(interface.identifier().name()),
|
||||||
|
interface.identifier().name(),
|
||||||
|
interface.is_public(),
|
||||||
|
ConcreteTypeSymbolKind::Interface,
|
||||||
|
Some(SourceDefinition::from_identifier(interface.identifier())),
|
||||||
|
);
|
||||||
|
if let Err(symbol_insert_error) =
|
||||||
|
symbol_table.insert_type_symbol(TypeSymbol::Concrete(type_symbol))
|
||||||
|
{
|
||||||
|
handle_insert_error(
|
||||||
|
symbol_insert_error,
|
||||||
|
interface.identifier().name(),
|
||||||
|
interface.identifier().file_id(),
|
||||||
|
interface.identifier().range(),
|
||||||
|
"Interface",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fqn_context.push(interface.identifier().name());
|
||||||
|
symbol_table.push_scope(&format!("InterfaceScope {}", interface.identifier().name()));
|
||||||
|
|
||||||
|
for declaration in interface.declarations() {
|
||||||
|
gather_node(
|
||||||
|
declaration.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol_table.pop_scope();
|
||||||
|
fqn_context.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_class(
|
||||||
|
class: &Class,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
let class_symbol = ConcreteTypeSymbol::new(
|
||||||
|
&fqn_context.resolve(class.identifier().name()),
|
||||||
|
class.identifier().name(),
|
||||||
|
class.is_public(),
|
||||||
|
ConcreteTypeSymbolKind::Class,
|
||||||
|
Some(SourceDefinition::from_identifier(class.identifier())),
|
||||||
|
);
|
||||||
|
if let Err(symbol_insert_error) =
|
||||||
|
symbol_table.insert_type_symbol(TypeSymbol::Concrete(class_symbol))
|
||||||
|
{
|
||||||
|
handle_insert_error(
|
||||||
|
symbol_insert_error,
|
||||||
|
class.identifier().name(),
|
||||||
|
class.identifier().file_id(),
|
||||||
|
class.identifier().range(),
|
||||||
|
"Class",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fqn_context.push(class.identifier().name());
|
||||||
|
symbol_table.push_scope(&format!("ClassScope {}", class.identifier().name()));
|
||||||
|
|
||||||
|
for declaration in class.class_level_declarations() {
|
||||||
|
gather_node(
|
||||||
|
declaration.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol_table.pop_scope();
|
||||||
|
fqn_context.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_function(
|
||||||
|
function: &Function,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
|
||||||
|
&fqn_context.resolve(function.identifier().name()),
|
||||||
|
function.identifier().name(),
|
||||||
|
function.is_public(),
|
||||||
|
false,
|
||||||
|
Some(SourceDefinition::from_identifier(function.identifier())),
|
||||||
|
);
|
||||||
|
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
|
||||||
|
handle_insert_error(
|
||||||
|
insert_error,
|
||||||
|
function.identifier().name(),
|
||||||
|
function.identifier().file_id(),
|
||||||
|
function.identifier().range(),
|
||||||
|
"Function",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
gather_node(
|
||||||
|
function.function_body().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_function_block_body(
|
||||||
|
function_block_body: &FunctionBlockBody,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
symbol_table.push_scope("FunctionBlockBody");
|
||||||
|
gather_node_children(function_block_body, symbol_table, fqn_context, diagnostics);
|
||||||
|
symbol_table.pop_scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_variable_declaration(
|
||||||
|
variable_declaration: &VariableDeclaration,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
let variable_symbol = VariableSymbol::new(
|
||||||
|
variable_declaration.identifier().name(),
|
||||||
|
variable_declaration.is_mut(),
|
||||||
|
Some(SourceDefinition::from_identifier(
|
||||||
|
variable_declaration.identifier(),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
if let Err(insert_error) = symbol_table.insert_variable_symbol(variable_symbol) {
|
||||||
|
handle_insert_error(
|
||||||
|
insert_error,
|
||||||
|
variable_declaration.identifier().name(),
|
||||||
|
variable_declaration.identifier().file_id(),
|
||||||
|
variable_declaration.identifier().range(),
|
||||||
|
"Variable",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let Some(expression) = variable_declaration.expression() {
|
||||||
|
gather_node(
|
||||||
|
expression.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,16 +24,18 @@ use crate::diagnostic::DmDiagnostic;
|
|||||||
use crate::name_analysis::gather::gather_compilation_unit;
|
use crate::name_analysis::gather::gather_compilation_unit;
|
||||||
// use crate::name_analysis::resolve::resolve_compilation_unit;
|
// use crate::name_analysis::resolve::resolve_compilation_unit;
|
||||||
use crate::name_analysis::symbol_table::SymbolTable;
|
use crate::name_analysis::symbol_table::SymbolTable;
|
||||||
|
use codespan_reporting::files::Files;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
mod fqn_context;
|
pub(self) mod fqn_context;
|
||||||
mod gather;
|
mod gather;
|
||||||
// mod resolve;
|
// mod resolve;
|
||||||
pub mod symbol;
|
pub mod symbol;
|
||||||
pub mod symbol_table;
|
pub mod symbol_table;
|
||||||
|
|
||||||
pub fn analyze_names(
|
pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>(
|
||||||
compilation_units: &mut [Box<CompilationUnit>],
|
compilation_units: &mut [Box<CompilationUnit>],
|
||||||
|
files: &'a F,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
) -> Vec<DmDiagnostic> {
|
) -> Vec<DmDiagnostic> {
|
||||||
let mut diagnostics = vec![];
|
let mut diagnostics = vec![];
|
||||||
@ -41,12 +43,8 @@ pub fn analyze_names(
|
|||||||
|
|
||||||
// gather symbols
|
// gather symbols
|
||||||
for compilation_unit in compilation_units.iter_mut() {
|
for compilation_unit in compilation_units.iter_mut() {
|
||||||
gather_compilation_unit(
|
let file_name = files.name(compilation_unit.file_id()).unwrap();
|
||||||
compilation_unit,
|
gather_compilation_unit(compilation_unit, &file_name, symbol_table, &mut diagnostics);
|
||||||
symbol_table,
|
|
||||||
&mut identifier_scope_ids,
|
|
||||||
&mut diagnostics,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve symbols
|
// resolve symbols
|
||||||
|
|||||||
45
src/name_analysis/symbol/class_member_symbol.rs
Normal file
45
src/name_analysis/symbol/class_member_symbol.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ClassMemberSymbol {
|
||||||
|
declared_name: String,
|
||||||
|
is_field: bool,
|
||||||
|
source_definition: Option<SourceDefinition>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClassMemberSymbol {
|
||||||
|
pub fn new(
|
||||||
|
declared_name: &str,
|
||||||
|
is_field: bool,
|
||||||
|
source_definition: Option<SourceDefinition>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
declared_name: declared_name.to_string(),
|
||||||
|
is_field,
|
||||||
|
source_definition,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declared_name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_field(&self) -> bool {
|
||||||
|
self.is_field
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source_definition(&self) -> Option<&SourceDefinition> {
|
||||||
|
self.source_definition.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for ClassMemberSymbol {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("ClassMemberSymbol")
|
||||||
|
.field("declared_name", &self.declared_name)
|
||||||
|
.field("is_field", &self.is_field)
|
||||||
|
.field("source_definition", &self.source_definition)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
101
src/name_analysis/symbol/function_symbol.rs
Normal file
101
src/name_analysis/symbol/function_symbol.rs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
|
||||||
|
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||||
|
use crate::name_analysis::symbol::type_symbol::ConcreteTypeSymbol;
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct FunctionSymbol {
|
||||||
|
fqn: String,
|
||||||
|
declared_name: String,
|
||||||
|
is_public: bool,
|
||||||
|
is_platform: bool,
|
||||||
|
source_definition: Option<SourceDefinition>,
|
||||||
|
parameters: Vec<ParameterSymbol>,
|
||||||
|
return_type: Option<ConcreteTypeSymbol>, // todo: can we use TypeSymbol?
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FunctionSymbol {
|
||||||
|
pub fn without_parameters_or_return_type(
|
||||||
|
fqn: &str,
|
||||||
|
declared_name: &str,
|
||||||
|
is_public: bool,
|
||||||
|
is_platform: bool,
|
||||||
|
source_definition: Option<SourceDefinition>,
|
||||||
|
) -> FunctionSymbol {
|
||||||
|
FunctionSymbol {
|
||||||
|
fqn: fqn.to_string(),
|
||||||
|
declared_name: declared_name.to_string(),
|
||||||
|
is_public,
|
||||||
|
is_platform,
|
||||||
|
source_definition,
|
||||||
|
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,
|
||||||
|
source_definition: self.source_definition,
|
||||||
|
parameters,
|
||||||
|
return_type: self.return_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_return_type(self, return_type: ConcreteTypeSymbol) -> Self {
|
||||||
|
Self {
|
||||||
|
fqn: self.fqn,
|
||||||
|
declared_name: self.declared_name,
|
||||||
|
is_public: self.is_public,
|
||||||
|
is_platform: self.is_platform,
|
||||||
|
source_definition: self.source_definition,
|
||||||
|
parameters: self.parameters,
|
||||||
|
return_type: Some(return_type),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fqn(&self) -> &str {
|
||||||
|
&self.fqn
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declared_name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_public(&self) -> bool {
|
||||||
|
self.is_public
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_platform(&self) -> bool {
|
||||||
|
self.is_platform
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source_definition(&self) -> Option<&SourceDefinition> {
|
||||||
|
self.source_definition.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parameters(&self) -> &[ParameterSymbol] {
|
||||||
|
&self.parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn return_type(&self) -> Option<&ConcreteTypeSymbol> {
|
||||||
|
self.return_type.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for FunctionSymbol {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("FunctionSymbol")
|
||||||
|
.field("fqn", &self.fqn)
|
||||||
|
.field("declared_name", &self.declared_name)
|
||||||
|
.field("is_public", &self.is_public)
|
||||||
|
.field("is_platform", &self.is_platform)
|
||||||
|
.field("parameters", &self.parameters)
|
||||||
|
.field("return_type", &self.return_type)
|
||||||
|
.field("source_definition", &self.source_definition)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,445 +1,46 @@
|
|||||||
pub(super) mod source_definition;
|
pub(crate) mod class_member_symbol;
|
||||||
pub(super) mod use_symbol;
|
pub(crate) mod function_symbol;
|
||||||
|
pub(crate) mod module_symbol;
|
||||||
|
pub(crate) mod parameter_symbol;
|
||||||
|
pub(crate) mod source_definition;
|
||||||
|
pub(crate) mod type_symbol;
|
||||||
|
pub(crate) mod use_symbol;
|
||||||
|
pub(crate) mod variable_symbol;
|
||||||
|
|
||||||
use crate::ast::node::Identifier;
|
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
|
||||||
|
use class_member_symbol::ClassMemberSymbol;
|
||||||
|
use function_symbol::FunctionSymbol;
|
||||||
|
use module_symbol::ModuleSymbol;
|
||||||
|
use parameter_symbol::ParameterSymbol;
|
||||||
use source_definition::SourceDefinition;
|
use source_definition::SourceDefinition;
|
||||||
use std::cell::RefCell;
|
use std::fmt::{Debug, Display};
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use type_symbol::TypeSymbol;
|
||||||
|
use variable_symbol::VariableSymbol;
|
||||||
pub trait SymbolInner {
|
|
||||||
fn declared_name(&self) -> &str;
|
|
||||||
fn definition(&self) -> Option<SourceDefinition>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Symbol */
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Symbol {
|
pub enum Symbol {
|
||||||
UseStatement(Rc<RefCell<UseStatementSymbol>>),
|
ConcreteUse(ConcreteUseSymbol),
|
||||||
Module(Rc<ModuleSymbol>),
|
StarUse(StarUseSymbol),
|
||||||
Type(Rc<TypeSymbol>),
|
Module(ModuleSymbol),
|
||||||
Function(Rc<RefCell<FunctionSymbol>>),
|
Type(TypeSymbol),
|
||||||
Parameter(Rc<ParameterSymbol>),
|
Function(FunctionSymbol),
|
||||||
Variable(Rc<VariableSymbol>),
|
Parameter(ParameterSymbol),
|
||||||
ClassMember(Rc<ClassMemberSymbol>),
|
Variable(VariableSymbol),
|
||||||
|
ClassMember(ClassMemberSymbol),
|
||||||
}
|
}
|
||||||
|
|
||||||
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::ConcreteUse(concrete) => concrete.source_definition(),
|
||||||
Symbol::Module(s) => s.definition(),
|
Symbol::StarUse(star) => star.source_definition(),
|
||||||
Symbol::Type(s) => match s.deref() {
|
Symbol::Module(module) => module.source_definition(),
|
||||||
TypeSymbol::Concrete(cts) => cts.definition(),
|
Symbol::Type(type_symbol) => type_symbol.source_definition(),
|
||||||
TypeSymbol::Generic(gts) => gts.definition(),
|
Symbol::Function(function_symbol) => function_symbol.source_definition(),
|
||||||
},
|
Symbol::Parameter(parameter_symbol) => parameter_symbol.source_definition(),
|
||||||
Symbol::Function(s) => s.borrow().definition(),
|
Symbol::Variable(variable_symbol) => variable_symbol.source_definition(),
|
||||||
Symbol::Parameter(s) => s.definition(),
|
Symbol::ClassMember(class_member_symbol) => class_member_symbol.source_definition(),
|
||||||
Symbol::Variable(s) => s.definition(),
|
|
||||||
Symbol::ClassMember(s) => s.definition(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unwrap_use_statement_symbol(&self) -> Rc<RefCell<UseStatementSymbol>> {
|
|
||||||
match self {
|
|
||||||
Symbol::UseStatement(s) => s.clone(),
|
|
||||||
_ => panic!("unwrap_use_statement_symbol called on non-use statement symbol"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use-statement */
|
|
||||||
|
|
||||||
pub struct UseStatementSymbol {
|
|
||||||
pub fqn: String,
|
|
||||||
pub declared_name: String,
|
|
||||||
definition: Option<SourceDefinition>,
|
|
||||||
referenced_symbol: Option<Box<Symbol>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UseStatementSymbol {
|
|
||||||
pub fn new(fqn: &str, declared_name: &str, identifier: Option<&Identifier>) -> Self {
|
|
||||||
UseStatementSymbol {
|
|
||||||
fqn: fqn.to_string(),
|
|
||||||
declared_name: declared_name.to_string(),
|
|
||||||
definition: identifier.map(SourceDefinition::from_identifier),
|
|
||||||
referenced_symbol: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_referenced_symbol(&mut self, referenced_symbol: Symbol) {
|
|
||||||
self.referenced_symbol = Some(Box::new(referenced_symbol));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn referenced_symbol(&self) -> Option<Box<Symbol>> {
|
|
||||||
self.referenced_symbol.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SymbolInner for UseStatementSymbol {
|
|
||||||
fn declared_name(&self) -> &str {
|
|
||||||
&self.declared_name
|
|
||||||
}
|
|
||||||
|
|
||||||
fn definition(&self) -> Option<SourceDefinition> {
|
|
||||||
self.definition.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for UseStatementSymbol {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("UseStatementSymbol")
|
|
||||||
.field("fqn", &self.fqn)
|
|
||||||
.field("declared_name", &self.declared_name)
|
|
||||||
.field("referenced_symbol", &self.referenced_symbol)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Module */
|
|
||||||
|
|
||||||
pub struct ModuleSymbol {
|
|
||||||
fqn: String,
|
|
||||||
declared_name: String,
|
|
||||||
is_public: bool,
|
|
||||||
definition: Option<SourceDefinition>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModuleSymbol {
|
|
||||||
pub fn new(
|
|
||||||
fqn: &str,
|
|
||||||
declared_name: &str,
|
|
||||||
is_public: bool,
|
|
||||||
identifier: Option<&Identifier>,
|
|
||||||
) -> ModuleSymbol {
|
|
||||||
ModuleSymbol {
|
|
||||||
fqn: fqn.to_string(),
|
|
||||||
declared_name: declared_name.to_string(),
|
|
||||||
is_public,
|
|
||||||
definition: identifier.map(SourceDefinition::from_identifier),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SymbolInner for ModuleSymbol {
|
|
||||||
fn declared_name(&self) -> &str {
|
|
||||||
self.declared_name.as_str()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn definition(&self) -> Option<SourceDefinition> {
|
|
||||||
self.definition.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for ModuleSymbol {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("ModuleSymbol")
|
|
||||||
.field("fqn", &self.fqn)
|
|
||||||
.field("declared_name", &self.declared_name)
|
|
||||||
.field("is_public", &self.is_public)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TypeSymbol */
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum TypeSymbol {
|
|
||||||
Concrete(ConcreteTypeSymbol),
|
|
||||||
Generic(GenericTypeSymbol),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TypeSymbol {
|
|
||||||
pub fn declared_name(&self) -> &str {
|
|
||||||
match self {
|
|
||||||
TypeSymbol::Concrete(t) => t.declared_name(),
|
|
||||||
TypeSymbol::Generic(t) => t.declared_name(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ConcreteTypeSymbol {
|
|
||||||
fqn: String,
|
|
||||||
declared_name: String,
|
|
||||||
is_public: bool,
|
|
||||||
definition: Option<SourceDefinition>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConcreteTypeSymbol {
|
|
||||||
pub fn new(
|
|
||||||
fqn: &str,
|
|
||||||
declared_name: &str,
|
|
||||||
is_public: bool,
|
|
||||||
identifier: Option<&Identifier>,
|
|
||||||
) -> Self {
|
|
||||||
ConcreteTypeSymbol {
|
|
||||||
fqn: fqn.to_string(),
|
|
||||||
declared_name: declared_name.to_string(),
|
|
||||||
is_public,
|
|
||||||
definition: identifier.map(SourceDefinition::from_identifier),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fqn(&self) -> &str {
|
|
||||||
&self.fqn
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_public(&self) -> bool {
|
|
||||||
self.is_public
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SymbolInner for ConcreteTypeSymbol {
|
|
||||||
fn declared_name(&self) -> &str {
|
|
||||||
&self.declared_name
|
|
||||||
}
|
|
||||||
|
|
||||||
fn definition(&self) -> Option<SourceDefinition> {
|
|
||||||
self.definition.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for ConcreteTypeSymbol {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("TypeSymbol")
|
|
||||||
.field("fqn", &self.fqn)
|
|
||||||
.field("declared_name", &self.declared_name)
|
|
||||||
.field("is_public", &self.is_public)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct GenericTypeSymbol {
|
|
||||||
declared_name: String,
|
|
||||||
source_definition: SourceDefinition,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GenericTypeSymbol {
|
|
||||||
pub fn new(declared_name: &str, source_definition: SourceDefinition) -> Self {
|
|
||||||
GenericTypeSymbol {
|
|
||||||
declared_name: declared_name.to_string(),
|
|
||||||
source_definition,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SymbolInner for GenericTypeSymbol {
|
|
||||||
fn declared_name(&self) -> &str {
|
|
||||||
self.declared_name.as_str()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn definition(&self) -> Option<SourceDefinition> {
|
|
||||||
Some(self.source_definition.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for GenericTypeSymbol {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("GenericTypeSymbol")
|
|
||||||
.field("declared_name", &self.declared_name)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Function */
|
|
||||||
|
|
||||||
pub struct FunctionSymbol {
|
|
||||||
fqn: String,
|
|
||||||
declared_name: String,
|
|
||||||
is_public: bool,
|
|
||||||
is_platform: bool,
|
|
||||||
definition: Option<SourceDefinition>,
|
|
||||||
parameters: Vec<Rc<ParameterSymbol>>,
|
|
||||||
return_type: Option<Rc<ConcreteTypeSymbol>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FunctionSymbol {
|
|
||||||
pub fn new(
|
|
||||||
fqn: &str,
|
|
||||||
declared_name: &str,
|
|
||||||
is_public: bool,
|
|
||||||
is_platform: bool,
|
|
||||||
identifier: Option<&Identifier>,
|
|
||||||
) -> FunctionSymbol {
|
|
||||||
FunctionSymbol {
|
|
||||||
fqn: fqn.to_string(),
|
|
||||||
declared_name: declared_name.to_string(),
|
|
||||||
is_public,
|
|
||||||
is_platform,
|
|
||||||
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: ConcreteTypeSymbol) -> 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 {
|
|
||||||
&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<ConcreteTypeSymbol>) {
|
|
||||||
self.return_type = Some(return_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SymbolInner for FunctionSymbol {
|
|
||||||
fn declared_name(&self) -> &str {
|
|
||||||
self.declared_name.as_str()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn definition(&self) -> Option<SourceDefinition> {
|
|
||||||
self.definition.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for FunctionSymbol {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("FunctionSymbol")
|
|
||||||
.field("fqn", &self.fqn)
|
|
||||||
.field("declared_name", &self.declared_name)
|
|
||||||
.field("is_public", &self.is_public)
|
|
||||||
.field("is_platform", &self.is_platform)
|
|
||||||
.field("parameters", &self.parameters)
|
|
||||||
.field("return_type", &self.return_type)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parameter */
|
|
||||||
|
|
||||||
pub struct ParameterSymbol {
|
|
||||||
declared_name: String,
|
|
||||||
definition: Option<SourceDefinition>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ParameterSymbol {
|
|
||||||
pub fn new(declared_name: &str, identifier: Option<&Identifier>) -> Self {
|
|
||||||
ParameterSymbol {
|
|
||||||
declared_name: declared_name.to_string(),
|
|
||||||
definition: identifier.map(SourceDefinition::from_identifier),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SymbolInner for ParameterSymbol {
|
|
||||||
fn declared_name(&self) -> &str {
|
|
||||||
&self.declared_name
|
|
||||||
}
|
|
||||||
|
|
||||||
fn definition(&self) -> Option<SourceDefinition> {
|
|
||||||
self.definition.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for ParameterSymbol {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("ParameterSymbol")
|
|
||||||
.field("declared_name", &self.declared_name)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Variable */
|
|
||||||
|
|
||||||
pub struct VariableSymbol {
|
|
||||||
declared_name: String,
|
|
||||||
is_mutable: bool,
|
|
||||||
definition: Option<SourceDefinition>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VariableSymbol {
|
|
||||||
pub fn new(declared_name: &str, is_mutable: bool, identifier: Option<&Identifier>) -> Self {
|
|
||||||
VariableSymbol {
|
|
||||||
declared_name: declared_name.to_string(),
|
|
||||||
is_mutable,
|
|
||||||
definition: identifier.map(SourceDefinition::from_identifier),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SymbolInner for VariableSymbol {
|
|
||||||
fn declared_name(&self) -> &str {
|
|
||||||
self.declared_name.as_str()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn definition(&self) -> Option<SourceDefinition> {
|
|
||||||
self.definition.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for VariableSymbol {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("VariableSymbol")
|
|
||||||
.field("declared_name", &self.declared_name)
|
|
||||||
.field("is_mutable", &self.is_mutable)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Class Member */
|
|
||||||
|
|
||||||
pub struct ClassMemberSymbol {
|
|
||||||
declared_name: String,
|
|
||||||
is_field: bool,
|
|
||||||
definition: Option<SourceDefinition>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClassMemberSymbol {
|
|
||||||
pub fn new(declared_name: &str, is_field: bool, definition: Option<SourceDefinition>) -> Self {
|
|
||||||
ClassMemberSymbol {
|
|
||||||
declared_name: declared_name.to_string(),
|
|
||||||
is_field,
|
|
||||||
definition,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SymbolInner for ClassMemberSymbol {
|
|
||||||
fn declared_name(&self) -> &str {
|
|
||||||
self.declared_name.as_str()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn definition(&self) -> Option<SourceDefinition> {
|
|
||||||
self.definition.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for ClassMemberSymbol {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("ClassMemberSymbol")
|
|
||||||
.field("declared_name", &self.declared_name)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
53
src/name_analysis/symbol/module_symbol.rs
Normal file
53
src/name_analysis/symbol/module_symbol.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ModuleSymbol {
|
||||||
|
fqn: String,
|
||||||
|
declared_name: String,
|
||||||
|
is_public: bool,
|
||||||
|
source_definition: Option<SourceDefinition>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModuleSymbol {
|
||||||
|
pub fn new(
|
||||||
|
fqn: &str,
|
||||||
|
declared_name: &str,
|
||||||
|
is_public: bool,
|
||||||
|
source_definition: Option<SourceDefinition>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
fqn: fqn.to_string(),
|
||||||
|
declared_name: declared_name.to_string(),
|
||||||
|
is_public,
|
||||||
|
source_definition,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fqn(&self) -> &str {
|
||||||
|
&self.fqn
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declared_name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_public(&self) -> bool {
|
||||||
|
self.is_public
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source_definition(&self) -> Option<&SourceDefinition> {
|
||||||
|
self.source_definition.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for ModuleSymbol {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("ModuleSymbol")
|
||||||
|
.field("fqn", &self.fqn)
|
||||||
|
.field("declared_name", &self.declared_name)
|
||||||
|
.field("is_public", &self.is_public)
|
||||||
|
.field("source_definition", &self.source_definition)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
34
src/name_analysis/symbol/parameter_symbol.rs
Normal file
34
src/name_analysis/symbol/parameter_symbol.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ParameterSymbol {
|
||||||
|
declared_name: String,
|
||||||
|
source_definition: Option<SourceDefinition>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ParameterSymbol {
|
||||||
|
pub fn new(declared_name: &str, source_definition: Option<SourceDefinition>) -> Self {
|
||||||
|
ParameterSymbol {
|
||||||
|
declared_name: declared_name.to_string(),
|
||||||
|
source_definition,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declared_name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source_definition(&self) -> Option<&SourceDefinition> {
|
||||||
|
self.source_definition.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for ParameterSymbol {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("ParameterSymbol")
|
||||||
|
.field("declared_name", &self.declared_name)
|
||||||
|
.field("source_definition", &self.source_definition)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
121
src/name_analysis/symbol/type_symbol.rs
Normal file
121
src/name_analysis/symbol/type_symbol.rs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum TypeSymbol {
|
||||||
|
Concrete(ConcreteTypeSymbol),
|
||||||
|
Generic(GenericTypeSymbol),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeSymbol {
|
||||||
|
pub fn declared_name(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
TypeSymbol::Concrete(t) => t.declared_name(),
|
||||||
|
TypeSymbol::Generic(t) => t.declared_name(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source_definition(&self) -> Option<&SourceDefinition> {
|
||||||
|
match self {
|
||||||
|
TypeSymbol::Concrete(t) => t.source_definition(),
|
||||||
|
TypeSymbol::Generic(t) => t.source_definition(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ConcreteTypeSymbol {
|
||||||
|
fqn: String,
|
||||||
|
declared_name: String,
|
||||||
|
is_public: bool,
|
||||||
|
kind: ConcreteTypeSymbolKind,
|
||||||
|
source_definition: Option<SourceDefinition>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConcreteTypeSymbol {
|
||||||
|
pub fn new(
|
||||||
|
fqn: &str,
|
||||||
|
declared_name: &str,
|
||||||
|
is_public: bool,
|
||||||
|
kind: ConcreteTypeSymbolKind,
|
||||||
|
source_definition: Option<SourceDefinition>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
fqn: fqn.to_string(),
|
||||||
|
declared_name: declared_name.to_string(),
|
||||||
|
is_public,
|
||||||
|
kind,
|
||||||
|
source_definition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fqn(&self) -> &str {
|
||||||
|
&self.fqn
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_public(&self) -> bool {
|
||||||
|
self.is_public
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &ConcreteTypeSymbolKind {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declared_name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source_definition(&self) -> Option<&SourceDefinition> {
|
||||||
|
self.source_definition.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for ConcreteTypeSymbol {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("TypeSymbol")
|
||||||
|
.field("fqn", &self.fqn)
|
||||||
|
.field("declared_name", &self.declared_name)
|
||||||
|
.field("is_public", &self.is_public)
|
||||||
|
.field("kind", &self.kind)
|
||||||
|
.field("source_definition", &self.source_definition)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum ConcreteTypeSymbolKind {
|
||||||
|
Interface,
|
||||||
|
Class
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct GenericTypeSymbol {
|
||||||
|
declared_name: String,
|
||||||
|
source_definition: Option<SourceDefinition>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenericTypeSymbol {
|
||||||
|
pub fn new(declared_name: &str, source_definition: Option<SourceDefinition>) -> Self {
|
||||||
|
GenericTypeSymbol {
|
||||||
|
declared_name: declared_name.to_string(),
|
||||||
|
source_definition,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declared_name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source_definition(&self) -> Option<&SourceDefinition> {
|
||||||
|
self.source_definition.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for GenericTypeSymbol {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("GenericTypeSymbol")
|
||||||
|
.field("declared_name", &self.declared_name)
|
||||||
|
.field("source_definition", &self.source_definition)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,16 +1,56 @@
|
|||||||
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
pub enum UseStatementSymbol {
|
#[derive(Clone)]
|
||||||
Concrete,
|
pub struct ConcreteUseSymbol {
|
||||||
Star(StarUseStatementSymbol),
|
base_fqn: String,
|
||||||
|
declared_name: String,
|
||||||
|
source_definition: Option<SourceDefinition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StarUseStatementSymbol {
|
impl ConcreteUseSymbol {
|
||||||
|
pub fn new(
|
||||||
|
base_fqn: &str,
|
||||||
|
declared_name: &str,
|
||||||
|
source_definition: Option<SourceDefinition>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
base_fqn: base_fqn.to_string(),
|
||||||
|
declared_name: declared_name.to_string(),
|
||||||
|
source_definition,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn base_fqn(&self) -> &str {
|
||||||
|
&self.base_fqn
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declared_name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source_definition(&self) -> Option<&SourceDefinition> {
|
||||||
|
self.source_definition.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for ConcreteUseSymbol {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("ConcreteUseStatementSymbol")
|
||||||
|
.field("base_fqn", &self.base_fqn)
|
||||||
|
.field("declared_name", &self.declared_name)
|
||||||
|
.field("source_definition", &self.source_definition)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct StarUseSymbol {
|
||||||
base_fqn: String,
|
base_fqn: String,
|
||||||
source_definition: Option<SourceDefinition>,
|
source_definition: Option<SourceDefinition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StarUseStatementSymbol {
|
impl StarUseSymbol {
|
||||||
pub fn new(base_fqn: &str, source_definition: Option<SourceDefinition>) -> Self {
|
pub fn new(base_fqn: &str, source_definition: Option<SourceDefinition>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
base_fqn: base_fqn.to_string(),
|
base_fqn: base_fqn.to_string(),
|
||||||
@ -26,3 +66,12 @@ impl StarUseStatementSymbol {
|
|||||||
self.source_definition.as_ref()
|
self.source_definition.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Debug for StarUseSymbol {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("StarUseStatementSymbol")
|
||||||
|
.field("base_fqn", &self.base_fqn)
|
||||||
|
.field("source_definition", &self.source_definition)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
41
src/name_analysis/symbol/variable_symbol.rs
Normal file
41
src/name_analysis/symbol/variable_symbol.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct VariableSymbol {
|
||||||
|
declared_name: String,
|
||||||
|
is_mutable: bool,
|
||||||
|
source_definition: Option<SourceDefinition>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VariableSymbol {
|
||||||
|
pub fn new(declared_name: &str, is_mutable: bool, source_definition: Option<SourceDefinition>) -> Self {
|
||||||
|
VariableSymbol {
|
||||||
|
declared_name: declared_name.to_string(),
|
||||||
|
is_mutable,
|
||||||
|
source_definition,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declared_name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_mutable(&self) -> bool {
|
||||||
|
self.is_mutable
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source_definition(&self) -> Option<&SourceDefinition> {
|
||||||
|
self.source_definition.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for VariableSymbol {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("VariableSymbol")
|
||||||
|
.field("declared_name", &self.declared_name)
|
||||||
|
.field("is_mutable", &self.is_mutable)
|
||||||
|
.field("source_definition", &self.source_definition)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,468 +0,0 @@
|
|||||||
use crate::name_analysis::symbol::*;
|
|
||||||
use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined;
|
|
||||||
use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::fmt::Display;
|
|
||||||
use std::ops::Deref;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
/* Scope */
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Scope {
|
|
||||||
parent: Option<usize>,
|
|
||||||
use_statement_symbols: HashMap<String, Rc<RefCell<UseStatementSymbol>>>,
|
|
||||||
module_symbols: HashMap<String, Rc<ModuleSymbol>>,
|
|
||||||
type_symbols: HashMap<String, Rc<TypeSymbol>>,
|
|
||||||
function_symbols: HashMap<String, Rc<RefCell<FunctionSymbol>>>,
|
|
||||||
parameter_symbols: HashMap<String, Rc<ParameterSymbol>>,
|
|
||||||
variable_symbols: HashMap<String, Rc<VariableSymbol>>,
|
|
||||||
class_member_symbols: HashMap<String, Rc<ClassMemberSymbol>>,
|
|
||||||
debug_name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Scope {
|
|
||||||
pub fn new(parent: Option<usize>, debug_name: String) -> Scope {
|
|
||||||
Scope {
|
|
||||||
parent,
|
|
||||||
use_statement_symbols: HashMap::new(),
|
|
||||||
module_symbols: HashMap::new(),
|
|
||||||
type_symbols: HashMap::new(),
|
|
||||||
function_symbols: HashMap::new(),
|
|
||||||
parameter_symbols: HashMap::new(),
|
|
||||||
variable_symbols: HashMap::new(),
|
|
||||||
class_member_symbols: HashMap::new(),
|
|
||||||
debug_name,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_module_symbol_by_declared_name(&self, name: &str) -> Option<Rc<ModuleSymbol>> {
|
|
||||||
for module_symbol in self.module_symbols.values() {
|
|
||||||
if module_symbol.declared_name() == name {
|
|
||||||
return Some(module_symbol.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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| match s.deref().deref() {
|
|
||||||
TypeSymbol::Concrete(cts) => cts.fqn() == fqn,
|
|
||||||
_ => false,
|
|
||||||
})
|
|
||||||
.cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_usable_symbol_by_fqn(&self, fqn: &str) -> Option<Symbol> {
|
|
||||||
for function_symbol in self.function_symbols.values() {
|
|
||||||
if function_symbol.borrow().fqn() == fqn {
|
|
||||||
return Some(Symbol::Function(function_symbol.clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for type_symbol in self.type_symbols.values() {
|
|
||||||
match type_symbol.deref() {
|
|
||||||
TypeSymbol::Concrete(concrete_type_symbol) => {
|
|
||||||
if concrete_type_symbol.fqn() == fqn {
|
|
||||||
return Some(Symbol::Type(type_symbol.clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => continue,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_usable_symbol_by_declared_name(&self, declared_name: &str) -> Option<Symbol> {
|
|
||||||
for function_symbol in self.function_symbols.values() {
|
|
||||||
if function_symbol.borrow().declared_name() == declared_name {
|
|
||||||
return Some(Symbol::Function(function_symbol.clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for type_symbol in self.type_symbols.values() {
|
|
||||||
if type_symbol.declared_name() == declared_name {
|
|
||||||
return Some(Symbol::Type(type_symbol.clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_value_symbol_by_declared_name(&self, declared_name: &str) -> Option<Symbol> {
|
|
||||||
for variable_symbol in self.variable_symbols.values() {
|
|
||||||
if variable_symbol.declared_name() == declared_name {
|
|
||||||
return Some(Symbol::Variable(variable_symbol.clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for parameter_symbol in self.parameter_symbols.values() {
|
|
||||||
if parameter_symbol.declared_name() == declared_name {
|
|
||||||
return Some(Symbol::Parameter(parameter_symbol.clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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.class_member_symbols
|
|
||||||
.get(declared_name)
|
|
||||||
.map(|cms| Symbol::ClassMember(cms.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.get_type_symbol_by_fqn(fqn)
|
|
||||||
.map(|ts| Symbol::Type(ts.clone()))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Symbol table */
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum SymbolInsertError {
|
|
||||||
SymbolAlreadyDefined(Symbol),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum SymbolLookupError {
|
|
||||||
NoDefinition,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct SymbolTable {
|
|
||||||
scopes: Vec<Scope>,
|
|
||||||
current_scope_id: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Contains a vec of scopes, like a flattened tree
|
|
||||||
impl SymbolTable {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let mut t = SymbolTable {
|
|
||||||
scopes: vec![Scope::new(None, String::from("GlobalScope"))],
|
|
||||||
current_scope_id: 0,
|
|
||||||
};
|
|
||||||
t
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_scope_id(&self) -> usize {
|
|
||||||
self.current_scope_id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn scopes(&self) -> &Vec<Scope> {
|
|
||||||
&self.scopes
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_scope(&mut self, debug_name: &str) {
|
|
||||||
let id = self.scopes.len();
|
|
||||||
self.scopes.push(Scope::new(
|
|
||||||
Some(self.current_scope_id),
|
|
||||||
debug_name.to_string(),
|
|
||||||
));
|
|
||||||
self.current_scope_id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pop_scope(&mut self) {
|
|
||||||
if let Some(parent_id) = self.scopes[self.current_scope_id].parent {
|
|
||||||
self.current_scope_id = parent_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_use_statement_symbol(
|
|
||||||
&mut self,
|
|
||||||
use_statement_symbol: UseStatementSymbol,
|
|
||||||
) -> Result<Rc<RefCell<UseStatementSymbol>>, SymbolInsertError> {
|
|
||||||
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
|
|
||||||
if let Some(defined_symbol) =
|
|
||||||
current_scope.get_usable_symbol_by_declared_name(use_statement_symbol.declared_name())
|
|
||||||
{
|
|
||||||
Err(SymbolAlreadyDefined(defined_symbol))
|
|
||||||
} else {
|
|
||||||
let declared_name = use_statement_symbol.declared_name().to_string();
|
|
||||||
let to_insert = Rc::new(RefCell::new(use_statement_symbol));
|
|
||||||
let to_return = to_insert.clone();
|
|
||||||
current_scope
|
|
||||||
.use_statement_symbols
|
|
||||||
.insert(declared_name, to_insert);
|
|
||||||
Ok(to_return)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_module_symbol(
|
|
||||||
&mut self,
|
|
||||||
module_symbol: ModuleSymbol,
|
|
||||||
) -> Result<(), SymbolInsertError> {
|
|
||||||
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
|
|
||||||
if let Some(defined_symbol) =
|
|
||||||
current_scope.get_module_symbol_by_declared_name(module_symbol.declared_name())
|
|
||||||
{
|
|
||||||
Err(SymbolAlreadyDefined(Symbol::Module(defined_symbol.clone())))
|
|
||||||
} else {
|
|
||||||
current_scope.module_symbols.insert(
|
|
||||||
module_symbol.declared_name().to_string(),
|
|
||||||
Rc::new(module_symbol),
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_type_symbol(&mut self, type_symbol: TypeSymbol) -> Result<(), SymbolInsertError> {
|
|
||||||
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
|
|
||||||
if let Some(defined_symbol) =
|
|
||||||
current_scope.get_usable_symbol_by_declared_name(type_symbol.declared_name())
|
|
||||||
{
|
|
||||||
Err(SymbolAlreadyDefined(defined_symbol))
|
|
||||||
} else {
|
|
||||||
current_scope.type_symbols.insert(
|
|
||||||
type_symbol.declared_name().to_string(),
|
|
||||||
Rc::new(type_symbol),
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_function_symbol(
|
|
||||||
&mut self,
|
|
||||||
function_symbol: FunctionSymbol,
|
|
||||||
) -> Result<Rc<RefCell<FunctionSymbol>>, SymbolInsertError> {
|
|
||||||
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
|
|
||||||
if let Some(defined_symbol) =
|
|
||||||
current_scope.get_usable_symbol_by_declared_name(function_symbol.declared_name())
|
|
||||||
{
|
|
||||||
Err(SymbolAlreadyDefined(defined_symbol))
|
|
||||||
} else {
|
|
||||||
let declared_name = function_symbol.declared_name().to_string();
|
|
||||||
let to_insert = Rc::new(RefCell::new(function_symbol));
|
|
||||||
let to_return = to_insert.clone();
|
|
||||||
current_scope
|
|
||||||
.function_symbols
|
|
||||||
.insert(declared_name, to_insert);
|
|
||||||
Ok(to_return)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_parameter_symbol(
|
|
||||||
&mut self,
|
|
||||||
parameter_symbol: ParameterSymbol,
|
|
||||||
) -> Result<Rc<ParameterSymbol>, SymbolInsertError> {
|
|
||||||
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
|
|
||||||
if let Some(defined_symbol) =
|
|
||||||
current_scope.get_value_symbol_by_declared_name(parameter_symbol.declared_name())
|
|
||||||
{
|
|
||||||
Err(SymbolAlreadyDefined(defined_symbol))
|
|
||||||
} else {
|
|
||||||
let to_insert = Rc::new(parameter_symbol);
|
|
||||||
let to_return = to_insert.clone();
|
|
||||||
current_scope
|
|
||||||
.parameter_symbols
|
|
||||||
.insert(to_insert.declared_name().to_string(), to_insert);
|
|
||||||
Ok(to_return)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_variable_symbol(
|
|
||||||
&mut self,
|
|
||||||
variable_symbol: VariableSymbol,
|
|
||||||
) -> Result<Rc<VariableSymbol>, SymbolInsertError> {
|
|
||||||
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
|
|
||||||
if let Some(defined_symbol) =
|
|
||||||
current_scope.get_value_symbol_by_declared_name(variable_symbol.declared_name())
|
|
||||||
{
|
|
||||||
Err(SymbolAlreadyDefined(defined_symbol))
|
|
||||||
} else {
|
|
||||||
let declared_name = variable_symbol.declared_name().to_string();
|
|
||||||
let to_insert = Rc::new(variable_symbol);
|
|
||||||
let to_return = to_insert.clone();
|
|
||||||
current_scope
|
|
||||||
.variable_symbols
|
|
||||||
.insert(declared_name, to_insert);
|
|
||||||
Ok(to_return)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_class_member_symbol(
|
|
||||||
&mut self,
|
|
||||||
class_member_symbol: ClassMemberSymbol,
|
|
||||||
) -> Result<(), SymbolInsertError> {
|
|
||||||
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
|
|
||||||
if let Some(defined_symbol) =
|
|
||||||
current_scope.get_expressible_by_declared_name(class_member_symbol.declared_name())
|
|
||||||
{
|
|
||||||
Err(SymbolAlreadyDefined(defined_symbol))
|
|
||||||
} else {
|
|
||||||
current_scope.class_member_symbols.insert(
|
|
||||||
class_member_symbol.declared_name().to_string(),
|
|
||||||
Rc::new(class_member_symbol),
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
|
||||||
&self,
|
|
||||||
fully_qualified_name: &str,
|
|
||||||
scope_id: usize,
|
|
||||||
) -> Result<Symbol, SymbolLookupError> {
|
|
||||||
for scope in &self.scopes {
|
|
||||||
if let Some(symbol) = scope.get_usable_symbol_by_fqn(fully_qualified_name) {
|
|
||||||
return Ok(symbol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
writeln!(f, "SymbolTable(current_scope = {})", self.current_scope_id)?;
|
|
||||||
for (i, scope) in self.scopes.iter().enumerate() {
|
|
||||||
writeln!(f, "----Scope {} {}----", i, scope.debug_name)?;
|
|
||||||
for symbol in scope.use_statement_symbols.values() {
|
|
||||||
writeln!(f, "{:#?}", symbol.borrow())?;
|
|
||||||
}
|
|
||||||
for symbol in scope.module_symbols.values() {
|
|
||||||
writeln!(f, "{:#?}", symbol)?;
|
|
||||||
}
|
|
||||||
for symbol in scope.type_symbols.values() {
|
|
||||||
writeln!(f, "{:#?}", symbol)?;
|
|
||||||
}
|
|
||||||
for symbol in scope.function_symbols.values() {
|
|
||||||
writeln!(f, "{:#?}", symbol.borrow())?;
|
|
||||||
}
|
|
||||||
for symbol in scope.parameter_symbols.values() {
|
|
||||||
writeln!(f, "{:#?}", symbol)?;
|
|
||||||
}
|
|
||||||
for symbol in scope.variable_symbols.values() {
|
|
||||||
writeln!(f, "{:#?}", symbol)?;
|
|
||||||
}
|
|
||||||
for symbol in scope.class_member_symbols.values() {
|
|
||||||
writeln!(f, "{:#?}", symbol)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
333
src/name_analysis/symbol_table/mod.rs
Normal file
333
src/name_analysis/symbol_table/mod.rs
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol;
|
||||||
|
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
|
||||||
|
use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
|
||||||
|
use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
|
||||||
|
use crate::name_analysis::symbol::type_symbol::TypeSymbol;
|
||||||
|
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
|
||||||
|
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
|
||||||
|
use crate::name_analysis::symbol::*;
|
||||||
|
use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined;
|
||||||
|
use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition;
|
||||||
|
use scope::Scope;
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
mod scope;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SymbolInsertError {
|
||||||
|
SymbolAlreadyDefined(Symbol),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SymbolLookupError {
|
||||||
|
NoDefinition,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SymbolTable {
|
||||||
|
scopes: Vec<Scope>,
|
||||||
|
current_scope_id: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Contains a vec of scopes, like a flattened tree
|
||||||
|
impl SymbolTable {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
scopes: vec![Scope::new(None, 0, String::from("GlobalScope"))],
|
||||||
|
current_scope_id: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_scope_id(&self) -> usize {
|
||||||
|
self.current_scope_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_scope(&mut self, debug_name: &str) {
|
||||||
|
let id = self.scopes.len();
|
||||||
|
self.scopes
|
||||||
|
.push(Scope::new(Some(self.current_scope_id), id, debug_name.to_string()));
|
||||||
|
self.current_scope_id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_scope(&mut self) {
|
||||||
|
if let Some(parent_id) = self.scopes[self.current_scope_id].parent() {
|
||||||
|
self.current_scope_id = parent_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_scope(&self) -> &Scope {
|
||||||
|
self.scopes.last().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_scope_mut(&mut self) -> &mut Scope {
|
||||||
|
self.scopes.last_mut().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_current_scope_concrete_use_symbol(
|
||||||
|
&self,
|
||||||
|
declared_name: &str,
|
||||||
|
) -> Option<&ConcreteUseSymbol> {
|
||||||
|
self.current_scope()
|
||||||
|
.concrete_use_symbols()
|
||||||
|
.get(declared_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_current_scope_star_use_symbol(&self, base_fqn: &str) -> Option<&StarUseSymbol> {
|
||||||
|
self.current_scope().star_use_symbols().get(base_fqn)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_current_scope_type_symbol(&self, declared_name: &str) -> Option<&TypeSymbol> {
|
||||||
|
self.current_scope().type_symbols().get(declared_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_current_scope_module_symbol(&self, declared_name: &str) -> Option<&ModuleSymbol> {
|
||||||
|
self.current_scope().module_symbols().get(declared_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_current_scope_parameter_symbol(&self, declared_name: &str) -> Option<&ParameterSymbol> {
|
||||||
|
self.current_scope().parameter_symbols().get(declared_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_current_scope_variable_symbol(&self, declared_name: &str) -> Option<&VariableSymbol> {
|
||||||
|
self.current_scope().variable_symbols().get(declared_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_current_scope_class_member_symbol(
|
||||||
|
&self,
|
||||||
|
declared_name: &str,
|
||||||
|
) -> Option<&ClassMemberSymbol> {
|
||||||
|
self.current_scope()
|
||||||
|
.class_member_symbols()
|
||||||
|
.get(declared_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_current_scope_variable_or_parameter_symbol(
|
||||||
|
&self,
|
||||||
|
declared_name: &str,
|
||||||
|
) -> Option<Symbol> {
|
||||||
|
self.find_current_scope_variable_symbol(declared_name)
|
||||||
|
.map(|variable_symbol| Symbol::Variable(variable_symbol.clone()))
|
||||||
|
.or_else(|| {
|
||||||
|
self.find_current_scope_parameter_symbol(declared_name)
|
||||||
|
.map(|parameter_symbol| Symbol::Parameter(parameter_symbol.clone()))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_current_scope_usable_symbol(&self, declared_name: &str) -> Option<Symbol> {
|
||||||
|
self.find_current_scope_concrete_use_symbol(declared_name)
|
||||||
|
.map(|concrete_use_symbol| Symbol::ConcreteUse(concrete_use_symbol.clone()))
|
||||||
|
.or_else(|| {
|
||||||
|
self.find_current_scope_type_symbol(declared_name)
|
||||||
|
.map(|type_symbol| Symbol::Type(type_symbol.clone()))
|
||||||
|
})
|
||||||
|
.or_else(|| {
|
||||||
|
self.find_current_scope_module_symbol(declared_name)
|
||||||
|
.map(|module_symbol| Symbol::Module(module_symbol.clone()))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_concrete_use_symbol(
|
||||||
|
&mut self,
|
||||||
|
concrete_use_symbol: ConcreteUseSymbol,
|
||||||
|
) -> Result<(), SymbolInsertError> {
|
||||||
|
if let Some(defined_symbol) =
|
||||||
|
self.find_current_scope_usable_symbol(concrete_use_symbol.declared_name())
|
||||||
|
{
|
||||||
|
Err(SymbolAlreadyDefined(defined_symbol))
|
||||||
|
} else {
|
||||||
|
self.current_scope_mut().concrete_use_symbols_mut().insert(
|
||||||
|
concrete_use_symbol.declared_name().to_string(),
|
||||||
|
concrete_use_symbol,
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_star_use_symbol(
|
||||||
|
&mut self,
|
||||||
|
star_use_symbol: StarUseSymbol,
|
||||||
|
) -> Result<(), SymbolInsertError> {
|
||||||
|
if let Some(defined_symbol) =
|
||||||
|
self.find_current_scope_star_use_symbol(star_use_symbol.base_fqn())
|
||||||
|
{
|
||||||
|
Err(SymbolAlreadyDefined(Symbol::StarUse(
|
||||||
|
defined_symbol.clone(),
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
self.current_scope_mut()
|
||||||
|
.star_use_symbols_mut()
|
||||||
|
.insert(star_use_symbol.base_fqn().to_string(), star_use_symbol);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_module_symbol(
|
||||||
|
&mut self,
|
||||||
|
module_symbol: ModuleSymbol,
|
||||||
|
) -> Result<(), SymbolInsertError> {
|
||||||
|
if let Some(defined_symbol) =
|
||||||
|
self.find_current_scope_usable_symbol(module_symbol.declared_name())
|
||||||
|
{
|
||||||
|
Err(SymbolAlreadyDefined(defined_symbol))
|
||||||
|
} else {
|
||||||
|
self.current_scope_mut()
|
||||||
|
.module_symbols_mut()
|
||||||
|
.insert(module_symbol.declared_name().to_string(), module_symbol);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_type_symbol(&mut self, type_symbol: TypeSymbol) -> Result<(), SymbolInsertError> {
|
||||||
|
if let Some(defined_symbol) =
|
||||||
|
self.find_current_scope_usable_symbol(type_symbol.declared_name())
|
||||||
|
{
|
||||||
|
Err(SymbolAlreadyDefined(defined_symbol))
|
||||||
|
} else {
|
||||||
|
self.current_scope_mut()
|
||||||
|
.type_symbols_mut()
|
||||||
|
.insert(type_symbol.declared_name().to_string(), type_symbol);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_function_symbol(
|
||||||
|
&mut self,
|
||||||
|
function_symbol: FunctionSymbol,
|
||||||
|
) -> Result<(), SymbolInsertError> {
|
||||||
|
if let Some(defined_symbol) =
|
||||||
|
self.find_current_scope_usable_symbol(function_symbol.declared_name())
|
||||||
|
{
|
||||||
|
Err(SymbolAlreadyDefined(defined_symbol))
|
||||||
|
} else {
|
||||||
|
self.current_scope_mut()
|
||||||
|
.function_symbols_mut()
|
||||||
|
.insert(function_symbol.declared_name().to_string(), function_symbol);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_parameter_symbol(
|
||||||
|
&mut self,
|
||||||
|
parameter_symbol: ParameterSymbol,
|
||||||
|
) -> Result<(), SymbolInsertError> {
|
||||||
|
if let Some(defined_symbol) =
|
||||||
|
self.find_current_scope_parameter_symbol(parameter_symbol.declared_name())
|
||||||
|
{
|
||||||
|
Err(SymbolAlreadyDefined(Symbol::Parameter(
|
||||||
|
defined_symbol.clone(),
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
self.current_scope_mut().parameter_symbols_mut().insert(
|
||||||
|
parameter_symbol.declared_name().to_string(),
|
||||||
|
parameter_symbol,
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_variable_symbol(
|
||||||
|
&mut self,
|
||||||
|
variable_symbol: VariableSymbol,
|
||||||
|
) -> Result<(), SymbolInsertError> {
|
||||||
|
if let Some(defined_symbol) =
|
||||||
|
self.find_current_scope_variable_or_parameter_symbol(variable_symbol.declared_name())
|
||||||
|
{
|
||||||
|
Err(SymbolAlreadyDefined(defined_symbol))
|
||||||
|
} else {
|
||||||
|
self.current_scope_mut()
|
||||||
|
.variable_symbols_mut()
|
||||||
|
.insert(variable_symbol.declared_name().to_string(), variable_symbol);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_class_member_symbol(
|
||||||
|
&mut self,
|
||||||
|
class_member_symbol: ClassMemberSymbol,
|
||||||
|
) -> Result<(), SymbolInsertError> {
|
||||||
|
if let Some(defined_symbol) =
|
||||||
|
self.find_current_scope_class_member_symbol(class_member_symbol.declared_name())
|
||||||
|
{
|
||||||
|
Err(SymbolAlreadyDefined(Symbol::ClassMember(
|
||||||
|
defined_symbol.clone(),
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
self.current_scope_mut().class_member_symbols_mut().insert(
|
||||||
|
class_member_symbol.declared_name().to_string(),
|
||||||
|
class_member_symbol,
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_type_in_scope_by_declared_name<'a>(
|
||||||
|
scope: &'a Scope,
|
||||||
|
declared_name: &str,
|
||||||
|
) -> Option<&'a TypeSymbol> {
|
||||||
|
scope.type_symbols().get(declared_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lookup_type_by_declared_name(
|
||||||
|
&self,
|
||||||
|
declared_name: &str,
|
||||||
|
scope_id: usize,
|
||||||
|
) -> Result<&TypeSymbol, SymbolLookupError> {
|
||||||
|
let mut scope_opt = Some(&self.scopes[scope_id]);
|
||||||
|
while let Some(scope) = scope_opt {
|
||||||
|
if let Some(symbol) = Self::lookup_type_in_scope_by_declared_name(scope, declared_name)
|
||||||
|
{
|
||||||
|
return Ok(symbol);
|
||||||
|
}
|
||||||
|
scope_opt = if let Some(parent_id) = scope.parent() {
|
||||||
|
Some(&self.scopes[parent_id])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(NoDefinition)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_type_in_scope_by_fqn<'a>(scope: &'a Scope, fqn: &str) -> Option<&'a TypeSymbol> {
|
||||||
|
for type_symbol in scope.type_symbols().values() {
|
||||||
|
match type_symbol {
|
||||||
|
TypeSymbol::Concrete(concrete_type_symbol) => {
|
||||||
|
if concrete_type_symbol.fqn() == fqn {
|
||||||
|
return Some(type_symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeSymbol::Generic(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lookup_type_by_fqn(
|
||||||
|
&self,
|
||||||
|
fqn: &str,
|
||||||
|
scope_id: usize,
|
||||||
|
) -> Result<&TypeSymbol, SymbolLookupError> {
|
||||||
|
let mut scope_opt = Some(&self.scopes[scope_id]);
|
||||||
|
while let Some(scope) = scope_opt {
|
||||||
|
if let Some(type_symbol) = Self::lookup_type_in_scope_by_fqn(scope, fqn) {
|
||||||
|
return Ok(type_symbol);
|
||||||
|
}
|
||||||
|
scope_opt = if let Some(parent_id) = scope.parent() {
|
||||||
|
Some(&self.scopes[parent_id])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(NoDefinition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for SymbolTable {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
writeln!(f, "SymbolTable(current_scope = {})", self.current_scope_id)?;
|
||||||
|
for scope in &self.scopes {
|
||||||
|
writeln!(f, "{}", scope)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
141
src/name_analysis/symbol_table/scope.rs
Normal file
141
src/name_analysis/symbol_table/scope.rs
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol;
|
||||||
|
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
|
||||||
|
use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
|
||||||
|
use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
|
||||||
|
use crate::name_analysis::symbol::type_symbol::TypeSymbol;
|
||||||
|
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
|
||||||
|
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Scope {
|
||||||
|
parent: Option<usize>,
|
||||||
|
id: usize,
|
||||||
|
concrete_use_symbols: HashMap<String, ConcreteUseSymbol>,
|
||||||
|
star_use_symbols: HashMap<String, StarUseSymbol>,
|
||||||
|
module_symbols: HashMap<String, ModuleSymbol>,
|
||||||
|
type_symbols: HashMap<String, TypeSymbol>,
|
||||||
|
function_symbols: HashMap<String, FunctionSymbol>,
|
||||||
|
parameter_symbols: HashMap<String, ParameterSymbol>,
|
||||||
|
variable_symbols: HashMap<String, VariableSymbol>,
|
||||||
|
class_member_symbols: HashMap<String, ClassMemberSymbol>,
|
||||||
|
debug_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Scope {
|
||||||
|
pub fn new(parent: Option<usize>, id: usize, debug_name: String) -> Self {
|
||||||
|
Self {
|
||||||
|
parent,
|
||||||
|
id,
|
||||||
|
concrete_use_symbols: HashMap::new(),
|
||||||
|
star_use_symbols: HashMap::new(),
|
||||||
|
module_symbols: HashMap::new(),
|
||||||
|
type_symbols: HashMap::new(),
|
||||||
|
function_symbols: HashMap::new(),
|
||||||
|
parameter_symbols: HashMap::new(),
|
||||||
|
variable_symbols: HashMap::new(),
|
||||||
|
class_member_symbols: HashMap::new(),
|
||||||
|
debug_name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parent(&self) -> Option<usize> {
|
||||||
|
self.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn id(&self) -> usize {
|
||||||
|
self.id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn concrete_use_symbols(&self) -> &HashMap<String, ConcreteUseSymbol> {
|
||||||
|
&self.concrete_use_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn concrete_use_symbols_mut(&mut self) -> &mut HashMap<String, ConcreteUseSymbol> {
|
||||||
|
&mut self.concrete_use_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn star_use_symbols(&self) -> &HashMap<String, StarUseSymbol> {
|
||||||
|
&self.star_use_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn star_use_symbols_mut(&mut self) -> &mut HashMap<String, StarUseSymbol> {
|
||||||
|
&mut self.star_use_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn module_symbols(&self) -> &HashMap<String, ModuleSymbol> {
|
||||||
|
&self.module_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn module_symbols_mut(&mut self) -> &mut HashMap<String, ModuleSymbol> {
|
||||||
|
&mut self.module_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_symbols(&self) -> &HashMap<String, TypeSymbol> {
|
||||||
|
&self.type_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_symbols_mut(&mut self) -> &mut HashMap<String, TypeSymbol> {
|
||||||
|
&mut self.type_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function_symbols(&self) -> &HashMap<String, FunctionSymbol> {
|
||||||
|
&self.function_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function_symbols_mut(&mut self) -> &mut HashMap<String, FunctionSymbol> {
|
||||||
|
&mut self.function_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parameter_symbols(&self) -> &HashMap<String, ParameterSymbol> {
|
||||||
|
&self.parameter_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parameter_symbols_mut(&mut self) -> &mut HashMap<String, ParameterSymbol> {
|
||||||
|
&mut self.parameter_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn variable_symbols(&self) -> &HashMap<String, VariableSymbol> {
|
||||||
|
&self.variable_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn variable_symbols_mut(&mut self) -> &mut HashMap<String, VariableSymbol> {
|
||||||
|
&mut self.variable_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn class_member_symbols(&self) -> &HashMap<String, ClassMemberSymbol> {
|
||||||
|
&self.class_member_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn class_member_symbols_mut(&mut self) -> &mut HashMap<String, ClassMemberSymbol> {
|
||||||
|
&mut self.class_member_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn debug_name(&self) -> &str {
|
||||||
|
&self.debug_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! write_symbols {
|
||||||
|
( $f:expr, $symbols:expr ) => {
|
||||||
|
for symbol in $symbols.values() {
|
||||||
|
writeln!($f, "{:#?}", symbol)?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Scope {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
writeln!(f, "----Scope {} {}----", self.id(), self.debug_name())?;
|
||||||
|
write_symbols!(f, self.concrete_use_symbols());
|
||||||
|
write_symbols!(f, self.star_use_symbols());
|
||||||
|
write_symbols!(f, self.module_symbols());
|
||||||
|
write_symbols!(f, self.type_symbols());
|
||||||
|
write_symbols!(f, self.function_symbols());
|
||||||
|
write_symbols!(f, self.parameter_symbols());
|
||||||
|
write_symbols!(f, self.variable_symbols());
|
||||||
|
write_symbols!(f, self.class_member_symbols());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -88,6 +88,7 @@ $defs:
|
|||||||
- $ref: "#/$defs/StructChildSkipHash"
|
- $ref: "#/$defs/StructChildSkipHash"
|
||||||
- $ref: "#/$defs/StructChildVecHash"
|
- $ref: "#/$defs/StructChildVecHash"
|
||||||
- $ref: "#/$defs/StructChildMemberHash"
|
- $ref: "#/$defs/StructChildMemberHash"
|
||||||
|
- $ref: "#/$defs/StructChildSpecialHash"
|
||||||
StructChildSkipHash:
|
StructChildSkipHash:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
@ -148,7 +149,6 @@ $defs:
|
|||||||
oneOf:
|
oneOf:
|
||||||
- $ref: "#/$defs/StructChildMemberBuildNodeHash"
|
- $ref: "#/$defs/StructChildMemberBuildNodeHash"
|
||||||
- $ref: "#/$defs/StructChildMemberBuildBooleanHash"
|
- $ref: "#/$defs/StructChildMemberBuildBooleanHash"
|
||||||
- $ref: "#/$defs/StructChildMemberBuildSpecialHash"
|
|
||||||
StructChildMemberBuildNodeHash:
|
StructChildMemberBuildNodeHash:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
@ -191,7 +191,7 @@ $defs:
|
|||||||
- rule_present
|
- rule_present
|
||||||
required:
|
required:
|
||||||
- on
|
- on
|
||||||
StructChildMemberBuildSpecialHash:
|
StructChildSpecialHash:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
description: A special member to be built.
|
description: A special member to be built.
|
||||||
|
|||||||
@ -181,7 +181,7 @@ ReturnType:
|
|||||||
CompilationUnit:
|
CompilationUnit:
|
||||||
struct:
|
struct:
|
||||||
children:
|
children:
|
||||||
- parent_mod:
|
- namespace:
|
||||||
member:
|
member:
|
||||||
optional: true
|
optional: true
|
||||||
- use_statements:
|
- use_statements:
|
||||||
@ -193,12 +193,15 @@ CompilationUnit:
|
|||||||
- eoi:
|
- eoi:
|
||||||
skip:
|
skip:
|
||||||
rule: EOI
|
rule: EOI
|
||||||
ParentMod:
|
- file_id:
|
||||||
|
special:
|
||||||
|
kind: file_id
|
||||||
|
Namespace:
|
||||||
struct:
|
struct:
|
||||||
children:
|
children:
|
||||||
- mod_kw:
|
- ns_kw:
|
||||||
skip:
|
skip:
|
||||||
rule: Mod
|
rule: Ns
|
||||||
- fqn:
|
- fqn:
|
||||||
member:
|
member:
|
||||||
rule: FullyQualifiedName
|
rule: FullyQualifiedName
|
||||||
@ -215,13 +218,9 @@ UseStatement:
|
|||||||
member:
|
member:
|
||||||
rule: UseStatementSuffix
|
rule: UseStatementSuffix
|
||||||
- file_id:
|
- file_id:
|
||||||
member:
|
|
||||||
build:
|
|
||||||
special:
|
special:
|
||||||
kind: file_id
|
kind: file_id
|
||||||
- range:
|
- range:
|
||||||
member:
|
|
||||||
build:
|
|
||||||
special:
|
special:
|
||||||
kind: range
|
kind: range
|
||||||
UseStatementPrefix:
|
UseStatementPrefix:
|
||||||
@ -254,7 +253,6 @@ ModuleLevelDeclaration:
|
|||||||
InterfaceLevelDeclaration:
|
InterfaceLevelDeclaration:
|
||||||
tree_enum:
|
tree_enum:
|
||||||
rules:
|
rules:
|
||||||
- CompanionModule
|
|
||||||
- Interface
|
- Interface
|
||||||
- Class
|
- Class
|
||||||
- InterfaceFunction
|
- InterfaceFunction
|
||||||
@ -264,7 +262,6 @@ InterfaceLevelDeclaration:
|
|||||||
ClassLevelDeclaration:
|
ClassLevelDeclaration:
|
||||||
tree_enum:
|
tree_enum:
|
||||||
rules:
|
rules:
|
||||||
- CompanionModule
|
|
||||||
- Interface
|
- Interface
|
||||||
- Class
|
- Class
|
||||||
- Function
|
- Function
|
||||||
@ -291,21 +288,6 @@ Module:
|
|||||||
- end_kw:
|
- end_kw:
|
||||||
skip:
|
skip:
|
||||||
rule: End
|
rule: End
|
||||||
CompanionModule:
|
|
||||||
struct:
|
|
||||||
children:
|
|
||||||
- companion_kw:
|
|
||||||
skip:
|
|
||||||
rule: Companion
|
|
||||||
- mod_kw:
|
|
||||||
skip:
|
|
||||||
rule: Mod
|
|
||||||
- declarations:
|
|
||||||
vec:
|
|
||||||
rule: ModuleLevelDeclaration
|
|
||||||
- end_kw:
|
|
||||||
skip:
|
|
||||||
rule: End
|
|
||||||
Interface:
|
Interface:
|
||||||
struct:
|
struct:
|
||||||
children:
|
children:
|
||||||
|
|||||||
@ -307,13 +307,13 @@ ReturnType = {
|
|||||||
|
|
||||||
CompilationUnit = {
|
CompilationUnit = {
|
||||||
SOI
|
SOI
|
||||||
~ ParentMod?
|
~ Namespace?
|
||||||
~ ( UseStatement | ModuleLevelDeclaration )*
|
~ ( UseStatement | ModuleLevelDeclaration )*
|
||||||
~ EOI
|
~ EOI
|
||||||
}
|
}
|
||||||
|
|
||||||
ParentMod = {
|
Namespace = {
|
||||||
Mod
|
Ns
|
||||||
~ FullyQualifiedName
|
~ FullyQualifiedName
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,8 +352,7 @@ ModuleLevelDeclaration = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InterfaceLevelDeclaration = {
|
InterfaceLevelDeclaration = {
|
||||||
CompanionModule
|
Interface
|
||||||
| Interface
|
|
||||||
| Class
|
| Class
|
||||||
| InterfaceFunction
|
| InterfaceFunction
|
||||||
| InterfaceDefaultFunction
|
| InterfaceDefaultFunction
|
||||||
@ -362,8 +361,7 @@ InterfaceLevelDeclaration = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ClassLevelDeclaration = {
|
ClassLevelDeclaration = {
|
||||||
CompanionModule
|
Interface
|
||||||
| Interface
|
|
||||||
| Class
|
| Class
|
||||||
| Function
|
| Function
|
||||||
| OperatorFunction
|
| OperatorFunction
|
||||||
@ -380,13 +378,6 @@ Module = {
|
|||||||
~ End
|
~ End
|
||||||
}
|
}
|
||||||
|
|
||||||
CompanionModule = {
|
|
||||||
Companion
|
|
||||||
~ Mod
|
|
||||||
~ ModuleLevelDeclaration*
|
|
||||||
~ End
|
|
||||||
}
|
|
||||||
|
|
||||||
Interface = {
|
Interface = {
|
||||||
Pub?
|
Pub?
|
||||||
~ IntKw
|
~ IntKw
|
||||||
|
|||||||
@ -1,13 +1,26 @@
|
|||||||
use crate::name_analysis::symbol::{FunctionSymbol, ParameterSymbol};
|
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
|
||||||
|
use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
|
||||||
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_function_symbol(
|
||||||
FunctionSymbol::new("std::core::println", "println", true, true, None)
|
FunctionSymbol::without_parameters_or_return_type(
|
||||||
|
"std::core::println",
|
||||||
|
"println",
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
None,
|
||||||
|
)
|
||||||
.with_parameters(vec![ParameterSymbol::new("msg", None)]),
|
.with_parameters(vec![ParameterSymbol::new("msg", None)]),
|
||||||
)?;
|
)?;
|
||||||
symbol_table.insert_function_symbol(
|
symbol_table.insert_function_symbol(
|
||||||
FunctionSymbol::new("std::core::print", "print", true, true, None)
|
FunctionSymbol::without_parameters_or_return_type(
|
||||||
|
"std::core::print",
|
||||||
|
"print",
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
None,
|
||||||
|
)
|
||||||
.with_parameters(vec![ParameterSymbol::new("msg", None)]),
|
.with_parameters(vec![ParameterSymbol::new("msg", None)]),
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user