Compare commits
No commits in common. "d09d945323f0c36ab112bf88e0866c2be3528ef1" and "f0772fbf11d2ec5dff1411f331392b89a8da3540" have entirely different histories.
d09d945323
...
f0772fbf11
@ -16,7 +16,7 @@ pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream {
|
|||||||
let child_ident = format_ident!("{}", node_child.node_kind().to_case(Case::Snake));
|
let child_ident = format_ident!("{}", node_child.node_kind().to_case(Case::Snake));
|
||||||
quote! {
|
quote! {
|
||||||
#type_ident::#rule_ident(#child_ident) => vec![
|
#type_ident::#rule_ident(#child_ident) => vec![
|
||||||
#child_ident
|
#child_ident.as_node_ref()
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,14 +35,14 @@ pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream {
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl<'a> AstNode<'a> for #type_ident {
|
impl AstNode for #type_ident {
|
||||||
fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> {
|
fn children(&self) -> Vec<AstNodeRef> {
|
||||||
match self {
|
match self {
|
||||||
#(#match_arms,)*
|
#(#match_arms,)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_node_ref(&'a self) -> AstNodeRef<'a> {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
use crate::spec::leaf_enum_spec::LeafEnumBuildSpec;
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
use crate::spec::leaf_enum_spec::LeafEnumBuildSpec;
|
||||||
|
|
||||||
pub fn make_leaf_enum_ast_node_impl(spec: &LeafEnumBuildSpec) -> TokenStream {
|
pub fn make_leaf_enum_ast_node_impl(spec: &LeafEnumBuildSpec) -> TokenStream {
|
||||||
let type_ident = format_ident!("{}", spec.build());
|
let type_ident = format_ident!("{}", spec.build());
|
||||||
quote! {
|
quote! {
|
||||||
impl<'a> AstNode<'a> for #type_ident {
|
impl AstNode for #type_ident {
|
||||||
fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> {
|
fn children(&self) -> Vec<AstNodeRef> {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_node_ref(&'a self) -> AstNodeRef<'a> {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,12 +5,12 @@ use quote::{format_ident, quote};
|
|||||||
pub fn make_leaf_struct_ast_node_impl(spec: &LeafStructBuildSpec) -> TokenStream {
|
pub fn make_leaf_struct_ast_node_impl(spec: &LeafStructBuildSpec) -> TokenStream {
|
||||||
let type_ident = format_ident!("{}", spec.build());
|
let type_ident = format_ident!("{}", spec.build());
|
||||||
quote! {
|
quote! {
|
||||||
impl<'a> AstNode<'a> for #type_ident {
|
impl AstNode for #type_ident {
|
||||||
fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> {
|
fn children(&self) -> Vec<AstNodeRef> {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_node_ref(&'a self) -> AstNodeRef<'a> {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,34 +71,3 @@ pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option<TokenStream> {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_ast_node_ref_unwrapper(build_spec: &BuildSpec) -> Option<TokenStream> {
|
|
||||||
match build_spec {
|
|
||||||
BuildSpec::Enum(enum_spec) => {
|
|
||||||
Some(format_ident!("{}", enum_spec.build()))
|
|
||||||
}
|
|
||||||
BuildSpec::LeafEnum(leaf_enum) => {
|
|
||||||
Some(format_ident!("{}", leaf_enum.build()))
|
|
||||||
}
|
|
||||||
BuildSpec::Struct(struct_spec) => {
|
|
||||||
Some(format_ident!("{}", struct_spec.build()))
|
|
||||||
}
|
|
||||||
BuildSpec::LeafStruct(leaf_struct) => {
|
|
||||||
Some(format_ident!("{}", leaf_struct.build()))
|
|
||||||
}
|
|
||||||
BuildSpec::Production(_) => None,
|
|
||||||
BuildSpec::NodeProduction(_) => None,
|
|
||||||
BuildSpec::PolymorphicType(polymorphic_type) => {
|
|
||||||
Some(format_ident!("{}", polymorphic_type.name()))
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
|
|
||||||
Some(format_ident!("{}", polymorphic_enum_loop.name()))
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicPassThrough(_) => None
|
|
||||||
}
|
|
||||||
.map(|type_ident| {
|
|
||||||
quote! {
|
|
||||||
AstNodeRef::#type_ident(inner) => *inner
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -28,20 +28,20 @@ pub fn make_polymorphic_enum_loop_ast_node_impl(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
quote! {
|
quote! {
|
||||||
children.push(self.#child_ident() as &dyn AstNode);
|
children.push(self.#child_ident().as_node_ref())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl<'a> AstNode<'a> for #type_ident {
|
impl AstNode for #type_ident {
|
||||||
fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> {
|
fn children(&self) -> Vec<AstNodeRef> {
|
||||||
let mut children = vec![];
|
let mut children: Vec<AstNodeRef> = vec![];
|
||||||
#(#child_adders;)*
|
#(#child_adders;)*
|
||||||
children
|
children
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_node_ref(&'a self) -> AstNodeRef<'a> {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,20 +11,20 @@ pub fn make_polymorphic_type_ast_node_impl(spec: &PolymorphicTypeBuildSpec) -> T
|
|||||||
let variant_ident = format_ident!("{}", variant.name());
|
let variant_ident = format_ident!("{}", variant.name());
|
||||||
let child_ident = format_ident!("{}", variant.inner_kind().to_case(Case::Snake));
|
let child_ident = format_ident!("{}", variant.inner_kind().to_case(Case::Snake));
|
||||||
quote! {
|
quote! {
|
||||||
#type_ident::#variant_ident(#child_ident) => vec![#child_ident]
|
#type_ident::#variant_ident(#child_ident) => vec![#child_ident.as_node_ref()]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl<'a> AstNode<'a> for #type_ident {
|
impl AstNode for #type_ident {
|
||||||
fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> {
|
fn children(&self) -> Vec<AstNodeRef> {
|
||||||
match self {
|
match self {
|
||||||
#(#match_arms,)*
|
#(#match_arms,)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_node_ref(&'a self) -> AstNodeRef<'a> {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,8 +13,8 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
|||||||
VecChildBuild::Node(_) => {
|
VecChildBuild::Node(_) => {
|
||||||
let child_ident = format_ident!("{}", vec_child.name());
|
let child_ident = format_ident!("{}", vec_child.name());
|
||||||
let children_stream = quote! {
|
let children_stream = quote! {
|
||||||
for child in self.#child_ident() {
|
for child in self.#child_ident().map(AstNode::as_node_ref) {
|
||||||
children.push(child as &dyn AstNode);
|
children.push(child);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Some(children_stream)
|
Some(children_stream)
|
||||||
@ -26,12 +26,12 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
|||||||
if member_child.optional() {
|
if member_child.optional() {
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
if let Some(#child_ident) = self.#child_ident() {
|
if let Some(#child_ident) = self.#child_ident() {
|
||||||
children.push(#child_ident as &dyn AstNode);
|
children.push(#child_ident.as_node_ref());
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
children.push(self.#child_ident() as &dyn AstNode)
|
children.push(self.#child_ident().as_node_ref())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,14 +44,14 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl<'a> AstNode<'a> for #type_ident {
|
impl AstNode for #type_ident {
|
||||||
fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> {
|
fn children(&self) -> Vec<AstNodeRef> {
|
||||||
let mut children = vec![];
|
let mut children: Vec<AstNodeRef> = vec![];
|
||||||
#(#child_adders;)*
|
#(#child_adders;)*
|
||||||
children
|
children
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_node_ref(&'a self) -> AstNodeRef<'a> {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ mod spec;
|
|||||||
mod type_gen;
|
mod type_gen;
|
||||||
mod walk;
|
mod walk;
|
||||||
|
|
||||||
use crate::ast_node::{make_ast_enum_member, make_ast_node_impl, make_ast_node_ref_unwrapper};
|
use crate::ast_node::{make_ast_enum_member, make_ast_node_impl};
|
||||||
use crate::build_fn::make_build_fn;
|
use crate::build_fn::make_build_fn;
|
||||||
use crate::deserialize::deserialize_yaml_spec;
|
use crate::deserialize::deserialize_yaml_spec;
|
||||||
use crate::pretty_print::make_pretty_print_impl;
|
use crate::pretty_print::make_pretty_print_impl;
|
||||||
@ -165,13 +165,6 @@ fn generate_ast_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
|||||||
.map(Option::unwrap)
|
.map(Option::unwrap)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let inner_unwrappers = build_specs
|
|
||||||
.iter()
|
|
||||||
.map(|build_spec| make_ast_node_ref_unwrapper(build_spec))
|
|
||||||
.filter(Option::is_some)
|
|
||||||
.map(Option::unwrap)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let combined = quote! {
|
let combined = quote! {
|
||||||
use crate::ast::node::*;
|
use crate::ast::node::*;
|
||||||
|
|
||||||
@ -179,18 +172,10 @@ fn generate_ast_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
|||||||
#(#ast_enum_members,)*
|
#(#ast_enum_members,)*
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AstNodeRef<'a> {
|
pub trait AstNode {
|
||||||
pub fn inner(&self) -> &dyn AstNode<'a> {
|
fn children(&self) -> Vec<AstNodeRef>;
|
||||||
match self {
|
|
||||||
#(#inner_unwrappers,)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait AstNode<'a> {
|
fn as_node_ref(&self) -> AstNodeRef;
|
||||||
fn children(&'a self) -> Vec<&'a dyn AstNode<'a>>;
|
|
||||||
|
|
||||||
fn as_node_ref(&'a self) -> AstNodeRef<'a>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#(#impls)*
|
#(#impls)*
|
||||||
|
|||||||
@ -1,16 +1,59 @@
|
|||||||
use crate::spec::BuildSpec;
|
use crate::spec::BuildSpec;
|
||||||
|
use convert_case::{Case, Casing};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
pub fn make_walk_fn(specs: &[BuildSpec]) -> TokenStream {
|
pub fn make_walk_fn(specs: &[BuildSpec]) -> TokenStream {
|
||||||
|
let child_match_arms = specs
|
||||||
|
.iter()
|
||||||
|
.map(|spec| match spec {
|
||||||
|
BuildSpec::Enum(enum_spec) => Some((
|
||||||
|
format_ident!("{}", enum_spec.build()),
|
||||||
|
format_ident!("{}", enum_spec.build().to_case(Case::Snake)),
|
||||||
|
)),
|
||||||
|
BuildSpec::LeafEnum(leaf_enum) => Some((
|
||||||
|
format_ident!("{}", leaf_enum.build()),
|
||||||
|
format_ident!("{}", leaf_enum.build().to_case(Case::Snake)),
|
||||||
|
)),
|
||||||
|
BuildSpec::Struct(struct_spec) => Some((
|
||||||
|
format_ident!("{}", struct_spec.build()),
|
||||||
|
format_ident!("{}", struct_spec.build().to_case(Case::Snake)),
|
||||||
|
)),
|
||||||
|
BuildSpec::LeafStruct(leaf_struct) => Some((
|
||||||
|
format_ident!("{}", leaf_struct.build()),
|
||||||
|
format_ident!("{}", leaf_struct.build().to_case(Case::Snake)),
|
||||||
|
)),
|
||||||
|
BuildSpec::Production(_) => None,
|
||||||
|
BuildSpec::NodeProduction(_) => None,
|
||||||
|
BuildSpec::PolymorphicType(polymorphic_type) => Some((
|
||||||
|
format_ident!("{}", polymorphic_type.name()),
|
||||||
|
format_ident!("{}", polymorphic_type.name().to_case(Case::Snake)),
|
||||||
|
)),
|
||||||
|
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => Some((
|
||||||
|
format_ident!("{}", polymorphic_enum_loop.name()),
|
||||||
|
format_ident!("{}", polymorphic_enum_loop.name().to_case(Case::Snake)),
|
||||||
|
)),
|
||||||
|
BuildSpec::PolymorphicPassThrough(_) => None,
|
||||||
|
})
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.map(|(type_ident, inner_ident)| {
|
||||||
|
quote! {
|
||||||
|
#type_ident(#inner_ident) => walk_depth_first(#inner_ident, f)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
use crate::ast::node::*;
|
use crate::ast::node::*;
|
||||||
use crate::ast::ast_node::*;
|
use crate::ast::ast_node::*;
|
||||||
|
|
||||||
pub fn walk_depth_first<'a>(node: &'a dyn AstNode<'a>, f: &mut impl FnMut(AstNodeRef<'a>)) {
|
pub fn walk_depth_first(node: &impl AstNode, f: &mut impl FnMut(AstNodeRef)) {
|
||||||
use AstNodeRef::*;
|
use AstNodeRef::*;
|
||||||
for child in node.children() {
|
for child in node.children() {
|
||||||
walk_depth_first(child, f);
|
match child {
|
||||||
|
#(#child_match_arms,)*
|
||||||
|
}
|
||||||
}
|
}
|
||||||
f(node.as_node_ref());
|
f(node.as_node_ref());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,8 +7,8 @@ fn getWorlds() -> List<World> = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
fn findWorldByColor(worlds: List<World>, color: String) -> String
|
fn findWorldByColor(worlds: List<World>, color: String) -> String
|
||||||
worlds.find { it -> it.color == color }
|
worlds.find { it.color == color }
|
||||||
.map { it -> it.name }
|
.map { it.name }
|
||||||
.expect "No world has the given color ${color}"
|
.expect "No world has the given color ${color}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@ 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(&compilation_units, &files, &mut symbol_table);
|
let diagnostics = analyze_names(compilation_units.as_mut_slice(), &files, &mut symbol_table);
|
||||||
if diagnostics.is_empty() {
|
if diagnostics.is_empty() {
|
||||||
println!("Name analysis complete.");
|
println!("Name analysis complete.");
|
||||||
println!("{}", symbol_table);
|
println!("{}", symbol_table);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -19,46 +19,42 @@ The resolve phase has one main responsibility: resolve all references based on t
|
|||||||
`scope_id` property.
|
`scope_id` property.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// use crate::name_analysis::resolve::resolve_compilation_unit;
|
use crate::ast::node::{CompilationUnit, VariableUse};
|
||||||
use crate::ast::ast_node::AstNode;
|
|
||||||
use crate::ast::node::CompilationUnit;
|
|
||||||
use crate::diagnostic::DmDiagnostic;
|
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::symbol_table::SymbolTable;
|
use crate::name_analysis::symbol_table::SymbolTable;
|
||||||
use codespan_reporting::files::Files;
|
use codespan_reporting::files::Files;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::hash::Hash;
|
|
||||||
use crate::name_analysis::scope_table::ScopeTable;
|
|
||||||
|
|
||||||
pub(self) 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;
|
||||||
mod scope_table;
|
|
||||||
|
|
||||||
pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>(
|
pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>(
|
||||||
compilation_units: &[Box<CompilationUnit>],
|
compilation_units: &mut [Box<CompilationUnit>],
|
||||||
files: &'a F,
|
files: &'a F,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
) -> Vec<DmDiagnostic> {
|
) -> Vec<DmDiagnostic> {
|
||||||
let mut diagnostics = vec![];
|
let mut diagnostics = vec![];
|
||||||
let mut scope_table = ScopeTable::new();
|
let mut scope_ids: HashMap<VariableUse, usize> = HashMap::new();
|
||||||
|
|
||||||
// gather symbols
|
// gather symbols
|
||||||
for compilation_unit in compilation_units {
|
for compilation_unit in compilation_units.iter_mut() {
|
||||||
let file_name = files.name(compilation_unit.file_id()).unwrap();
|
let file_name = files.name(compilation_unit.file_id()).unwrap();
|
||||||
gather_compilation_unit(
|
gather_compilation_unit(
|
||||||
compilation_unit,
|
compilation_unit,
|
||||||
&file_name,
|
&file_name,
|
||||||
symbol_table,
|
symbol_table,
|
||||||
&mut scope_table,
|
&mut scope_ids,
|
||||||
&mut diagnostics,
|
&mut diagnostics,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve symbols
|
// resolve symbols
|
||||||
for compilation_unit in compilation_units {
|
for compilation_unit in compilation_units.iter_mut() {
|
||||||
// resolve_compilation_unit(compilation_unit, symbol_table, &mut diagnostics);
|
// resolve_compilation_unit(compilation_unit, symbol_table, &mut diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,32 +0,0 @@
|
|||||||
use crate::ast::node::{FullyQualifiedName, VariableUse};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
pub struct ScopeTable<'a> {
|
|
||||||
variable_use_scopes: HashMap<&'a VariableUse, usize>,
|
|
||||||
fqn_scopes: HashMap<&'a FullyQualifiedName, usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ScopeTable<'a> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
variable_use_scopes: HashMap::new(),
|
|
||||||
fqn_scopes: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_variable_use_scope(&mut self, variable_use: &'a VariableUse, scope_id: usize) {
|
|
||||||
self.variable_use_scopes.insert(variable_use, scope_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_fqn_scope(&mut self, fqn: &'a FullyQualifiedName, scope_id: usize) {
|
|
||||||
self.fqn_scopes.insert(fqn, scope_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn variable_use_scope(&self, variable_use: &'a VariableUse) -> Option<usize> {
|
|
||||||
self.variable_use_scopes.get(&variable_use).copied()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fqn_scope(&self, fqn: &'a FullyQualifiedName) -> Option<usize> {
|
|
||||||
self.fqn_scopes.get(&fqn).copied()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -45,11 +45,8 @@ impl SymbolTable {
|
|||||||
|
|
||||||
pub fn push_scope(&mut self, debug_name: &str) {
|
pub fn push_scope(&mut self, debug_name: &str) {
|
||||||
let id = self.scopes.len();
|
let id = self.scopes.len();
|
||||||
self.scopes.push(Scope::new(
|
self.scopes
|
||||||
Some(self.current_scope_id),
|
.push(Scope::new(Some(self.current_scope_id), id, debug_name.to_string()));
|
||||||
id,
|
|
||||||
debug_name.to_string(),
|
|
||||||
));
|
|
||||||
self.current_scope_id = id;
|
self.current_scope_id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,61 +316,7 @@ impl SymbolTable {
|
|||||||
Some(&self.scopes[parent_id])
|
Some(&self.scopes[parent_id])
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
|
||||||
}
|
}
|
||||||
Err(NoDefinition)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lookup_addressable_in_scope_by_identifier(
|
|
||||||
scope: &Scope,
|
|
||||||
identifier: &str,
|
|
||||||
) -> Option<Symbol> {
|
|
||||||
scope
|
|
||||||
.variable_symbols()
|
|
||||||
.get(identifier)
|
|
||||||
.map(|variable_symbol| Symbol::Variable(variable_symbol.clone()))
|
|
||||||
.or_else(|| {
|
|
||||||
scope
|
|
||||||
.parameter_symbols()
|
|
||||||
.get(identifier)
|
|
||||||
.map(|parameter_symbol| Symbol::Parameter(parameter_symbol.clone()))
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
scope
|
|
||||||
.class_member_symbols()
|
|
||||||
.get(identifier)
|
|
||||||
.map(|class_member_symbol| Symbol::ClassMember(class_member_symbol.clone()))
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
scope
|
|
||||||
.function_symbols()
|
|
||||||
.get(identifier)
|
|
||||||
.map(|function_symbol| Symbol::Function(function_symbol.clone()))
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
scope
|
|
||||||
.type_symbols()
|
|
||||||
.get(identifier)
|
|
||||||
.map(|type_symbol| Symbol::Type(type_symbol.clone()))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn lookup_addressable_by_identifier(
|
|
||||||
&self,
|
|
||||||
identifier: &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) = Self::lookup_addressable_in_scope_by_identifier(scope, identifier)
|
|
||||||
{
|
|
||||||
return Ok(symbol);
|
|
||||||
}
|
|
||||||
scope_opt = if let Some(parent_id) = scope.parent() {
|
|
||||||
Some(&self.scopes[parent_id])
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
Err(NoDefinition)
|
Err(NoDefinition)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,6 +50,7 @@ Identifier:
|
|||||||
- range:
|
- range:
|
||||||
kind: range
|
kind: range
|
||||||
derive:
|
derive:
|
||||||
|
- Clone
|
||||||
- PartialEq
|
- PartialEq
|
||||||
- Eq
|
- Eq
|
||||||
- Hash
|
- Hash
|
||||||
@ -59,10 +60,6 @@ FullyQualifiedName:
|
|||||||
- identifiers:
|
- identifiers:
|
||||||
vec:
|
vec:
|
||||||
rule: Identifier
|
rule: Identifier
|
||||||
derive:
|
|
||||||
- PartialEq
|
|
||||||
- Eq
|
|
||||||
- Hash
|
|
||||||
|
|
||||||
# Lists
|
# Lists
|
||||||
TypeUseList:
|
TypeUseList:
|
||||||
@ -77,7 +74,7 @@ IdentifierList:
|
|||||||
- identifiers:
|
- identifiers:
|
||||||
vec:
|
vec:
|
||||||
rule: Identifier
|
rule: Identifier
|
||||||
ParenthesesTypeUseList:
|
ParenthesesOptionalTypeUseList:
|
||||||
struct:
|
struct:
|
||||||
children:
|
children:
|
||||||
- type_use_list:
|
- type_use_list:
|
||||||
@ -93,29 +90,19 @@ TypeUse:
|
|||||||
- TupleTypeUse
|
- TupleTypeUse
|
||||||
- FunctionTypeUse
|
- FunctionTypeUse
|
||||||
PrimitiveType:
|
PrimitiveType:
|
||||||
tree_enum:
|
leaf_enum:
|
||||||
rules:
|
rules:
|
||||||
- Byte:
|
- Byte
|
||||||
child: false
|
- Short
|
||||||
- Short:
|
- Char
|
||||||
child: false
|
- Int
|
||||||
- Char:
|
- Long
|
||||||
child: false
|
- Double
|
||||||
- Int:
|
- Bool
|
||||||
child: false
|
- String
|
||||||
- Long:
|
|
||||||
child: false
|
|
||||||
- Double:
|
|
||||||
child: false
|
|
||||||
- Bool:
|
|
||||||
child: false
|
|
||||||
- String:
|
|
||||||
child: false
|
|
||||||
- TypedArray
|
- TypedArray
|
||||||
- Any:
|
- Any
|
||||||
child: false
|
- Void
|
||||||
- Void:
|
|
||||||
child: false
|
|
||||||
TypedArray:
|
TypedArray:
|
||||||
struct:
|
struct:
|
||||||
children:
|
children:
|
||||||
@ -173,7 +160,7 @@ GenericParameters:
|
|||||||
TupleArguments:
|
TupleArguments:
|
||||||
struct:
|
struct:
|
||||||
children:
|
children:
|
||||||
- parentheses_type_use_list
|
- parentheses_optional_type_use_list
|
||||||
|
|
||||||
# Implements List
|
# Implements List
|
||||||
ImplementsList:
|
ImplementsList:
|
||||||
@ -669,7 +656,7 @@ IfClause:
|
|||||||
skip:
|
skip:
|
||||||
rule: Then
|
rule: Then
|
||||||
- statements:
|
- statements:
|
||||||
vec:
|
skip:
|
||||||
rule: Statement
|
rule: Statement
|
||||||
IfElseIf:
|
IfElseIf:
|
||||||
struct:
|
struct:
|
||||||
@ -717,7 +704,7 @@ ForStatement:
|
|||||||
- do_kw:
|
- do_kw:
|
||||||
skip:
|
skip:
|
||||||
rule: Do
|
rule: Do
|
||||||
- statements:
|
- statement:
|
||||||
vec:
|
vec:
|
||||||
rule: Statement
|
rule: Statement
|
||||||
- end_kw:
|
- end_kw:
|
||||||
@ -744,6 +731,7 @@ VariableUse:
|
|||||||
children:
|
children:
|
||||||
- identifier
|
- identifier
|
||||||
derive:
|
derive:
|
||||||
|
- Clone
|
||||||
- PartialEq
|
- PartialEq
|
||||||
- Eq
|
- Eq
|
||||||
- Hash
|
- Hash
|
||||||
|
|||||||
@ -199,7 +199,7 @@ IdentifierList = {
|
|||||||
~ ( "," ~ Identifier )*
|
~ ( "," ~ Identifier )*
|
||||||
}
|
}
|
||||||
|
|
||||||
ParenthesesTypeUseList = {
|
ParenthesesOptionalTypeUseList = {
|
||||||
"("
|
"("
|
||||||
~ TypeUseList?
|
~ TypeUseList?
|
||||||
~ ")"
|
~ ")"
|
||||||
@ -272,7 +272,7 @@ GenericParameters = {
|
|||||||
// Tuple Arguments
|
// Tuple Arguments
|
||||||
|
|
||||||
TupleArguments = {
|
TupleArguments = {
|
||||||
ParenthesesTypeUseList
|
ParenthesesOptionalTypeUseList
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements list
|
// Implements list
|
||||||
|
|||||||
@ -1,205 +0,0 @@
|
|||||||
use std::cell::RefCell;
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::ops::Mul;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Gc<T> {
|
|
||||||
inner: *mut GcInner,
|
|
||||||
data: *const T,
|
|
||||||
_phantom: PhantomData<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct GcInner {
|
|
||||||
color: GcColor,
|
|
||||||
size: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GcInner {
|
|
||||||
pub fn new(size: usize) -> Self {
|
|
||||||
Self {
|
|
||||||
color: GcColor::White,
|
|
||||||
size,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
|
||||||
pub enum GcColor {
|
|
||||||
White,
|
|
||||||
Black,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Gc<T> {
|
|
||||||
pub fn new(data: T) -> Self {
|
|
||||||
let inner = Box::into_raw(Box::new(GcInner::new(size_of::<T>())));
|
|
||||||
let boxed_data = Box::into_raw(Box::new(data)) as *const T;
|
|
||||||
Self {
|
|
||||||
inner,
|
|
||||||
data: boxed_data,
|
|
||||||
_phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_color(&mut self, color: GcColor) {
|
|
||||||
unsafe {
|
|
||||||
(*self.inner).color = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn color(&self) -> GcColor {
|
|
||||||
unsafe { (*self.inner).color }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size(&self) -> usize {
|
|
||||||
unsafe { (*self.inner).size }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn data(&self) -> &T {
|
|
||||||
unsafe { &*self.data }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dealloc(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
drop(Box::from_raw(self.inner));
|
|
||||||
drop(Box::from_raw(self.data as *mut T));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Clone for Gc<T> {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
Self {
|
|
||||||
inner: self.inner,
|
|
||||||
data: self.data,
|
|
||||||
_phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum DvmValue {
|
|
||||||
Primitive(usize),
|
|
||||||
Object(Gc<RefCell<DvmObject>>),
|
|
||||||
Nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct DvmObject {
|
|
||||||
fields: Vec<DvmValue>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DvmObject {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self { fields: vec![] }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fields(&self) -> &[DvmValue] {
|
|
||||||
&self.fields
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fields_mut(&mut self) -> &mut Vec<DvmValue> {
|
|
||||||
&mut self.fields
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn collect_garbage(
|
|
||||||
next_gc: &mut usize,
|
|
||||||
current_size: &mut usize,
|
|
||||||
stack: &Vec<DvmValue>,
|
|
||||||
gcs: &mut Vec<Gc<RefCell<DvmObject>>>,
|
|
||||||
) {
|
|
||||||
let mut gray_stack: Vec<Gc<RefCell<DvmObject>>> = vec![];
|
|
||||||
|
|
||||||
for stack_value in stack {
|
|
||||||
match stack_value {
|
|
||||||
DvmValue::Object(gc) => {
|
|
||||||
if gc.color() == GcColor::White {
|
|
||||||
gray_stack.push(gc.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while let Some(mut current) = gray_stack.pop() {
|
|
||||||
for field in current.data().borrow().fields() {
|
|
||||||
match field {
|
|
||||||
DvmValue::Object(object) => {
|
|
||||||
gray_stack.push(object.clone());
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
current.set_color(GcColor::Black);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut collected_size: usize = 0;
|
|
||||||
|
|
||||||
for i in (0..gcs.len()).rev() {
|
|
||||||
if gcs[i].color() == GcColor::White {
|
|
||||||
let mut gc = gcs.remove(i);
|
|
||||||
let size = gc.size();
|
|
||||||
*current_size -= size;
|
|
||||||
collected_size += size;
|
|
||||||
gc.dealloc();
|
|
||||||
} else {
|
|
||||||
gcs[i].set_color(GcColor::White);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*next_gc = std::cmp::max(1024 * 1024, current_size.mul(2));
|
|
||||||
println!(
|
|
||||||
"collected_size: {}, current_size: {}, next_gc: {}",
|
|
||||||
collected_size, current_size, next_gc
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn maybe_collect_garbage(
|
|
||||||
next_gc: &mut usize,
|
|
||||||
current_size: &mut usize,
|
|
||||||
stack: &Vec<DvmValue>,
|
|
||||||
gcs: &mut Vec<Gc<RefCell<DvmObject>>>,
|
|
||||||
) {
|
|
||||||
if current_size > next_gc {
|
|
||||||
collect_garbage(next_gc, current_size, stack, gcs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc_dvm_object(
|
|
||||||
next_gc: &mut usize,
|
|
||||||
current_size: &mut usize,
|
|
||||||
stack: &Vec<DvmValue>,
|
|
||||||
gcs: &mut Vec<Gc<RefCell<DvmObject>>>,
|
|
||||||
) -> Gc<RefCell<DvmObject>> {
|
|
||||||
maybe_collect_garbage(next_gc, current_size, stack, gcs);
|
|
||||||
let mut object = DvmObject::new();
|
|
||||||
object.fields_mut().push(DvmValue::Nil);
|
|
||||||
let gc = Gc::new(RefCell::new(object));
|
|
||||||
*current_size += gc.size();
|
|
||||||
gcs.push(gc.clone());
|
|
||||||
gc
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_field(obj: &mut Gc<RefCell<DvmObject>>, field_index: usize, value: DvmValue) {
|
|
||||||
let mut binding = obj.data().borrow_mut();
|
|
||||||
binding.fields_mut()[field_index] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::vm::mem::{alloc_dvm_object, collect_garbage, DvmObject, DvmValue, Gc};
|
|
||||||
use std::cell::RefCell;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
let mut stack: Vec<DvmValue> = vec![];
|
|
||||||
let mut heap: Vec<Gc<RefCell<DvmObject>>> = vec![];
|
|
||||||
let mut next_gc: usize = 1024 * 1024;
|
|
||||||
let mut current_size: usize = 0;
|
|
||||||
for i in 0..100_000_000 {
|
|
||||||
let mut o = alloc_dvm_object(&mut next_gc, &mut current_size, &stack, &mut heap);
|
|
||||||
}
|
|
||||||
collect_garbage(&mut next_gc, &mut current_size, &stack, &mut heap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -6,7 +6,6 @@ pub mod implementation;
|
|||||||
pub mod instruction;
|
pub mod instruction;
|
||||||
pub mod interface;
|
pub mod interface;
|
||||||
pub mod lib;
|
pub mod lib;
|
||||||
mod mem;
|
|
||||||
pub mod method;
|
pub mod method;
|
||||||
pub mod object;
|
pub mod object;
|
||||||
pub mod op_codes;
|
pub mod op_codes;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user