Compare commits
No commits in common. "f656d0d4d4e14748915807c3b329b507cb69bcc6" and "803b95c5dcaa780838bf7c094d355d9e95ea7a53" have entirely different histories.
f656d0d4d4
...
803b95c5dc
@ -1,7 +1,6 @@
|
|||||||
mod enum_ast_node;
|
mod enum_ast_node;
|
||||||
mod leaf_enum_ast_node;
|
mod leaf_enum_ast_node;
|
||||||
mod leaf_struct_ast_node;
|
mod leaf_struct_ast_node;
|
||||||
mod polymorphic_enum_inner_build_ast_node;
|
|
||||||
mod polymorphic_enum_loop_ast_node;
|
mod polymorphic_enum_loop_ast_node;
|
||||||
mod polymorphic_type_ast_node;
|
mod polymorphic_type_ast_node;
|
||||||
mod struct_ast_node;
|
mod struct_ast_node;
|
||||||
@ -9,7 +8,6 @@ mod struct_ast_node;
|
|||||||
use crate::ast_node::enum_ast_node::make_enum_ast_node_impl;
|
use crate::ast_node::enum_ast_node::make_enum_ast_node_impl;
|
||||||
use crate::ast_node::leaf_enum_ast_node::make_leaf_enum_ast_node_impl;
|
use crate::ast_node::leaf_enum_ast_node::make_leaf_enum_ast_node_impl;
|
||||||
use crate::ast_node::leaf_struct_ast_node::make_leaf_struct_ast_node_impl;
|
use crate::ast_node::leaf_struct_ast_node::make_leaf_struct_ast_node_impl;
|
||||||
use crate::ast_node::polymorphic_enum_inner_build_ast_node::make_polymorphic_enum_inner_build_ast_node_impl;
|
|
||||||
use crate::ast_node::polymorphic_enum_loop_ast_node::make_polymorphic_enum_loop_ast_node_impl;
|
use crate::ast_node::polymorphic_enum_loop_ast_node::make_polymorphic_enum_loop_ast_node_impl;
|
||||||
use crate::ast_node::polymorphic_type_ast_node::make_polymorphic_type_ast_node_impl;
|
use crate::ast_node::polymorphic_type_ast_node::make_polymorphic_type_ast_node_impl;
|
||||||
use crate::ast_node::struct_ast_node::make_struct_ast_node_impl;
|
use crate::ast_node::struct_ast_node::make_struct_ast_node_impl;
|
||||||
@ -32,11 +30,6 @@ pub fn make_ast_node_impl(build_spec: &BuildSpec) -> Option<TokenStream> {
|
|||||||
make_polymorphic_enum_loop_ast_node_impl(polymorphic_enum_loop),
|
make_polymorphic_enum_loop_ast_node_impl(polymorphic_enum_loop),
|
||||||
),
|
),
|
||||||
BuildSpec::PolymorphicPassThrough(_) => None,
|
BuildSpec::PolymorphicPassThrough(_) => None,
|
||||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build) => Some(
|
|
||||||
make_polymorphic_enum_inner_build_ast_node_impl(polymorphic_enum_inner_build),
|
|
||||||
),
|
|
||||||
BuildSpec::PolymorphicLeafEnum(_) => None,
|
|
||||||
BuildSpec::PolymorphicTreeEnum(_) => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,11 +48,6 @@ fn make_type_ident(build_spec: &BuildSpec) -> Option<Ident> {
|
|||||||
BuildSpec::PolymorphicPassThrough(_) => None,
|
BuildSpec::PolymorphicPassThrough(_) => None,
|
||||||
BuildSpec::Production(_) => None,
|
BuildSpec::Production(_) => None,
|
||||||
BuildSpec::NodeProduction(_) => None,
|
BuildSpec::NodeProduction(_) => None,
|
||||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build) => {
|
|
||||||
Some(format_ident!("{}", polymorphic_enum_inner_build.name()))
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicLeafEnum(_) => None,
|
|
||||||
BuildSpec::PolymorphicTreeEnum(_) => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,4 +81,4 @@ pub fn make_ast_node_ref_mut_unwrapper(build_spec: &BuildSpec) -> Option<TokenSt
|
|||||||
AstNodeRefMut::#type_ident(inner) => *inner
|
AstNodeRefMut::#type_ident(inner) => *inner
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1,76 +0,0 @@
|
|||||||
use convert_case::{Case, Casing};
|
|
||||||
use crate::spec::polymorphic_enum_inner_build::{PolymorphicEnumInnerBuild, PolymorphicEnumInnerBuildMemberKind};
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
|
|
||||||
pub fn make_polymorphic_enum_inner_build_ast_node_impl(
|
|
||||||
spec: &PolymorphicEnumInnerBuild,
|
|
||||||
) -> TokenStream {
|
|
||||||
let type_ident = format_ident!("{}", spec.name());
|
|
||||||
|
|
||||||
let match_arms = spec.members()
|
|
||||||
.map(|member| {
|
|
||||||
let member_ident = format_ident!("{}", member.name());
|
|
||||||
match member.kind() {
|
|
||||||
PolymorphicEnumInnerBuildMemberKind::Leaf => {
|
|
||||||
quote! {
|
|
||||||
#type_ident::#member_ident => vec![]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PolymorphicEnumInnerBuildMemberKind::Struct => {
|
|
||||||
let child_ident = format_ident!("{}", member.name().to_case(Case::Snake));
|
|
||||||
quote! {
|
|
||||||
#type_ident::#member_ident(#child_ident) => vec![
|
|
||||||
#child_ident
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let mut_match_arms = spec.members()
|
|
||||||
.map(|member| {
|
|
||||||
let member_ident = format_ident!("{}", member.name());
|
|
||||||
match member.kind() {
|
|
||||||
PolymorphicEnumInnerBuildMemberKind::Leaf => {
|
|
||||||
quote! {
|
|
||||||
#type_ident::#member_ident => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PolymorphicEnumInnerBuildMemberKind::Struct => {
|
|
||||||
let child_ident = format_ident!("{}", member.name().to_case(Case::Snake));
|
|
||||||
quote! {
|
|
||||||
#type_ident::#member_ident(#child_ident) => {
|
|
||||||
f(#child_ident as &'a mut dyn AstNode<'a>)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
impl<'a> AstNode<'a> for #type_ident {
|
|
||||||
fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> {
|
|
||||||
match self {
|
|
||||||
#(#match_arms,)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn for_each_child_mut(&'a mut self, mut f: &mut dyn FnMut(&'a mut dyn AstNode<'a>)) {
|
|
||||||
match self {
|
|
||||||
#(#mut_match_arms,)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_node_ref(&'a self) -> AstNodeRef<'a> {
|
|
||||||
AstNodeRef::#type_ident(&self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a> {
|
|
||||||
AstNodeRefMut::#type_ident(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,26 +1,20 @@
|
|||||||
|
use crate::build_fn::leaf_enum_build_fn::make_leaf_enum_build_fn;
|
||||||
|
use crate::build_fn::leaf_struct_build_fn::make_leaf_struct_build_fn;
|
||||||
|
use crate::build_fn::node_production_build_fn::make_node_production_build_fn;
|
||||||
|
use crate::build_fn::polymorphic_enum_loop_build_fn::make_polymorphic_enum_loop_build_fn;
|
||||||
|
use crate::build_fn::polymorphic_pass_through_build_fn::make_polymorphic_pass_through_build_fn;
|
||||||
|
use crate::build_fn::polymorphic_type_build_fn::make_polymorphic_type_build_fn;
|
||||||
|
use crate::build_fn::production_build_fn::make_production_build_fn;
|
||||||
|
use crate::build_fn::struct_build_fn::make_struct_build_fn;
|
||||||
|
use crate::build_fn::tree_enum_build_fn::make_enum_build_fn;
|
||||||
use crate::spec::BuildSpec;
|
use crate::spec::BuildSpec;
|
||||||
use leaf_enum_build_fn::make_leaf_enum_build_fn;
|
|
||||||
use leaf_struct_build_fn::make_leaf_struct_build_fn;
|
|
||||||
use node_production_build_fn::make_node_production_build_fn;
|
|
||||||
use polymorphic_enum_inner_build_build_fn::make_polymorphic_enum_inner_build_build_fn;
|
|
||||||
use polymorphic_enum_loop_build_fn::make_polymorphic_enum_loop_build_fn;
|
|
||||||
use polymorphic_leaf_enum_build_fn::make_polymorphic_leaf_enum_build_fn;
|
|
||||||
use polymorphic_pass_through_build_fn::make_polymorphic_pass_through_build_fn;
|
|
||||||
use polymorphic_tree_enum_build_fn::make_polymorphic_tree_enum_build_fn;
|
|
||||||
use polymorphic_type_build_fn::make_polymorphic_type_build_fn;
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use production_build_fn::make_production_build_fn;
|
|
||||||
use struct_build_fn::make_struct_build_fn;
|
|
||||||
use tree_enum_build_fn::make_enum_build_fn;
|
|
||||||
|
|
||||||
mod leaf_enum_build_fn;
|
mod leaf_enum_build_fn;
|
||||||
mod leaf_struct_build_fn;
|
mod leaf_struct_build_fn;
|
||||||
mod node_production_build_fn;
|
mod node_production_build_fn;
|
||||||
mod polymorphic_enum_inner_build_build_fn;
|
|
||||||
mod polymorphic_enum_loop_build_fn;
|
mod polymorphic_enum_loop_build_fn;
|
||||||
mod polymorphic_leaf_enum_build_fn;
|
|
||||||
mod polymorphic_pass_through_build_fn;
|
mod polymorphic_pass_through_build_fn;
|
||||||
mod polymorphic_tree_enum_build_fn;
|
|
||||||
mod polymorphic_type_build_fn;
|
mod polymorphic_type_build_fn;
|
||||||
mod production_build_fn;
|
mod production_build_fn;
|
||||||
mod struct_build_fn;
|
mod struct_build_fn;
|
||||||
@ -45,14 +39,5 @@ pub fn make_build_fn(build_spec: &BuildSpec) -> TokenStream {
|
|||||||
BuildSpec::PolymorphicPassThrough(polymorphic_pass_through_spec) => {
|
BuildSpec::PolymorphicPassThrough(polymorphic_pass_through_spec) => {
|
||||||
make_polymorphic_pass_through_build_fn(polymorphic_pass_through_spec)
|
make_polymorphic_pass_through_build_fn(polymorphic_pass_through_spec)
|
||||||
}
|
}
|
||||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build_spec) => {
|
|
||||||
make_polymorphic_enum_inner_build_build_fn(polymorphic_enum_inner_build_spec)
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicLeafEnum(polymorphic_leaf_enum_spec) => {
|
|
||||||
make_polymorphic_leaf_enum_build_fn(polymorphic_leaf_enum_spec)
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicTreeEnum(polymorphic_tree_enum_spec) => {
|
|
||||||
make_polymorphic_tree_enum_build_fn(polymorphic_tree_enum_spec)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
use crate::spec::polymorphic_enum_inner_build::PolymorphicEnumInnerBuild;
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
|
||||||
|
|
||||||
pub fn make_polymorphic_enum_inner_build_build_fn(spec: &PolymorphicEnumInnerBuild) -> TokenStream {
|
|
||||||
let build_fn_ident = format_ident!("{}", make_build_fn_name(spec.name()));
|
|
||||||
let pair_ident = format_ident!("{}", make_build_pair(spec.name()));
|
|
||||||
let return_type_ident = format_ident!("{}", spec.name());
|
|
||||||
|
|
||||||
let rule_branches = spec.rules()
|
|
||||||
.map(|rule| {
|
|
||||||
let rule_ident = format_ident!("{}", rule.name());
|
|
||||||
let rule_build_fn_ident = format_ident!("{}", rule.with());
|
|
||||||
quote! {
|
|
||||||
Rule::#rule_ident => #rule_build_fn_ident(file_id, inner_pair)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident {
|
|
||||||
let inner_pair = #pair_ident.into_inner().next().unwrap();
|
|
||||||
match inner_pair.as_rule() {
|
|
||||||
#(#rule_branches,)*
|
|
||||||
_ => unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
use crate::spec::polymorphic_leaf_enum::PolymorphicLeafEnum;
|
|
||||||
use convert_case::{Case, Casing};
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
|
|
||||||
pub fn make_polymorphic_leaf_enum_build_fn(spec: &PolymorphicLeafEnum) -> TokenStream {
|
|
||||||
let build_fn_ident = format_ident!("build_{}", spec.name().to_case(Case::Snake));
|
|
||||||
let pair_ident = format_ident!("{}_pair", spec.name().to_case(Case::Snake));
|
|
||||||
let return_type_ident = format_ident!("{}", spec.kind());
|
|
||||||
|
|
||||||
let child_matchers = spec.rules()
|
|
||||||
.map(|rule| {
|
|
||||||
let rule_ident = format_ident!("{}", rule);
|
|
||||||
quote! {
|
|
||||||
Rule::#rule_ident => #return_type_ident::#rule_ident
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident {
|
|
||||||
let inner_pair = #pair_ident.into_inner().next().unwrap();
|
|
||||||
match inner_pair.as_rule() {
|
|
||||||
#(#child_matchers,)*
|
|
||||||
_ => unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
use crate::spec::polymorphic_tree_enum_spec::PolymorphicTreeEnumSpec;
|
|
||||||
use convert_case::{Case, Casing};
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
|
|
||||||
pub fn make_polymorphic_tree_enum_build_fn(spec: &PolymorphicTreeEnumSpec) -> TokenStream {
|
|
||||||
let build_fn_ident = format_ident!("build_{}", spec.name().to_case(Case::Snake));
|
|
||||||
let pair_ident = format_ident!("{}_pair", spec.name().to_case(Case::Snake));
|
|
||||||
let return_type_ident = format_ident!("{}", spec.kind());
|
|
||||||
|
|
||||||
let rule_matchers = spec
|
|
||||||
.rules()
|
|
||||||
.map(|rule| {
|
|
||||||
let rule_ident = format_ident!("{}", rule);
|
|
||||||
let inner_build_fn_ident = format_ident!("build_{}", rule.to_case(Case::Snake));
|
|
||||||
quote! {
|
|
||||||
Rule::#rule_ident => #return_type_ident::#rule_ident(
|
|
||||||
#inner_build_fn_ident(file_id, inner_pair)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident {
|
|
||||||
let inner_pair = #pair_ident.into_inner().next().unwrap();
|
|
||||||
match inner_pair.as_rule() {
|
|
||||||
#(#rule_matchers,)*
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +1,8 @@
|
|||||||
mod leaf_enum_spec;
|
mod leaf_enum_spec;
|
||||||
mod leaf_struct_spec;
|
mod leaf_struct_spec;
|
||||||
mod node_production_spec;
|
mod node_production_spec;
|
||||||
mod polymorphic_enum_build_inner;
|
|
||||||
mod polymorphic_enum_loop_spec;
|
mod polymorphic_enum_loop_spec;
|
||||||
mod polymorphic_leaf_enum;
|
|
||||||
mod polymorphic_pass_through_spec;
|
mod polymorphic_pass_through_spec;
|
||||||
mod polymorphic_tree_enum;
|
|
||||||
mod polymorphic_type_spec;
|
mod polymorphic_type_spec;
|
||||||
mod production_spec;
|
mod production_spec;
|
||||||
mod struct_spec;
|
mod struct_spec;
|
||||||
@ -15,17 +12,14 @@ pub(crate) mod util;
|
|||||||
use crate::deserialize::leaf_enum_spec::deserialize_leaf_enum;
|
use crate::deserialize::leaf_enum_spec::deserialize_leaf_enum;
|
||||||
use crate::deserialize::leaf_struct_spec::deserialize_leaf_struct;
|
use crate::deserialize::leaf_struct_spec::deserialize_leaf_struct;
|
||||||
use crate::deserialize::node_production_spec::deserialize_node_production;
|
use crate::deserialize::node_production_spec::deserialize_node_production;
|
||||||
use crate::deserialize::polymorphic_enum_build_inner::deserialize_polymorphic_enum_inner_build;
|
|
||||||
use crate::deserialize::polymorphic_enum_loop_spec::deserialize_polymorphic_enum_loop;
|
use crate::deserialize::polymorphic_enum_loop_spec::deserialize_polymorphic_enum_loop;
|
||||||
use crate::deserialize::polymorphic_leaf_enum::deserialize_polymorphic_leaf_enum;
|
|
||||||
use crate::deserialize::polymorphic_pass_through_spec::deserialize_polymorphic_pass_through;
|
|
||||||
use crate::deserialize::polymorphic_type_spec::deserialize_polymorphic_type;
|
use crate::deserialize::polymorphic_type_spec::deserialize_polymorphic_type;
|
||||||
use crate::deserialize::production_spec::deserialize_production;
|
use crate::deserialize::production_spec::deserialize_production;
|
||||||
use crate::deserialize::struct_spec::deserialize_struct_spec;
|
use crate::deserialize::struct_spec::deserialize_struct_spec;
|
||||||
use crate::deserialize::tree_enum_spec::deserialize_tree_enum;
|
use crate::deserialize::tree_enum_spec::deserialize_tree_enum;
|
||||||
use crate::spec::BuildSpec;
|
use crate::spec::BuildSpec;
|
||||||
use yaml_rust2::{Yaml, YamlLoader};
|
use yaml_rust2::{Yaml, YamlLoader};
|
||||||
use crate::deserialize::polymorphic_tree_enum::deserialize_polymorphic_tree_enum;
|
use crate::deserialize::polymorphic_pass_through_spec::deserialize_polymorphic_pass_through;
|
||||||
|
|
||||||
fn deserialize_build_spec(build_spec_name: &str, build_spec: &Yaml) -> BuildSpec {
|
fn deserialize_build_spec(build_spec_name: &str, build_spec: &Yaml) -> BuildSpec {
|
||||||
if build_spec["struct"].is_hash() {
|
if build_spec["struct"].is_hash() {
|
||||||
@ -73,21 +67,6 @@ fn deserialize_build_spec(build_spec_name: &str, build_spec: &Yaml) -> BuildSpec
|
|||||||
build_spec_name,
|
build_spec_name,
|
||||||
&build_spec["polymorphic_pass_through"],
|
&build_spec["polymorphic_pass_through"],
|
||||||
))
|
))
|
||||||
} else if build_spec["polymorphic_enum_inner_build"].is_hash() {
|
|
||||||
BuildSpec::PolymorphicEnumInnerBuild(deserialize_polymorphic_enum_inner_build(
|
|
||||||
build_spec_name,
|
|
||||||
&build_spec["polymorphic_enum_inner_build"],
|
|
||||||
))
|
|
||||||
} else if build_spec["polymorphic_leaf_enum"].is_hash() {
|
|
||||||
BuildSpec::PolymorphicLeafEnum(deserialize_polymorphic_leaf_enum(
|
|
||||||
build_spec_name,
|
|
||||||
&build_spec["polymorphic_leaf_enum"],
|
|
||||||
))
|
|
||||||
} else if build_spec["polymorphic_tree_enum"].is_hash() {
|
|
||||||
BuildSpec::PolymorphicTreeEnum(deserialize_polymorphic_tree_enum(
|
|
||||||
build_spec_name,
|
|
||||||
&build_spec["polymorphic_tree_enum"],
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
panic!("Missing or incorrect build type for {}", build_spec_name);
|
panic!("Missing or incorrect build type for {}", build_spec_name);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,59 +0,0 @@
|
|||||||
use crate::deserialize::util::{make_build_fn_name, unwrap_single_member_hash};
|
|
||||||
use crate::spec::polymorphic_enum_inner_build::{
|
|
||||||
PolymorphicEnumInnerBuild, PolymorphicEnumInnerBuildMember,
|
|
||||||
PolymorphicEnumInnerBuildMemberKind, PolymorphicEnumInnerBuildRule,
|
|
||||||
};
|
|
||||||
use yaml_rust2::Yaml;
|
|
||||||
|
|
||||||
pub fn deserialize_polymorphic_enum_inner_build(
|
|
||||||
name: &str,
|
|
||||||
props: &Yaml,
|
|
||||||
) -> PolymorphicEnumInnerBuild {
|
|
||||||
let members = props["members"]
|
|
||||||
.as_vec()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|member| {
|
|
||||||
if let Some(name) = member.as_str() {
|
|
||||||
PolymorphicEnumInnerBuildMember::new(
|
|
||||||
name,
|
|
||||||
PolymorphicEnumInnerBuildMemberKind::Struct,
|
|
||||||
)
|
|
||||||
} else if member.is_hash() {
|
|
||||||
let (name, props) = unwrap_single_member_hash(member);
|
|
||||||
if let Some(kind) = props["kind"].as_str() {
|
|
||||||
match kind {
|
|
||||||
"leaf" => PolymorphicEnumInnerBuildMember::new(
|
|
||||||
&name,
|
|
||||||
PolymorphicEnumInnerBuildMemberKind::Leaf,
|
|
||||||
),
|
|
||||||
"struct" => PolymorphicEnumInnerBuildMember::new(
|
|
||||||
&name,
|
|
||||||
PolymorphicEnumInnerBuildMemberKind::Struct,
|
|
||||||
),
|
|
||||||
_ => panic!(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let rules = props["rules"]
|
|
||||||
.as_vec()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|rule| {
|
|
||||||
let rule_as_string = rule.as_str().unwrap().to_string();
|
|
||||||
PolymorphicEnumInnerBuildRule::new(
|
|
||||||
&rule_as_string,
|
|
||||||
&make_build_fn_name(&rule_as_string),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
PolymorphicEnumInnerBuild::new(name, members, rules)
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
use yaml_rust2::Yaml;
|
|
||||||
use crate::spec::polymorphic_leaf_enum::PolymorphicLeafEnum;
|
|
||||||
|
|
||||||
pub fn deserialize_polymorphic_leaf_enum(name: &str, props: &Yaml) -> PolymorphicLeafEnum {
|
|
||||||
let kind = props["kind"].as_str().unwrap();
|
|
||||||
let rules = props["rules"].as_vec().unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|rule| {
|
|
||||||
rule.as_str().unwrap().to_string()
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
PolymorphicLeafEnum::new(name, kind, rules)
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
use yaml_rust2::Yaml;
|
|
||||||
use crate::spec::polymorphic_tree_enum_spec::PolymorphicTreeEnumSpec;
|
|
||||||
|
|
||||||
pub fn deserialize_polymorphic_tree_enum(name: &str, props: &Yaml) -> PolymorphicTreeEnumSpec {
|
|
||||||
let kind = props["kind"].as_str().unwrap();
|
|
||||||
let rules = props["rules"].as_vec().unwrap()
|
|
||||||
.iter()
|
|
||||||
.map(|rule| rule.as_str().unwrap())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
PolymorphicTreeEnumSpec::new(name, kind, &rules)
|
|
||||||
}
|
|
||||||
@ -65,24 +65,6 @@ fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
|
|||||||
pass_through_build_spec.name()
|
pass_through_build_spec.name()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build_spec) => {
|
|
||||||
println!(
|
|
||||||
"Polymorphic Enum Inner Build Spec - name: {}",
|
|
||||||
polymorphic_enum_inner_build_spec.name()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicLeafEnum(polymorphic_leaf_enum) => {
|
|
||||||
println!(
|
|
||||||
"Polymorphic Leaf Enum Build Spec - name: {}",
|
|
||||||
polymorphic_leaf_enum.name()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicTreeEnum(polymorphic_tree_enum) => {
|
|
||||||
println!(
|
|
||||||
"Polymorphic Tree Enum Build Spec - name: {}",
|
|
||||||
polymorphic_tree_enum.name()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
println!("{:#?}", token_stream);
|
println!("{:#?}", token_stream);
|
||||||
let parsed: File = syn::parse2(token_stream.clone()).unwrap();
|
let parsed: File = syn::parse2(token_stream.clone()).unwrap();
|
||||||
|
|||||||
@ -10,56 +10,11 @@ use crate::spec::BuildSpec;
|
|||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use crate::spec::polymorphic_enum_inner_build::{PolymorphicEnumInnerBuild, PolymorphicEnumInnerBuildMember, PolymorphicEnumInnerBuildMemberKind};
|
|
||||||
|
|
||||||
fn make_result() -> TokenStream {
|
fn make_result() -> TokenStream {
|
||||||
quote! { std::fmt::Result }
|
quote! { std::fmt::Result }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_polymorphic_enum_inner_build_p2_impl(spec: &PolymorphicEnumInnerBuild) -> TokenStream {
|
|
||||||
let type_ident = format_ident!("{}", spec.name());
|
|
||||||
let result = make_result();
|
|
||||||
|
|
||||||
let type_string = spec.name();
|
|
||||||
|
|
||||||
let child_matchers = spec.members()
|
|
||||||
.map(|member| {
|
|
||||||
let variant_ident = format_ident!("{}", member.name());
|
|
||||||
match member.kind() {
|
|
||||||
PolymorphicEnumInnerBuildMemberKind::Leaf => {
|
|
||||||
let variant_string = member.name();
|
|
||||||
quote! {
|
|
||||||
#type_ident::#variant_ident => writer.writeln_indented(#variant_string)?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PolymorphicEnumInnerBuildMemberKind::Struct => {
|
|
||||||
let child_ident = format_ident!("{}", member.name().to_case(Case::Snake));
|
|
||||||
quote! {
|
|
||||||
#type_ident::#variant_ident(#child_ident) => {
|
|
||||||
#child_ident.pretty_print(writer)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
impl PrettyPrint for #type_ident {
|
|
||||||
fn pretty_print(&self, writer: &mut IndentWriter) -> #result {
|
|
||||||
writer.writeln_indented(#type_string)?;
|
|
||||||
writer.increase_indent();
|
|
||||||
match self {
|
|
||||||
#(#child_matchers,)*
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
writer.decrease_indent();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_polymorphic_enum_loop_p2_impl(spec: &PolymorphicEnumLoopBuildSpec) -> TokenStream {
|
fn make_polymorphic_enum_loop_p2_impl(spec: &PolymorphicEnumLoopBuildSpec) -> TokenStream {
|
||||||
let type_ident = format_ident!("{}", spec.name());
|
let type_ident = format_ident!("{}", spec.name());
|
||||||
let type_string = spec.name();
|
let type_string = spec.name();
|
||||||
@ -330,10 +285,5 @@ pub fn make_pretty_print_impl(build_spec: &BuildSpec) -> Option<TokenStream> {
|
|||||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
|
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
|
||||||
Some(make_polymorphic_enum_loop_p2_impl(polymorphic_enum_loop))
|
Some(make_polymorphic_enum_loop_p2_impl(polymorphic_enum_loop))
|
||||||
}
|
}
|
||||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build) => {
|
|
||||||
Some(make_polymorphic_enum_inner_build_p2_impl(polymorphic_enum_inner_build))
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicLeafEnum(_) => None,
|
|
||||||
BuildSpec::PolymorphicTreeEnum(_) => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +1,18 @@
|
|||||||
use polymorphic_leaf_enum::PolymorphicLeafEnum;
|
use crate::spec::node_production_spec::NodeProductionBuildSpec;
|
||||||
|
use crate::spec::polymorphic_enum_loop_spec::PolymorphicEnumLoopBuildSpec;
|
||||||
use leaf_enum_spec::LeafEnumBuildSpec;
|
use leaf_enum_spec::LeafEnumBuildSpec;
|
||||||
use leaf_struct_spec::LeafStructBuildSpec;
|
use leaf_struct_spec::LeafStructBuildSpec;
|
||||||
use node_production_spec::NodeProductionBuildSpec;
|
|
||||||
use polymorphic_enum_inner_build::PolymorphicEnumInnerBuild;
|
|
||||||
use polymorphic_enum_loop_spec::PolymorphicEnumLoopBuildSpec;
|
|
||||||
use polymorphic_pass_through_spec::PolymorphicPassThroughBuildSpec;
|
|
||||||
use polymorphic_type_spec::PolymorphicTypeBuildSpec;
|
use polymorphic_type_spec::PolymorphicTypeBuildSpec;
|
||||||
use production_spec::ProductionBuildSpec;
|
use production_spec::ProductionBuildSpec;
|
||||||
use struct_spec::StructSpec;
|
use struct_spec::StructSpec;
|
||||||
use tree_enum_spec::TreeEnumBuildSpec;
|
use tree_enum_spec::TreeEnumBuildSpec;
|
||||||
use polymorphic_tree_enum_spec::PolymorphicTreeEnumSpec;
|
use crate::spec::polymorphic_pass_through_spec::PolymorphicPassThroughBuildSpec;
|
||||||
|
|
||||||
pub(crate) mod leaf_enum_spec;
|
pub(crate) mod leaf_enum_spec;
|
||||||
pub(crate) mod leaf_struct_spec;
|
pub(crate) mod leaf_struct_spec;
|
||||||
pub(crate) mod node_production_spec;
|
pub(crate) mod node_production_spec;
|
||||||
pub(crate) mod polymorphic_enum_inner_build;
|
|
||||||
pub(crate) mod polymorphic_enum_loop_spec;
|
pub(crate) mod polymorphic_enum_loop_spec;
|
||||||
pub(crate) mod polymorphic_leaf_enum;
|
|
||||||
pub(crate) mod polymorphic_pass_through_spec;
|
pub(crate) mod polymorphic_pass_through_spec;
|
||||||
pub(crate) mod polymorphic_tree_enum_spec;
|
|
||||||
pub(crate) mod polymorphic_type_spec;
|
pub(crate) mod polymorphic_type_spec;
|
||||||
pub(crate) mod production_spec;
|
pub(crate) mod production_spec;
|
||||||
pub(crate) mod struct_spec;
|
pub(crate) mod struct_spec;
|
||||||
@ -33,8 +27,5 @@ pub enum BuildSpec {
|
|||||||
NodeProduction(NodeProductionBuildSpec),
|
NodeProduction(NodeProductionBuildSpec),
|
||||||
PolymorphicType(PolymorphicTypeBuildSpec),
|
PolymorphicType(PolymorphicTypeBuildSpec),
|
||||||
PolymorphicEnumLoop(PolymorphicEnumLoopBuildSpec),
|
PolymorphicEnumLoop(PolymorphicEnumLoopBuildSpec),
|
||||||
PolymorphicPassThrough(PolymorphicPassThroughBuildSpec),
|
PolymorphicPassThrough(PolymorphicPassThroughBuildSpec)
|
||||||
PolymorphicEnumInnerBuild(PolymorphicEnumInnerBuild),
|
|
||||||
PolymorphicLeafEnum(PolymorphicLeafEnum),
|
|
||||||
PolymorphicTreeEnum(PolymorphicTreeEnumSpec),
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,76 +0,0 @@
|
|||||||
pub struct PolymorphicEnumInnerBuild {
|
|
||||||
name: String,
|
|
||||||
members: Vec<PolymorphicEnumInnerBuildMember>,
|
|
||||||
rules: Vec<PolymorphicEnumInnerBuildRule>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PolymorphicEnumInnerBuild {
|
|
||||||
pub fn new(name: &str, members: Vec<PolymorphicEnumInnerBuildMember>, rules: Vec<PolymorphicEnumInnerBuildRule>) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
members,
|
|
||||||
rules,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn members(&self) -> impl Iterator<Item = &PolymorphicEnumInnerBuildMember> {
|
|
||||||
self.members.iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rules(&self) -> impl Iterator<Item = &PolymorphicEnumInnerBuildRule> {
|
|
||||||
self.rules.iter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PolymorphicEnumInnerBuildMember {
|
|
||||||
name: String,
|
|
||||||
kind: PolymorphicEnumInnerBuildMemberKind
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PolymorphicEnumInnerBuildMember {
|
|
||||||
pub fn new(name: &str, kind: PolymorphicEnumInnerBuildMemberKind) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
kind
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> &PolymorphicEnumInnerBuildMemberKind {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum PolymorphicEnumInnerBuildMemberKind {
|
|
||||||
Leaf,
|
|
||||||
Struct
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PolymorphicEnumInnerBuildRule {
|
|
||||||
name: String,
|
|
||||||
with: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PolymorphicEnumInnerBuildRule {
|
|
||||||
pub fn new(name: &str, with: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
with: with.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with(&self) -> &str {
|
|
||||||
&self.with
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
pub struct PolymorphicLeafEnum {
|
|
||||||
name: String,
|
|
||||||
kind: String,
|
|
||||||
rules: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PolymorphicLeafEnum {
|
|
||||||
pub fn new(name: &str, kind: &str, rules: Vec<String>) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
kind: kind.to_string(),
|
|
||||||
rules,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> &str {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rules(&self) -> impl Iterator<Item = &str> {
|
|
||||||
self.rules.iter().map(AsRef::as_ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
pub struct PolymorphicTreeEnumSpec {
|
|
||||||
name: String,
|
|
||||||
kind: String,
|
|
||||||
rules: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PolymorphicTreeEnumSpec {
|
|
||||||
pub fn new(name: &str, kind: &str, rules: &[&str]) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
kind: kind.to_string(),
|
|
||||||
rules: rules.iter().map(ToString::to_string).collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> &str {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rules(&self) -> impl Iterator<Item = &str> {
|
|
||||||
self.rules.iter().map(AsRef::as_ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,7 +1,6 @@
|
|||||||
mod enum_type;
|
mod enum_type;
|
||||||
mod leaf_enum_type;
|
mod leaf_enum_type;
|
||||||
mod leaf_struct_type;
|
mod leaf_struct_type;
|
||||||
mod polymorphic_enum_inner_build_type;
|
|
||||||
mod polymorphic_enum_loop_type;
|
mod polymorphic_enum_loop_type;
|
||||||
mod polymorphic_type_type;
|
mod polymorphic_type_type;
|
||||||
mod struct_type;
|
mod struct_type;
|
||||||
@ -10,11 +9,10 @@ use crate::spec::BuildSpec;
|
|||||||
use crate::type_gen::enum_type::make_enum_type;
|
use crate::type_gen::enum_type::make_enum_type;
|
||||||
use crate::type_gen::leaf_enum_type::make_leaf_enum_type;
|
use crate::type_gen::leaf_enum_type::make_leaf_enum_type;
|
||||||
use crate::type_gen::leaf_struct_type::make_leaf_struct_type;
|
use crate::type_gen::leaf_struct_type::make_leaf_struct_type;
|
||||||
use crate::type_gen::polymorphic_enum_inner_build_type::make_polymorphic_enum_inner_build_type;
|
|
||||||
use crate::type_gen::polymorphic_enum_loop_type::make_polymorphic_enum_loop_type;
|
|
||||||
use crate::type_gen::polymorphic_type_type::make_polymorphic_type_type;
|
use crate::type_gen::polymorphic_type_type::make_polymorphic_type_type;
|
||||||
use crate::type_gen::struct_type::make_struct_type;
|
use crate::type_gen::struct_type::make_struct_type;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
|
use crate::type_gen::polymorphic_enum_loop_type::make_polymorphic_enum_loop_type;
|
||||||
|
|
||||||
pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> {
|
pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||||
match build_spec {
|
match build_spec {
|
||||||
@ -33,12 +31,7 @@ pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> {
|
|||||||
}
|
}
|
||||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop_spec) => {
|
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop_spec) => {
|
||||||
Some(make_polymorphic_enum_loop_type(polymorphic_enum_loop_spec))
|
Some(make_polymorphic_enum_loop_type(polymorphic_enum_loop_spec))
|
||||||
}
|
},
|
||||||
BuildSpec::PolymorphicPassThrough(_) => None,
|
BuildSpec::PolymorphicPassThrough(_) => None,
|
||||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build_spec) => Some(
|
|
||||||
make_polymorphic_enum_inner_build_type(polymorphic_enum_inner_build_spec),
|
|
||||||
),
|
|
||||||
BuildSpec::PolymorphicLeafEnum(_) => None,
|
|
||||||
BuildSpec::PolymorphicTreeEnum(_) => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,25 +0,0 @@
|
|||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
use crate::spec::polymorphic_enum_inner_build::{PolymorphicEnumInnerBuild, PolymorphicEnumInnerBuildMemberKind};
|
|
||||||
|
|
||||||
pub fn make_polymorphic_enum_inner_build_type(spec: &PolymorphicEnumInnerBuild) -> TokenStream {
|
|
||||||
let members = spec.members()
|
|
||||||
.map(|member| {
|
|
||||||
let name_ident = format_ident!("{}", member.name());
|
|
||||||
match member.kind() {
|
|
||||||
PolymorphicEnumInnerBuildMemberKind::Leaf => {
|
|
||||||
quote! { #name_ident }
|
|
||||||
}
|
|
||||||
PolymorphicEnumInnerBuildMemberKind::Struct => {
|
|
||||||
quote! { #name_ident(#name_ident) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let type_name_ident = format_ident!("{}", spec.name());
|
|
||||||
quote! {
|
|
||||||
pub enum #type_name_ident {
|
|
||||||
#(#members,)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
use std::core::println
|
|
||||||
|
|
||||||
fn main(args: Array<String>)
|
|
||||||
let hello = 42
|
|
||||||
let world = hello + 16
|
|
||||||
println(hello)
|
|
||||||
println(world)
|
|
||||||
end
|
|
||||||
@ -1,260 +0,0 @@
|
|||||||
use crate::asm::{AsmBinaryOperator, AsmFunction, AsmInstruction, AsmOperand, ControlUnit, ControlUnitId, VirtualRegisterId};
|
|
||||||
use crate::ir::{IrAssign, IrBinaryOperation, IrBinaryOperator, IrCall, IrCallType, IrExpression, IrFunction, IrLiteral, IrReturn, IrStatement};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::ops::Deref;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
struct AssemblyContext {
|
|
||||||
control_unit_counter: ControlUnitId,
|
|
||||||
control_units: Vec<ControlUnit>,
|
|
||||||
virtual_register_counter: VirtualRegisterId,
|
|
||||||
virtual_registers: HashMap<Rc<str>, VirtualRegisterId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AssemblyContext {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
control_unit_counter: 0,
|
|
||||||
control_units: Vec::new(),
|
|
||||||
virtual_register_counter: 0,
|
|
||||||
virtual_registers: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_control_unit_id(&mut self) -> ControlUnitId {
|
|
||||||
let id = self.control_unit_counter;
|
|
||||||
self.control_unit_counter += 1;
|
|
||||||
id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_control_unit(&mut self) -> ControlUnitId {
|
|
||||||
let new_id = self.next_control_unit_id();
|
|
||||||
self.control_units.push(ControlUnit::new(new_id));
|
|
||||||
new_id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_control_unit(&mut self) -> &ControlUnit {
|
|
||||||
if self.control_units.is_empty() {
|
|
||||||
self.new_control_unit();
|
|
||||||
}
|
|
||||||
self.control_units.last().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_control_unit_mut(&mut self) -> &mut ControlUnit {
|
|
||||||
if self.control_units.is_empty() {
|
|
||||||
self.new_control_unit();
|
|
||||||
}
|
|
||||||
self.control_units.last_mut().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_control_units(self) -> Vec<ControlUnit> {
|
|
||||||
self.control_units
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_virtual_register(&self, name: &str) -> VirtualRegisterId {
|
|
||||||
*self
|
|
||||||
.virtual_registers
|
|
||||||
.get(name)
|
|
||||||
.expect(&format!("Did not set a virtual register for name {}", name))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn next_virtual_register(&mut self, name: &str) -> VirtualRegisterId {
|
|
||||||
if self.virtual_registers.contains_key(name) {
|
|
||||||
panic!(
|
|
||||||
"Should not already have a virtual register with name {}",
|
|
||||||
name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let virtual_register_id = self.virtual_register_counter;
|
|
||||||
self.virtual_register_counter += 1;
|
|
||||||
self.virtual_registers
|
|
||||||
.insert(name.into(), virtual_register_id);
|
|
||||||
virtual_register_id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn assemble_ir_function(ir_function: &IrFunction) -> AsmFunction {
|
|
||||||
let mut context = AssemblyContext::new();
|
|
||||||
|
|
||||||
// body
|
|
||||||
for statement in ir_function.statements() {
|
|
||||||
assemble_ir_statement(statement, &mut context);
|
|
||||||
}
|
|
||||||
|
|
||||||
AsmFunction::new(ir_function.name().into(), context.into_control_units())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assemble_ir_statement(ir_statement: &IrStatement, context: &mut AssemblyContext) {
|
|
||||||
match ir_statement {
|
|
||||||
IrStatement::Allocate(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
IrStatement::Call(ir_call) => {
|
|
||||||
assemble_ir_call(ir_call, context);
|
|
||||||
}
|
|
||||||
IrStatement::Return(ir_return) => {
|
|
||||||
assemble_ir_return(ir_return, context);
|
|
||||||
}
|
|
||||||
IrStatement::Assign(ir_assign) => {
|
|
||||||
assemble_ir_assign(ir_assign, context);
|
|
||||||
}
|
|
||||||
IrStatement::MakeClosure(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
IrStatement::BinaryOperation(ir_binary_operation) => {
|
|
||||||
assemble_ir_binary_operation(ir_binary_operation, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assemble_ir_assign(ir_assign: &IrAssign, context: &mut AssemblyContext) {
|
|
||||||
let source_operand = match ir_assign.rhs() {
|
|
||||||
IrExpression::Variable(ir_variable) => {
|
|
||||||
let virtual_register_id = context.get_virtual_register(ir_variable.name());
|
|
||||||
AsmOperand::VirtualRegister(virtual_register_id)
|
|
||||||
}
|
|
||||||
IrExpression::ConstRef(ir_const_ref) => AsmOperand::Constant {
|
|
||||||
name: ir_const_ref.name_owned(),
|
|
||||||
},
|
|
||||||
IrExpression::Literal(ir_literal) => ir_literal_to_asm_operand(ir_literal),
|
|
||||||
};
|
|
||||||
let destination = context.next_virtual_register(ir_assign.lhs().name());
|
|
||||||
context
|
|
||||||
.current_control_unit_mut()
|
|
||||||
.append_instruction(AsmInstruction::Move {
|
|
||||||
source: source_operand,
|
|
||||||
destination,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ir_literal_to_asm_operand(ir_literal: &IrLiteral) -> AsmOperand {
|
|
||||||
match ir_literal {
|
|
||||||
IrLiteral::I8(i) => AsmOperand::I8(*i),
|
|
||||||
IrLiteral::I16(i) => AsmOperand::I16(*i),
|
|
||||||
IrLiteral::I32(i) => AsmOperand::I32(*i),
|
|
||||||
IrLiteral::I64(i) => AsmOperand::I64(*i),
|
|
||||||
IrLiteral::I128(i) => AsmOperand::I128(*i),
|
|
||||||
IrLiteral::ISize(i) => AsmOperand::ISize(*i),
|
|
||||||
IrLiteral::U8(u) => AsmOperand::U8(*u),
|
|
||||||
IrLiteral::U16(u) => AsmOperand::U16(*u),
|
|
||||||
IrLiteral::U32(u) => AsmOperand::U32(*u),
|
|
||||||
IrLiteral::U64(u) => AsmOperand::U64(*u),
|
|
||||||
IrLiteral::U128(u) => AsmOperand::U128(*u),
|
|
||||||
IrLiteral::USize(u) => AsmOperand::USize(*u),
|
|
||||||
IrLiteral::Boolean(b) => AsmOperand::Boolean(*b),
|
|
||||||
IrLiteral::Float(f) => AsmOperand::Float(*f),
|
|
||||||
IrLiteral::Double(d) => AsmOperand::Double(*d),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assemble_ir_call(ir_call: &IrCall, context: &mut AssemblyContext) {
|
|
||||||
// push args
|
|
||||||
for argument in ir_call.arguments() {
|
|
||||||
match argument {
|
|
||||||
IrExpression::Variable(ir_variable) => {
|
|
||||||
let variable_register_id = context.get_virtual_register(ir_variable.name());
|
|
||||||
context
|
|
||||||
.current_control_unit_mut()
|
|
||||||
.append_instruction(AsmInstruction::Push {
|
|
||||||
source: AsmOperand::VirtualRegister(variable_register_id),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
IrExpression::ConstRef(ir_const_ref) => context
|
|
||||||
.current_control_unit_mut()
|
|
||||||
.append_instruction(AsmInstruction::Push {
|
|
||||||
source: AsmOperand::Constant {
|
|
||||||
name: ir_const_ref.name_owned(),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
IrExpression::Literal(ir_literal) => context
|
|
||||||
.current_control_unit_mut()
|
|
||||||
.append_instruction(AsmInstruction::Push {
|
|
||||||
source: ir_literal_to_asm_operand(ir_literal),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// issue call
|
|
||||||
match ir_call.call_type() {
|
|
||||||
IrCallType::Static => {
|
|
||||||
context
|
|
||||||
.current_control_unit_mut()
|
|
||||||
.append_instruction(AsmInstruction::InvokeStatic {
|
|
||||||
fqn: ir_call.function_name_owned(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
IrCallType::Object => {
|
|
||||||
context
|
|
||||||
.current_control_unit_mut()
|
|
||||||
.append_instruction(AsmInstruction::InvokeObject {
|
|
||||||
fqn: ir_call.function_name_owned(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assemble_ir_return(ir_return: &IrReturn, context: &mut AssemblyContext) {
|
|
||||||
let operand = match ir_return.expression() {
|
|
||||||
IrExpression::Variable(ir_variable) => {
|
|
||||||
let variable_virtual_register_id = context.get_virtual_register(ir_variable.name());
|
|
||||||
AsmOperand::VirtualRegister(variable_virtual_register_id)
|
|
||||||
}
|
|
||||||
IrExpression::ConstRef(ir_const_ref) => AsmOperand::Constant {
|
|
||||||
name: ir_const_ref.name_owned(),
|
|
||||||
},
|
|
||||||
IrExpression::Literal(ir_literal) => ir_literal_to_asm_operand(ir_literal),
|
|
||||||
};
|
|
||||||
context
|
|
||||||
.current_control_unit_mut()
|
|
||||||
.append_instruction(AsmInstruction::Return { operand });
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assemble_ir_binary_operation(ir_binary_operation: &IrBinaryOperation, context: &mut AssemblyContext) {
|
|
||||||
let left = match ir_binary_operation.left() {
|
|
||||||
IrExpression::Variable(ir_variable) => {
|
|
||||||
AsmOperand::VirtualRegister(context.get_virtual_register(ir_variable.name()))
|
|
||||||
}
|
|
||||||
IrExpression::ConstRef(ir_const_ref) => {
|
|
||||||
unreachable!("Cannot assemble binary operation with a lhs IrConstRef")
|
|
||||||
}
|
|
||||||
IrExpression::Literal(ir_literal) => {
|
|
||||||
ir_literal_to_asm_operand(ir_literal)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let right = match ir_binary_operation.right() {
|
|
||||||
IrExpression::Variable(ir_variable) => {
|
|
||||||
AsmOperand::VirtualRegister(context.get_virtual_register(ir_variable.name()))
|
|
||||||
},
|
|
||||||
IrExpression::ConstRef(ir_const_ref) => {
|
|
||||||
unreachable!("Cannot assemble binary operation with a rhs IrConstRef")
|
|
||||||
}
|
|
||||||
IrExpression::Literal(ir_literal) => {
|
|
||||||
ir_literal_to_asm_operand(ir_literal)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let destination = context.next_virtual_register(ir_binary_operation.destination().name());
|
|
||||||
let operator = match ir_binary_operation.operator() {
|
|
||||||
IrBinaryOperator::Add => {
|
|
||||||
AsmBinaryOperator::Add
|
|
||||||
}
|
|
||||||
IrBinaryOperator::Subtract => {
|
|
||||||
AsmBinaryOperator::Subtract
|
|
||||||
}
|
|
||||||
IrBinaryOperator::Multiply => {
|
|
||||||
AsmBinaryOperator::Multiply
|
|
||||||
}
|
|
||||||
IrBinaryOperator::Divide => {
|
|
||||||
AsmBinaryOperator::Divide
|
|
||||||
}
|
|
||||||
IrBinaryOperator::Exponent => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let instruction = AsmInstruction::BinaryOperation {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
operator
|
|
||||||
};
|
|
||||||
context.current_control_unit_mut().append_instruction(instruction);
|
|
||||||
}
|
|
||||||
240
src/asm/mod.rs
240
src/asm/mod.rs
@ -1,240 +0,0 @@
|
|||||||
pub mod assemble_ir;
|
|
||||||
|
|
||||||
use std::fmt::{Display, Formatter};
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub type ControlUnitId = usize;
|
|
||||||
|
|
||||||
pub type VirtualRegisterId = u32;
|
|
||||||
|
|
||||||
pub struct AsmFunction {
|
|
||||||
fqn: Rc<str>,
|
|
||||||
control_units: Vec<ControlUnit>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsmFunction {
|
|
||||||
pub fn new(fqn: Rc<str>, control_units: Vec<ControlUnit>) -> Self {
|
|
||||||
Self { fqn, control_units }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for AsmFunction {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
writeln!(f, "fn {}", self.fqn)?;
|
|
||||||
for control_unit in &self.control_units {
|
|
||||||
writeln!(f, " #{}:", control_unit.id)?;
|
|
||||||
for instruction in &control_unit.instructions {
|
|
||||||
writeln!(f, " {}", instruction)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ControlUnit {
|
|
||||||
id: ControlUnitId,
|
|
||||||
successor_ids: Vec<ControlUnitId>,
|
|
||||||
instructions: Vec<AsmInstruction>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ControlUnit {
|
|
||||||
pub fn new(id: ControlUnitId) -> Self {
|
|
||||||
Self {
|
|
||||||
id,
|
|
||||||
successor_ids: vec![],
|
|
||||||
instructions: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_instruction(&mut self, instruction: AsmInstruction) {
|
|
||||||
self.instructions.push(instruction);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_instructions(&mut self, instructions: Vec<AsmInstruction>) {
|
|
||||||
self.instructions.extend(instructions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum AsmInstruction {
|
|
||||||
Goto {
|
|
||||||
control_unit_id: ControlUnitId,
|
|
||||||
},
|
|
||||||
Move {
|
|
||||||
source: AsmOperand,
|
|
||||||
destination: VirtualRegisterId,
|
|
||||||
},
|
|
||||||
Push {
|
|
||||||
source: AsmOperand,
|
|
||||||
},
|
|
||||||
Pop {
|
|
||||||
destination: VirtualRegisterId,
|
|
||||||
},
|
|
||||||
Allocate {
|
|
||||||
class_name: Rc<str>,
|
|
||||||
destination: VirtualRegisterId,
|
|
||||||
},
|
|
||||||
InvokeStatic {
|
|
||||||
fqn: Rc<str>,
|
|
||||||
},
|
|
||||||
InvokeObject {
|
|
||||||
fqn: Rc<str>,
|
|
||||||
},
|
|
||||||
Return {
|
|
||||||
operand: AsmOperand,
|
|
||||||
},
|
|
||||||
BinaryOperation {
|
|
||||||
destination: VirtualRegisterId,
|
|
||||||
left: AsmOperand,
|
|
||||||
right: AsmOperand,
|
|
||||||
operator: AsmBinaryOperator,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for AsmInstruction {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
AsmInstruction::Goto { control_unit_id } => {
|
|
||||||
write!(f, "goto #{}", control_unit_id)
|
|
||||||
}
|
|
||||||
AsmInstruction::Move {
|
|
||||||
source,
|
|
||||||
destination,
|
|
||||||
} => {
|
|
||||||
write!(f, "move vr{}, {}", destination, source)
|
|
||||||
}
|
|
||||||
AsmInstruction::Push { source } => {
|
|
||||||
write!(f, "push {}", source)
|
|
||||||
}
|
|
||||||
AsmInstruction::Pop { destination } => {
|
|
||||||
write!(f, "pop vr{}", destination)
|
|
||||||
}
|
|
||||||
AsmInstruction::Allocate {
|
|
||||||
class_name,
|
|
||||||
destination,
|
|
||||||
} => {
|
|
||||||
write!(f, "allocate r{}, {}", destination, class_name)
|
|
||||||
}
|
|
||||||
AsmInstruction::InvokeStatic { fqn } => {
|
|
||||||
write!(f, "invoke_static {}", fqn)
|
|
||||||
}
|
|
||||||
AsmInstruction::InvokeObject { fqn } => {
|
|
||||||
write!(f, "invoke_object {}", fqn)
|
|
||||||
}
|
|
||||||
AsmInstruction::Return { operand } => {
|
|
||||||
write!(f, "return {}", operand)
|
|
||||||
}
|
|
||||||
AsmInstruction::BinaryOperation {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
operator,
|
|
||||||
} => {
|
|
||||||
write!(f, "op{} vr{}, {}, {}", operator, destination, left, right)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum AsmOperand {
|
|
||||||
I8(i8),
|
|
||||||
I16(i16),
|
|
||||||
I32(i32),
|
|
||||||
I64(i64),
|
|
||||||
I128(i128),
|
|
||||||
ISize(isize),
|
|
||||||
U8(u8),
|
|
||||||
U16(u16),
|
|
||||||
U32(u32),
|
|
||||||
U64(u64),
|
|
||||||
U128(u128),
|
|
||||||
USize(usize),
|
|
||||||
Float(f32),
|
|
||||||
Double(f64),
|
|
||||||
Boolean(bool),
|
|
||||||
Constant { name: Rc<str> },
|
|
||||||
VirtualRegister(VirtualRegisterId),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for AsmOperand {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
AsmOperand::I8(i) => {
|
|
||||||
write!(f, "{}i8", i)
|
|
||||||
}
|
|
||||||
AsmOperand::I16(i) => {
|
|
||||||
write!(f, "{}i16", i)
|
|
||||||
}
|
|
||||||
AsmOperand::I32(i) => {
|
|
||||||
write!(f, "{}i32", i)
|
|
||||||
}
|
|
||||||
AsmOperand::I64(i) => {
|
|
||||||
write!(f, "{}i64", i)
|
|
||||||
}
|
|
||||||
AsmOperand::I128(i) => {
|
|
||||||
write!(f, "{}i128", i)
|
|
||||||
}
|
|
||||||
AsmOperand::ISize(i) => {
|
|
||||||
write!(f, "{}isize", i)
|
|
||||||
}
|
|
||||||
AsmOperand::U8(u) => {
|
|
||||||
write!(f, "{}u8", u)
|
|
||||||
}
|
|
||||||
AsmOperand::U16(u) => {
|
|
||||||
write!(f, "{}u16", u)
|
|
||||||
}
|
|
||||||
AsmOperand::U32(u) => {
|
|
||||||
write!(f, "{}u32", u)
|
|
||||||
}
|
|
||||||
AsmOperand::U64(u) => {
|
|
||||||
write!(f, "{}u64", u)
|
|
||||||
}
|
|
||||||
AsmOperand::U128(u) => {
|
|
||||||
write!(f, "{}u128", u)
|
|
||||||
}
|
|
||||||
AsmOperand::USize(u) => {
|
|
||||||
write!(f, "{}usize", u)
|
|
||||||
}
|
|
||||||
AsmOperand::Float(float) => {
|
|
||||||
write!(f, "{}f32", float)
|
|
||||||
}
|
|
||||||
AsmOperand::Double(d) => {
|
|
||||||
write!(f, "{}f64", d)
|
|
||||||
}
|
|
||||||
AsmOperand::Boolean(b) => {
|
|
||||||
write!(f, "{}", b)
|
|
||||||
}
|
|
||||||
AsmOperand::Constant { name } => {
|
|
||||||
write!(f, "<{}>", name)
|
|
||||||
}
|
|
||||||
AsmOperand::VirtualRegister(id) => {
|
|
||||||
write!(f, "vr{}", id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum AsmBinaryOperator {
|
|
||||||
Add,
|
|
||||||
Subtract,
|
|
||||||
Multiply,
|
|
||||||
Divide,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for AsmBinaryOperator {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
AsmBinaryOperator::Add => {
|
|
||||||
write!(f, "+")
|
|
||||||
}
|
|
||||||
AsmBinaryOperator::Subtract => {
|
|
||||||
write!(f, "-")
|
|
||||||
}
|
|
||||||
AsmBinaryOperator::Multiply => {
|
|
||||||
write!(f, "*")
|
|
||||||
}
|
|
||||||
AsmBinaryOperator::Divide => {
|
|
||||||
write!(f, "/")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
use crate::name_analysis::name_analysis;
|
|
||||||
use deimos::asm::assemble_ir::assemble_ir_function;
|
|
||||||
use deimos::ast::node::CompilationUnit;
|
|
||||||
use deimos::ir::lower_ast::lower_compilation_unit;
|
|
||||||
use deimos::ir::Ir;
|
|
||||||
use deimos::util::indent_writer::IndentWriter;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
pub fn compile_to_ir(
|
|
||||||
paths: &[PathBuf],
|
|
||||||
) -> Result<Vec<CompilationUnit>, Box<dyn std::error::Error>> {
|
|
||||||
let compilation_units = name_analysis(&paths)?;
|
|
||||||
|
|
||||||
for compilation_unit in &compilation_units {
|
|
||||||
let cu_irs = lower_compilation_unit(compilation_unit);
|
|
||||||
let mut out = String::new();
|
|
||||||
let mut indent_writer = IndentWriter::new(0, " ", &mut out);
|
|
||||||
for ir in &cu_irs {
|
|
||||||
ir.pretty_print(&mut indent_writer)?;
|
|
||||||
}
|
|
||||||
println!("{}", &out);
|
|
||||||
|
|
||||||
for ir in &cu_irs {
|
|
||||||
match ir {
|
|
||||||
Ir::Function(ir_function) => {
|
|
||||||
let asm_function = assemble_ir_function(ir_function);
|
|
||||||
println!("{}", asm_function);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(compilation_units)
|
|
||||||
}
|
|
||||||
@ -1,4 +1,3 @@
|
|||||||
mod ir;
|
|
||||||
mod name_analysis;
|
mod name_analysis;
|
||||||
mod p3;
|
mod p3;
|
||||||
// mod unparse;
|
// mod unparse;
|
||||||
@ -9,7 +8,6 @@ use crate::name_analysis::name_analysis;
|
|||||||
use crate::p3::pretty_print_parse;
|
use crate::p3::pretty_print_parse;
|
||||||
// use crate::unparse::unparse;
|
// use crate::unparse::unparse;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use crate::ir::compile_to_ir;
|
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
#[command(name = "dmc")]
|
#[command(name = "dmc")]
|
||||||
@ -31,9 +29,6 @@ enum Commands {
|
|||||||
NameAnalysis {
|
NameAnalysis {
|
||||||
paths: Vec<PathBuf>,
|
paths: Vec<PathBuf>,
|
||||||
},
|
},
|
||||||
Ir {
|
|
||||||
paths: Vec<PathBuf>,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -55,12 +50,6 @@ fn main() {
|
|||||||
eprintln!("{}", e)
|
eprintln!("{}", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Commands::Ir { paths } => {
|
|
||||||
let result = compile_to_ir(&paths);
|
|
||||||
if let Err(e) = result {
|
|
||||||
eprintln!("{}", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,6 @@ use pest::Parser;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use deimos::ast::node::CompilationUnit;
|
|
||||||
|
|
||||||
struct ParseErrors {
|
struct ParseErrors {
|
||||||
errors: Vec<pest::error::Error<Rule>>,
|
errors: Vec<pest::error::Error<Rule>>,
|
||||||
@ -34,7 +33,7 @@ impl Display for ParseErrors {
|
|||||||
|
|
||||||
impl std::error::Error for ParseErrors {}
|
impl std::error::Error for ParseErrors {}
|
||||||
|
|
||||||
pub fn name_analysis(paths: &[PathBuf]) -> Result<Vec<CompilationUnit>, Box<dyn std::error::Error>> {
|
pub fn name_analysis(paths: &[PathBuf]) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut paths_and_sources: HashMap<String, String> = HashMap::new();
|
let mut paths_and_sources: HashMap<String, String> = HashMap::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();
|
||||||
@ -80,5 +79,5 @@ pub fn name_analysis(paths: &[PathBuf]) -> Result<Vec<CompilationUnit>, Box<dyn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(compilation_units)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,7 +87,7 @@ fn main() {
|
|||||||
// return 0
|
// return 0
|
||||||
MoveImmediate {
|
MoveImmediate {
|
||||||
destination_register: 2,
|
destination_register: 2,
|
||||||
immediate: Immediate::I32(0),
|
immediate: Immediate::Int(0),
|
||||||
},
|
},
|
||||||
SetReturnValue { source_register: 2 },
|
SetReturnValue { source_register: 2 },
|
||||||
Return, // explicit, not needed
|
Return, // explicit, not needed
|
||||||
@ -106,7 +106,7 @@ fn main() {
|
|||||||
let foo_function_instructions = vec![
|
let foo_function_instructions = vec![
|
||||||
MoveImmediate {
|
MoveImmediate {
|
||||||
destination_register: 0,
|
destination_register: 0,
|
||||||
immediate: Immediate::I32(42),
|
immediate: Immediate::Int(42),
|
||||||
},
|
},
|
||||||
SetReturnValue { source_register: 0 },
|
SetReturnValue { source_register: 0 },
|
||||||
Return, // explicit, not needed
|
Return, // explicit, not needed
|
||||||
|
|||||||
@ -1,669 +0,0 @@
|
|||||||
use crate::ast::node::{AdditiveExpression, AdditiveOperator, Call, Closure, CompilationUnit, Expression, ExpressionList, ExpressionStatement, Function, FunctionBlockBody, FunctionBody, Identifier, Literal, ModuleLevelDeclaration, Statement, SuffixExpression, SuffixOperator, VariableDeclaration};
|
|
||||||
use crate::ir::{
|
|
||||||
Ir, IrAssign, IrBinaryOperation, IrBinaryOperator, IrCall, IrCallType, IrConst, IrExpression,
|
|
||||||
IrFunction, IrKind, IrLiteral, IrPrimitiveKind, IrStatement, IrVariable,
|
|
||||||
};
|
|
||||||
use crate::name_analysis::symbol::{
|
|
||||||
ExpressibleSymbol, ParameterSymbol, PrimitiveTypeSymbol, TypeSymbol,
|
|
||||||
};
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use crate::ir::IrStatement::BinaryOperation;
|
|
||||||
|
|
||||||
pub fn lower_compilation_unit(compilation_unit: &CompilationUnit) -> Vec<Ir> {
|
|
||||||
let mut result: Vec<Ir> = vec![];
|
|
||||||
for declaration in compilation_unit.module_level_declarations() {
|
|
||||||
result.append(&mut lower_module_level_declaration(declaration));
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_module_level_declaration(declaration: &ModuleLevelDeclaration) -> Vec<Ir> {
|
|
||||||
match declaration {
|
|
||||||
ModuleLevelDeclaration::Module(module) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
ModuleLevelDeclaration::Interface(interface) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
ModuleLevelDeclaration::Class(class) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
ModuleLevelDeclaration::Function(function) => lower_function(function),
|
|
||||||
ModuleLevelDeclaration::PlatformFunction(platform_function) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LocalsTable {
|
|
||||||
t_count: usize,
|
|
||||||
stack_slot_count: usize,
|
|
||||||
stack_slots: HashMap<IrVariable, usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LocalsTable {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
t_count: 0,
|
|
||||||
stack_slot_count: 0,
|
|
||||||
stack_slots: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn next_t_var(&mut self) -> IrVariable {
|
|
||||||
let t_num = self.t_count;
|
|
||||||
self.t_count += 1;
|
|
||||||
let t_name = format!("__t{}", t_num);
|
|
||||||
let t_var = IrVariable::new(&t_name);
|
|
||||||
self.register_stack_local(&t_var);
|
|
||||||
t_var
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn register_stack_local(&mut self, ir_variable: &IrVariable) {
|
|
||||||
let stack_slot = self.stack_slot_count;
|
|
||||||
self.stack_slot_count += 1;
|
|
||||||
self.stack_slots.insert(ir_variable.clone(), stack_slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_stack_slot(&self, ir_variable: &IrVariable) -> usize {
|
|
||||||
*self.stack_slots.get(ir_variable).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_function(function: &Function) -> Vec<Ir> {
|
|
||||||
let function_symbol = function.function_symbol().unwrap().borrow();
|
|
||||||
let name = function_symbol.fqn_parts_owned().join("::");
|
|
||||||
let parameters = lower_parameter_symbols(function_symbol.parameter_symbols());
|
|
||||||
let return_type = lower_type_symbol(function_symbol.return_type().unwrap());
|
|
||||||
|
|
||||||
let mut locals_table = LocalsTable::new();
|
|
||||||
let (statements, consts) = lower_function_body(function.function_body(), &mut locals_table);
|
|
||||||
|
|
||||||
let mut result: Vec<Ir> = vec![];
|
|
||||||
result.push(Ir::Function(Box::new(IrFunction::new(
|
|
||||||
name,
|
|
||||||
parameters,
|
|
||||||
Box::new(return_type),
|
|
||||||
statements,
|
|
||||||
Box::new(locals_table),
|
|
||||||
))));
|
|
||||||
result.append(
|
|
||||||
&mut consts
|
|
||||||
.into_iter()
|
|
||||||
.map(|constant| Ir::Const(Box::new(constant)))
|
|
||||||
.collect(),
|
|
||||||
);
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_parameter_symbols(parameter_symbols: &[Rc<RefCell<ParameterSymbol>>]) -> Vec<IrKind> {
|
|
||||||
parameter_symbols
|
|
||||||
.iter()
|
|
||||||
.map(|parameter_symbol_rc| parameter_symbol_rc.borrow())
|
|
||||||
.map(|parameter_symbol| lower_type_symbol(parameter_symbol.type_symbol().unwrap()))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_type_symbol(type_symbol: &TypeSymbol) -> IrKind {
|
|
||||||
match type_symbol {
|
|
||||||
TypeSymbol::Primitive(primitive_type_symbol) => {
|
|
||||||
lower_primitive_type_symbol(primitive_type_symbol)
|
|
||||||
}
|
|
||||||
TypeSymbol::Class(class_type_symbol) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
TypeSymbol::Interface(interface_type_symbol) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
TypeSymbol::Generic(generic_type_symbol) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_primitive_type_symbol(primitive_type_symbol: &PrimitiveTypeSymbol) -> IrKind {
|
|
||||||
IrKind::Primitive(Box::new(match primitive_type_symbol {
|
|
||||||
PrimitiveTypeSymbol::Byte => IrPrimitiveKind::I8,
|
|
||||||
PrimitiveTypeSymbol::Char => IrPrimitiveKind::I8,
|
|
||||||
PrimitiveTypeSymbol::Short => IrPrimitiveKind::I16,
|
|
||||||
PrimitiveTypeSymbol::Int => IrPrimitiveKind::I32,
|
|
||||||
PrimitiveTypeSymbol::Long => IrPrimitiveKind::I64,
|
|
||||||
PrimitiveTypeSymbol::Float => IrPrimitiveKind::Float,
|
|
||||||
PrimitiveTypeSymbol::Double => IrPrimitiveKind::Double,
|
|
||||||
PrimitiveTypeSymbol::Boolean => IrPrimitiveKind::Boolean,
|
|
||||||
PrimitiveTypeSymbol::String => IrPrimitiveKind::String,
|
|
||||||
PrimitiveTypeSymbol::TypedArray { inner_type } => {
|
|
||||||
IrPrimitiveKind::Array(Box::new(lower_type_symbol(inner_type.as_ref().unwrap())))
|
|
||||||
}
|
|
||||||
PrimitiveTypeSymbol::Any => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
PrimitiveTypeSymbol::Void => IrPrimitiveKind::Void,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_function_body(
|
|
||||||
function_body: &FunctionBody,
|
|
||||||
locals_table: &mut LocalsTable,
|
|
||||||
) -> (Vec<IrStatement>, Vec<IrConst>) {
|
|
||||||
match function_body {
|
|
||||||
FunctionBody::FunctionAliasBody(alias_body) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
FunctionBody::FunctionEqualsBody(equals_body) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
FunctionBody::FunctionBlockBody(block_body) => {
|
|
||||||
lower_function_block_body(block_body, locals_table)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_function_block_body(
|
|
||||||
body: &FunctionBlockBody,
|
|
||||||
locals_table: &mut LocalsTable,
|
|
||||||
) -> (Vec<IrStatement>, Vec<IrConst>) {
|
|
||||||
let mut statements: Vec<IrStatement> = vec![];
|
|
||||||
let mut consts: Vec<IrConst> = vec![];
|
|
||||||
for statement in body.statements() {
|
|
||||||
statements.append(&mut lower_statement(statement, &mut consts, locals_table));
|
|
||||||
}
|
|
||||||
(statements, consts)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_statement(
|
|
||||||
statement: &Statement,
|
|
||||||
consts_pool: &mut Vec<IrConst>,
|
|
||||||
locals_table: &mut LocalsTable,
|
|
||||||
) -> Vec<IrStatement> {
|
|
||||||
match statement {
|
|
||||||
Statement::VariableDeclaration(variable_declaration) => {
|
|
||||||
lower_variable_declaration(variable_declaration, consts_pool, locals_table)
|
|
||||||
}
|
|
||||||
Statement::AssignmentStatement(assignment_statement) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Statement::ExpressionStatement(expression_statement) => {
|
|
||||||
lower_expression_statement(expression_statement, consts_pool, locals_table)
|
|
||||||
}
|
|
||||||
Statement::UseStatement(use_statement) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Statement::IfStatement(if_statement) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Statement::WhileStatement(while_statement) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Statement::ForStatement(for_statement) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_variable_declaration(
|
|
||||||
variable_declaration: &VariableDeclaration,
|
|
||||||
consts_pool: &mut Vec<IrConst>,
|
|
||||||
locals_table: &mut LocalsTable,
|
|
||||||
) -> Vec<IrStatement> {
|
|
||||||
let mut result: Vec<IrStatement> = vec![];
|
|
||||||
let expression_t_var = lower_expression(
|
|
||||||
variable_declaration.expression().unwrap(),
|
|
||||||
&mut result,
|
|
||||||
consts_pool,
|
|
||||||
locals_table,
|
|
||||||
);
|
|
||||||
let target = IrVariable::new(variable_declaration.identifier().name());
|
|
||||||
locals_table.register_stack_local(&target);
|
|
||||||
let assign_stmt = IrAssign::new(
|
|
||||||
Box::new(target),
|
|
||||||
Box::new(IrExpression::Variable(Box::new(expression_t_var))),
|
|
||||||
);
|
|
||||||
result.push(IrStatement::Assign(assign_stmt));
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_expression_statement(
|
|
||||||
expression_statement: &ExpressionStatement,
|
|
||||||
consts_pool: &mut Vec<IrConst>,
|
|
||||||
locals_table: &mut LocalsTable,
|
|
||||||
) -> Vec<IrStatement> {
|
|
||||||
let mut result: Vec<IrStatement> = vec![];
|
|
||||||
lower_expression(
|
|
||||||
expression_statement.expression(),
|
|
||||||
&mut result,
|
|
||||||
consts_pool,
|
|
||||||
locals_table,
|
|
||||||
);
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_expression(
|
|
||||||
expression: &Expression,
|
|
||||||
target: &mut Vec<IrStatement>,
|
|
||||||
consts_pool: &mut Vec<IrConst>,
|
|
||||||
locals_table: &mut LocalsTable,
|
|
||||||
) -> IrVariable {
|
|
||||||
match expression {
|
|
||||||
Expression::Ternary(ternary) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Or(or) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::And(and) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Comparison(comparison) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Shift(shift) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Additive(additive) => {
|
|
||||||
lower_additive_expression(additive, target, consts_pool, locals_table)
|
|
||||||
}
|
|
||||||
Expression::Multiplicative(multiplicative) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Prefix(prefix) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Suffix(suffix) => {
|
|
||||||
lower_suffix_expression(suffix, target, consts_pool, locals_table)
|
|
||||||
}
|
|
||||||
Expression::Literal(literal) => lower_literal(literal, target, consts_pool, locals_table),
|
|
||||||
Expression::Identifier(identifier_expression) => lower_identifier(
|
|
||||||
identifier_expression.identifier(),
|
|
||||||
target,
|
|
||||||
consts_pool,
|
|
||||||
locals_table,
|
|
||||||
),
|
|
||||||
Expression::Fqn(fqn) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Closure(closure) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::List(list) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_suffix_expression(
|
|
||||||
suffix_expression: &SuffixExpression,
|
|
||||||
target: &mut Vec<IrStatement>,
|
|
||||||
consts_pool: &mut Vec<IrConst>,
|
|
||||||
locals_table: &mut LocalsTable,
|
|
||||||
) -> IrVariable {
|
|
||||||
let receiver_variable = lower_expression(
|
|
||||||
suffix_expression.expression(),
|
|
||||||
target,
|
|
||||||
consts_pool,
|
|
||||||
locals_table,
|
|
||||||
);
|
|
||||||
match suffix_expression.operator() {
|
|
||||||
SuffixOperator::PlusPlus => {
|
|
||||||
let result_var = locals_table.next_t_var();
|
|
||||||
let operation = IrBinaryOperation::new(
|
|
||||||
result_var.clone(),
|
|
||||||
IrExpression::Variable(receiver_variable.into()),
|
|
||||||
IrExpression::Literal(IrLiteral::I32(1).into()),
|
|
||||||
IrBinaryOperator::Add,
|
|
||||||
);
|
|
||||||
target.push(IrStatement::BinaryOperation(operation));
|
|
||||||
result_var
|
|
||||||
}
|
|
||||||
SuffixOperator::MinusMinus => {
|
|
||||||
let result_var = locals_table.next_t_var();
|
|
||||||
let operation = IrBinaryOperation::new(
|
|
||||||
result_var.clone(),
|
|
||||||
IrExpression::Variable(receiver_variable.into()),
|
|
||||||
IrExpression::Literal(IrLiteral::I32(1).into()),
|
|
||||||
IrBinaryOperator::Subtract,
|
|
||||||
);
|
|
||||||
target.push(IrStatement::BinaryOperation(operation));
|
|
||||||
result_var
|
|
||||||
}
|
|
||||||
SuffixOperator::ObjectIndex(object_index) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
SuffixOperator::Call(call) => lower_call(
|
|
||||||
call,
|
|
||||||
suffix_expression.expression(),
|
|
||||||
target,
|
|
||||||
consts_pool,
|
|
||||||
locals_table,
|
|
||||||
),
|
|
||||||
SuffixOperator::ObjectProperty(object_property) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_literal(
|
|
||||||
literal: &Literal,
|
|
||||||
statements: &mut Vec<IrStatement>,
|
|
||||||
consts_pool: &mut Vec<IrConst>,
|
|
||||||
locals_table: &mut LocalsTable,
|
|
||||||
) -> IrVariable {
|
|
||||||
match literal {
|
|
||||||
Literal::IntLiteral(int_literal) => {
|
|
||||||
let t_var = locals_table.next_t_var();
|
|
||||||
let assign_stmt = IrAssign::new(
|
|
||||||
Box::new(t_var.clone()),
|
|
||||||
Box::new(IrExpression::Literal(Box::new(IrLiteral::I32(
|
|
||||||
*int_literal,
|
|
||||||
)))),
|
|
||||||
);
|
|
||||||
statements.push(IrStatement::Assign(assign_stmt));
|
|
||||||
t_var
|
|
||||||
}
|
|
||||||
Literal::LongLiteral(long_literal) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Literal::DoubleLiteral(double_literal) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Literal::SingleQuoteString(sq_string) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Literal::DString(d_string) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Literal::BacktickString(b_string) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Literal::BooleanLiteral(boolean_literal) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_call(
|
|
||||||
call: &Call,
|
|
||||||
receiver: &Expression,
|
|
||||||
target: &mut Vec<IrStatement>,
|
|
||||||
consts_pool: &mut Vec<IrConst>,
|
|
||||||
locals_table: &mut LocalsTable,
|
|
||||||
) -> IrVariable {
|
|
||||||
let fqn = match receiver {
|
|
||||||
Expression::Ternary(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Or(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::And(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Comparison(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Shift(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Additive(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Multiplicative(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Prefix(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Suffix(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Literal(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Identifier(identifier_expression) => {
|
|
||||||
match identifier_expression.expressible_symbol().unwrap() {
|
|
||||||
ExpressibleSymbol::Class(class_symbol) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
ExpressibleSymbol::Function(function_symbol) => {
|
|
||||||
function_symbol.borrow().fqn_formatted()
|
|
||||||
}
|
|
||||||
ExpressibleSymbol::ClassMember(class_member_symbol) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
ExpressibleSymbol::Parameter(parameter_symbol) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
ExpressibleSymbol::Variable(variable_symbol) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Expression::Fqn(fqn) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Closure(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::List(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let declared_type = match receiver {
|
|
||||||
Expression::Ternary(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Or(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::And(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Comparison(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Shift(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Additive(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Multiplicative(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Prefix(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Suffix(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Literal(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Identifier(identifier_expression) => {
|
|
||||||
match identifier_expression.expressible_symbol().unwrap() {
|
|
||||||
ExpressibleSymbol::Class(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
ExpressibleSymbol::Function(function_symbol) => {
|
|
||||||
match function_symbol.borrow().return_type().expect(&format!(
|
|
||||||
"Expected return type for fn {}",
|
|
||||||
function_symbol.borrow().fqn_formatted()
|
|
||||||
)) {
|
|
||||||
TypeSymbol::Primitive(primitive_type_symbol) => match primitive_type_symbol
|
|
||||||
{
|
|
||||||
PrimitiveTypeSymbol::Byte => {
|
|
||||||
IrKind::Primitive(IrPrimitiveKind::I8.into())
|
|
||||||
}
|
|
||||||
PrimitiveTypeSymbol::Char => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
PrimitiveTypeSymbol::Short => {
|
|
||||||
IrKind::Primitive(IrPrimitiveKind::I16.into())
|
|
||||||
}
|
|
||||||
PrimitiveTypeSymbol::Int => {
|
|
||||||
IrKind::Primitive(IrPrimitiveKind::I32.into())
|
|
||||||
}
|
|
||||||
PrimitiveTypeSymbol::Long => {
|
|
||||||
IrKind::Primitive(IrPrimitiveKind::I64.into())
|
|
||||||
}
|
|
||||||
PrimitiveTypeSymbol::Float => {
|
|
||||||
IrKind::Primitive(IrPrimitiveKind::Float.into())
|
|
||||||
}
|
|
||||||
PrimitiveTypeSymbol::Double => {
|
|
||||||
IrKind::Primitive(IrPrimitiveKind::Double.into())
|
|
||||||
}
|
|
||||||
PrimitiveTypeSymbol::Boolean => {
|
|
||||||
IrKind::Primitive(IrPrimitiveKind::Boolean.into())
|
|
||||||
}
|
|
||||||
PrimitiveTypeSymbol::String => {
|
|
||||||
IrKind::Primitive(IrPrimitiveKind::String.into())
|
|
||||||
}
|
|
||||||
PrimitiveTypeSymbol::TypedArray { inner_type } => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
PrimitiveTypeSymbol::Any => {
|
|
||||||
IrKind::Primitive(IrPrimitiveKind::Any.into())
|
|
||||||
}
|
|
||||||
PrimitiveTypeSymbol::Void => {
|
|
||||||
IrKind::Primitive(IrPrimitiveKind::Void.into())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
TypeSymbol::Class(class_symbol) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
TypeSymbol::Interface(interface_symbol) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
TypeSymbol::Generic(generic_symbol) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExpressibleSymbol::ClassMember(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
ExpressibleSymbol::Parameter(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
ExpressibleSymbol::Variable(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Expression::Fqn(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::Closure(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Expression::List(_) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let arg_vars = match call {
|
|
||||||
Call::ParenthesesCall(p_call) => {
|
|
||||||
let mut arg_vars: Vec<IrVariable> = vec![];
|
|
||||||
if let Some(expression_list) = p_call.expression_list() {
|
|
||||||
arg_vars.append(&mut lower_expression_list(
|
|
||||||
expression_list,
|
|
||||||
target,
|
|
||||||
consts_pool,
|
|
||||||
locals_table,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if let Some(closure) = p_call.closure() {
|
|
||||||
arg_vars.push(lower_closure(closure, target, consts_pool, locals_table));
|
|
||||||
}
|
|
||||||
arg_vars
|
|
||||||
}
|
|
||||||
Call::ClosureOnlyCall(c_call) => {
|
|
||||||
vec![lower_closure(
|
|
||||||
c_call.closure(),
|
|
||||||
target,
|
|
||||||
consts_pool,
|
|
||||||
locals_table,
|
|
||||||
)]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let arg_expressions = arg_vars
|
|
||||||
.iter()
|
|
||||||
.map(|ir_variable| IrExpression::Variable(ir_variable.clone().into()))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let result_var = locals_table.next_t_var();
|
|
||||||
let call = IrCall::new(
|
|
||||||
result_var.name(),
|
|
||||||
declared_type.into(),
|
|
||||||
&fqn,
|
|
||||||
IrCallType::Static,
|
|
||||||
arg_expressions,
|
|
||||||
);
|
|
||||||
target.push(IrStatement::Call(call));
|
|
||||||
result_var
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_expression_list(
|
|
||||||
expression_list: &ExpressionList,
|
|
||||||
target: &mut Vec<IrStatement>,
|
|
||||||
consts_pool: &mut Vec<IrConst>,
|
|
||||||
locals_table: &mut LocalsTable,
|
|
||||||
) -> Vec<IrVariable> {
|
|
||||||
let mut results: Vec<IrVariable> = vec![];
|
|
||||||
for expression in expression_list.expressions() {
|
|
||||||
results.push(lower_expression(
|
|
||||||
expression,
|
|
||||||
target,
|
|
||||||
consts_pool,
|
|
||||||
locals_table,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
results
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_closure(
|
|
||||||
closure: &Closure,
|
|
||||||
target: &mut Vec<IrStatement>,
|
|
||||||
consts_pool: &mut Vec<IrConst>,
|
|
||||||
locals_table: &mut LocalsTable,
|
|
||||||
) -> IrVariable {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_identifier(
|
|
||||||
identifier: &Identifier,
|
|
||||||
target: &mut Vec<IrStatement>,
|
|
||||||
consts_pool: &mut Vec<IrConst>,
|
|
||||||
locals_table: &mut LocalsTable,
|
|
||||||
) -> IrVariable {
|
|
||||||
IrVariable::new(identifier.name())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_additive_expression(
|
|
||||||
additive: &AdditiveExpression,
|
|
||||||
target: &mut Vec<IrStatement>,
|
|
||||||
consts_pool: &mut Vec<IrConst>,
|
|
||||||
locals_table: &mut LocalsTable,
|
|
||||||
) -> IrVariable {
|
|
||||||
let left_var = lower_expression(additive.left(), target, consts_pool, locals_table);
|
|
||||||
let right_var = lower_expression(additive.rhs().expression(), target, consts_pool, locals_table);
|
|
||||||
let destination = locals_table.next_t_var();
|
|
||||||
let operator = match additive.rhs().operator() {
|
|
||||||
AdditiveOperator::Add => {
|
|
||||||
IrBinaryOperator::Add
|
|
||||||
}
|
|
||||||
AdditiveOperator::Subtract => {
|
|
||||||
IrBinaryOperator::Subtract
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let operation = IrBinaryOperation::new(
|
|
||||||
destination.clone(),
|
|
||||||
IrExpression::Variable(left_var.into()),
|
|
||||||
IrExpression::Variable(right_var.into()),
|
|
||||||
operator
|
|
||||||
);
|
|
||||||
target.push(IrStatement::BinaryOperation(operation));
|
|
||||||
destination
|
|
||||||
}
|
|
||||||
@ -1,134 +0,0 @@
|
|||||||
use crate::ir::lower_ast::LocalsTable;
|
|
||||||
use crate::ir::{IrAllocable, IrAllocate, IrAssign, IrCall, IrExpression, IrFunction, IrLiteral, IrReturn, IrStatement};
|
|
||||||
use crate::vm::instruction::{Immediate, Instruction, Location};
|
|
||||||
use std::ops::Deref;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub fn lower_ir_function(ir_function: &IrFunction) -> Vec<Instruction> {
|
|
||||||
let mut instructions: Vec<Instruction> = vec![];
|
|
||||||
for statement in ir_function.statements() {
|
|
||||||
instructions.append(&mut lower_ir_statement(
|
|
||||||
statement,
|
|
||||||
ir_function.locals_table(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
instructions
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_ir_statement(ir_statement: &IrStatement, locals_table: &LocalsTable) -> Vec<Instruction> {
|
|
||||||
match ir_statement {
|
|
||||||
IrStatement::Allocate(allocate) => lower_ir_allocate(allocate),
|
|
||||||
IrStatement::Call(call) => lower_ir_call(call, locals_table),
|
|
||||||
IrStatement::Return(ir_return) => lower_return(ir_return, locals_table),
|
|
||||||
IrStatement::Assign(assign) => {
|
|
||||||
lower_ir_assign(assign, locals_table)
|
|
||||||
}
|
|
||||||
IrStatement::MakeClosure(make_closure) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
IrStatement::BinaryOperation(binary_operation) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_ir_allocate(ir_allocate: &IrAllocate) -> Vec<Instruction> {
|
|
||||||
let allocate_instruction = match ir_allocate.kind_to_alloc() {
|
|
||||||
IrAllocable::Struct(struct_kind) => Instruction::AllocateObject {
|
|
||||||
implementation_name: Rc::new(struct_kind.name().to_string()),
|
|
||||||
destination_register: 0,
|
|
||||||
},
|
|
||||||
IrAllocable::Array(array_kind) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let push_instruction = Instruction::Push { source_register: 0 };
|
|
||||||
vec![allocate_instruction, push_instruction]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_ir_call(ir_call: &IrCall, locals_table: &LocalsTable) -> Vec<Instruction> {
|
|
||||||
let mut instructions: Vec<Instruction> = vec![];
|
|
||||||
// push args
|
|
||||||
for argument in ir_call.arguments() {
|
|
||||||
lower_ir_expression(argument, &mut instructions, locals_table);
|
|
||||||
}
|
|
||||||
instructions
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_ir_expression(
|
|
||||||
ir_expression: &IrExpression,
|
|
||||||
instructions: &mut Vec<Instruction>,
|
|
||||||
locals_table: &LocalsTable,
|
|
||||||
) {
|
|
||||||
match ir_expression {
|
|
||||||
IrExpression::Variable(variable) => instructions.append(&mut vec![
|
|
||||||
Instruction::Copy {
|
|
||||||
source: Location::FramePointer {
|
|
||||||
offset: locals_table.get_stack_slot(variable) as isize,
|
|
||||||
},
|
|
||||||
destination: Location::Register(0),
|
|
||||||
},
|
|
||||||
Instruction::Push { source_register: 0 },
|
|
||||||
]),
|
|
||||||
IrExpression::ConstRef(const_ref) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
IrExpression::Literal(literal) => {
|
|
||||||
let immediate = match literal.deref() {
|
|
||||||
IrLiteral::I8(v) => Immediate::I8(*v),
|
|
||||||
IrLiteral::I16(v) => Immediate::I16(*v),
|
|
||||||
IrLiteral::I32(v) => Immediate::I32(*v),
|
|
||||||
IrLiteral::I64(v) => Immediate::I64(*v),
|
|
||||||
IrLiteral::I128(v) => Immediate::I128(*v),
|
|
||||||
IrLiteral::ISize(v) => Immediate::ISize(*v),
|
|
||||||
IrLiteral::U8(v) => Immediate::U8(*v),
|
|
||||||
IrLiteral::U16(v) => Immediate::U16(*v),
|
|
||||||
IrLiteral::U32(v) => Immediate::U32(*v),
|
|
||||||
IrLiteral::U64(v) => Immediate::U64(*v),
|
|
||||||
IrLiteral::U128(v) => Immediate::U128(*v),
|
|
||||||
IrLiteral::USize(v) => Immediate::USize(*v),
|
|
||||||
IrLiteral::Boolean(v) => Immediate::Boolean(*v),
|
|
||||||
IrLiteral::Float(v) => Immediate::Float(*v),
|
|
||||||
IrLiteral::Double(v) => Immediate::Double(*v),
|
|
||||||
};
|
|
||||||
instructions.append(&mut vec![
|
|
||||||
Instruction::MoveImmediate {
|
|
||||||
destination_register: 0,
|
|
||||||
immediate,
|
|
||||||
},
|
|
||||||
Instruction::Push { source_register: 0 },
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_return(ir_return: &IrReturn, locals_table: &LocalsTable) -> Vec<Instruction> {
|
|
||||||
let mut instructions: Vec<Instruction> = vec![];
|
|
||||||
lower_ir_expression(ir_return.expression(), &mut instructions, locals_table);
|
|
||||||
instructions.append(&mut vec![
|
|
||||||
Instruction::Pop {
|
|
||||||
destination_register: Some(0),
|
|
||||||
},
|
|
||||||
Instruction::PopFrame,
|
|
||||||
Instruction::Push { source_register: 0 },
|
|
||||||
Instruction::Return,
|
|
||||||
]);
|
|
||||||
instructions
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_ir_assign(ir_assign: &IrAssign, locals_table: &LocalsTable) -> Vec<Instruction> {
|
|
||||||
let mut instructions: Vec<Instruction> = vec![];
|
|
||||||
lower_ir_expression(ir_assign.rhs(), &mut instructions, locals_table);
|
|
||||||
instructions.append(&mut vec![
|
|
||||||
Instruction::Pop {
|
|
||||||
destination_register: Some(0),
|
|
||||||
},
|
|
||||||
Instruction::Copy {
|
|
||||||
source: Location::Register(0),
|
|
||||||
destination: Location::FramePointer {
|
|
||||||
offset: locals_table.get_stack_slot(ir_assign.lhs()) as isize,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
instructions
|
|
||||||
}
|
|
||||||
693
src/ir/mod.rs
693
src/ir/mod.rs
@ -1,90 +1,29 @@
|
|||||||
use crate::ir::lower_ast::LocalsTable;
|
pub enum DvmIr {
|
||||||
use crate::util::indent_writer::IndentWriter;
|
Struct(Box<DvmIrStruct>),
|
||||||
use std::fmt::{Display, Formatter};
|
Function(DvmIrFunction),
|
||||||
use std::rc::Rc;
|
Const(DvmIrConst),
|
||||||
|
|
||||||
pub mod lower_ast;
|
|
||||||
pub mod lower_ir;
|
|
||||||
|
|
||||||
pub enum Ir {
|
|
||||||
Struct(Box<IrStruct>),
|
|
||||||
Function(Box<IrFunction>),
|
|
||||||
PlatformFunction(Box<IrPlatformFunction>),
|
|
||||||
Const(Box<IrConst>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ir {
|
pub struct DvmIrStruct {
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Ir::Struct(ir_struct) => ir_struct.pretty_print(writer),
|
|
||||||
Ir::Function(ir_function) => ir_function.pretty_print(writer),
|
|
||||||
Ir::PlatformFunction(ir_platform_function) => ir_platform_function.pretty_print(writer),
|
|
||||||
Ir::Const(ir_const) => ir_const.pretty_print(writer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct IrStruct {
|
|
||||||
name: String,
|
name: String,
|
||||||
|
kind: Box<DvmIrKind>,
|
||||||
is_public: bool,
|
is_public: bool,
|
||||||
members: Vec<IrStructMember>,
|
members: Vec<Box<DvmIrStructMember>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrStruct {
|
pub struct DvmIrStructMember {
|
||||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
if self.is_public {
|
|
||||||
writer.writeln(&format!("pub struct {} {{", self.name))?;
|
|
||||||
} else {
|
|
||||||
writer.writeln(&format!("struct {} {{", self.name))?;
|
|
||||||
}
|
|
||||||
writer.increase_indent();
|
|
||||||
for member in &self.members {
|
|
||||||
member.pretty_print(writer)?;
|
|
||||||
writer.write("\n")?;
|
|
||||||
}
|
|
||||||
writer.decrease_indent();
|
|
||||||
writer.writeln("}")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct IrStructMember {
|
|
||||||
name: String,
|
name: String,
|
||||||
kind: Box<IrKind>,
|
kind: Box<DvmIrKind>,
|
||||||
is_public: bool,
|
is_public: bool,
|
||||||
is_mut: bool,
|
is_mut: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrStructMember {
|
pub enum DvmIrKind {
|
||||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
Primitive(Box<DvmIrPrimitiveKind>),
|
||||||
if self.is_public {
|
Struct(Box<DvmIrStructKind>),
|
||||||
writer.write("pub ")?;
|
|
||||||
}
|
|
||||||
if self.is_mut {
|
|
||||||
writer.write("mut ")?;
|
|
||||||
}
|
|
||||||
writer.write(&self.name)?;
|
|
||||||
writer.write(": ")?;
|
|
||||||
self.kind.pretty_print(writer)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum IrKind {
|
pub enum DvmIrPrimitiveKind {
|
||||||
Primitive(Box<IrPrimitiveKind>),
|
|
||||||
Struct(Box<IrStructKind>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IrKind {
|
|
||||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
IrKind::Primitive(primitive) => primitive.pretty_print(writer),
|
|
||||||
IrKind::Struct(struct_kind) => struct_kind.pretty_print(writer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum IrPrimitiveKind {
|
|
||||||
I8,
|
I8,
|
||||||
I16,
|
I16,
|
||||||
I32,
|
I32,
|
||||||
@ -97,438 +36,97 @@ pub enum IrPrimitiveKind {
|
|||||||
U64,
|
U64,
|
||||||
U128,
|
U128,
|
||||||
USize,
|
USize,
|
||||||
Float,
|
|
||||||
Double,
|
|
||||||
Boolean,
|
Boolean,
|
||||||
Array(Box<IrKind>),
|
Array(Box<DvmIrKind>),
|
||||||
String,
|
String,
|
||||||
Closure(Box<IrClosureKind>),
|
Closure(Box<DvmIrClosureKind>),
|
||||||
Ref(Box<IrKind>),
|
Ref(Box<DvmIrKind>),
|
||||||
Any,
|
|
||||||
Void,
|
Void,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrPrimitiveKind {
|
pub struct DvmIrStructKind {
|
||||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
IrPrimitiveKind::I8 => writer.write("i8"),
|
|
||||||
IrPrimitiveKind::I16 => writer.write("i16"),
|
|
||||||
IrPrimitiveKind::I32 => writer.write("i32"),
|
|
||||||
IrPrimitiveKind::I64 => writer.write("i64"),
|
|
||||||
IrPrimitiveKind::I128 => writer.write("i128"),
|
|
||||||
IrPrimitiveKind::ISize => writer.write("isize"),
|
|
||||||
IrPrimitiveKind::U8 => writer.write("u8"),
|
|
||||||
IrPrimitiveKind::U16 => writer.write("u16"),
|
|
||||||
IrPrimitiveKind::U32 => writer.write("u32"),
|
|
||||||
IrPrimitiveKind::U64 => writer.write("u64"),
|
|
||||||
IrPrimitiveKind::U128 => writer.write("u128"),
|
|
||||||
IrPrimitiveKind::USize => writer.write("usize"),
|
|
||||||
IrPrimitiveKind::Float => writer.write("f32"),
|
|
||||||
IrPrimitiveKind::Double => writer.write("f64"),
|
|
||||||
IrPrimitiveKind::Boolean => writer.write("boolean"),
|
|
||||||
IrPrimitiveKind::Array(kind) => {
|
|
||||||
writer.write("Array<")?;
|
|
||||||
kind.pretty_print(writer)?;
|
|
||||||
writer.write(">")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
IrPrimitiveKind::String => writer.write("String"),
|
|
||||||
IrPrimitiveKind::Closure(closure_kind) => writer.write("Closure"),
|
|
||||||
IrPrimitiveKind::Ref(ref_kind) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
IrPrimitiveKind::Any => writer.write("Any"),
|
|
||||||
IrPrimitiveKind::Void => writer.write("Void"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct IrStructKind {
|
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrStructKind {
|
pub struct DvmIrClosureKind {
|
||||||
pub fn new(name: &str) -> Self {
|
captures_name: String,
|
||||||
Self {
|
parameters: Vec<Box<DvmIrKind>>,
|
||||||
name: name.to_string(),
|
return_type: Box<DvmIrKind>,
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
writer.write(&self.name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IrClosureKind {
|
pub struct DvmIrFunction {
|
||||||
captures_struct_name: String,
|
|
||||||
parameters: Vec<IrKind>,
|
|
||||||
return_type: Box<IrKind>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct IrFunction {
|
|
||||||
name: String,
|
name: String,
|
||||||
parameters: Vec<IrKind>,
|
parameters: Vec<Box<DvmIrKind>>,
|
||||||
return_type: Box<IrKind>,
|
return_type: Box<DvmIrKind>,
|
||||||
statements: Vec<IrStatement>,
|
statements: Vec<Box<DvmIrStatement>>,
|
||||||
locals_table: Box<LocalsTable>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrFunction {
|
pub enum DvmIrStatement {
|
||||||
pub fn new(
|
Alloc(DvmIrAlloc),
|
||||||
name: String,
|
Call(DvmIrCallStmt),
|
||||||
parameters: Vec<IrKind>,
|
Ret(DvmIrRet),
|
||||||
return_type: Box<IrKind>,
|
Assign(DvmIrAssign),
|
||||||
statements: Vec<IrStatement>,
|
MakeClosure(DvmIrMakeClosure),
|
||||||
locals_table: Box<LocalsTable>,
|
Drop(DvmIrDrop),
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
name,
|
|
||||||
parameters,
|
|
||||||
return_type,
|
|
||||||
statements,
|
|
||||||
locals_table,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parameters(&self) -> &[IrKind] {
|
|
||||||
&self.parameters
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn return_type(&self) -> &IrKind {
|
|
||||||
&self.return_type
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn statements(&self) -> &[IrStatement] {
|
|
||||||
&self.statements
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn locals_table(&self) -> &LocalsTable {
|
|
||||||
&self.locals_table
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
writer.write("fn ")?;
|
|
||||||
writer.write(&self.name)?;
|
|
||||||
writer.write("(")?;
|
|
||||||
for (i, parameter) in self.parameters.iter().enumerate() {
|
|
||||||
parameter.pretty_print(writer)?;
|
|
||||||
if i != self.parameters.len() - 1 {
|
|
||||||
writer.write(", ")?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writer.write(") -> ")?;
|
|
||||||
self.return_type.pretty_print(writer)?;
|
|
||||||
writer.write(" {\n")?;
|
|
||||||
writer.increase_indent();
|
|
||||||
for statement in &self.statements {
|
|
||||||
statement.pretty_print(writer)?;
|
|
||||||
}
|
|
||||||
writer.decrease_indent();
|
|
||||||
writer.writeln("}")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IrPlatformFunction {
|
pub enum DvmIrAllocable {
|
||||||
name: String,
|
Struct(Box<DvmIrStructKind>),
|
||||||
parameters: Vec<IrKind>,
|
Array(Box<DvmIrArrayKind>),
|
||||||
return_type: Box<IrKind>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrPlatformFunction {
|
pub enum DvmIrArrayKind {
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
StaticSize(Box<DvmIrStaticArrayKind>),
|
||||||
writer.write("platform fn ")?;
|
DynamicSize(Box<DvmIrDynamicArrayKind>)
|
||||||
writer.write(&self.name)?;
|
|
||||||
writer.write("(")?;
|
|
||||||
for (i, parameter) in self.parameters.iter().enumerate() {
|
|
||||||
parameter.pretty_print(writer)?;
|
|
||||||
if i != self.parameters.len() - 1 {
|
|
||||||
writer.write(", ")?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writer.write(") -> ")?;
|
|
||||||
self.return_type.pretty_print(writer)?;
|
|
||||||
writer.write("\n")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum IrStatement {
|
pub struct DvmIrStaticArrayKind {
|
||||||
Allocate(IrAllocate),
|
inner_kind: Box<DvmIrKind>,
|
||||||
Call(IrCall),
|
|
||||||
Return(IrReturn),
|
|
||||||
Assign(IrAssign),
|
|
||||||
MakeClosure(IrMakeClosure),
|
|
||||||
BinaryOperation(IrBinaryOperation),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IrStatement {
|
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
IrStatement::Allocate(allocate) => allocate.pretty_print(writer),
|
|
||||||
IrStatement::Call(call) => call.pretty_print(writer),
|
|
||||||
IrStatement::Return(ir_return) => ir_return.pretty_print(writer),
|
|
||||||
IrStatement::Assign(assign) => assign.pretty_print(writer),
|
|
||||||
IrStatement::MakeClosure(make_closure) => make_closure.pretty_print(writer),
|
|
||||||
IrStatement::BinaryOperation(binary_operation) => binary_operation.pretty_print(writer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum IrAllocable {
|
|
||||||
Struct(Box<IrStructKind>),
|
|
||||||
Array(Box<IrArrayKind>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IrAllocable {
|
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
IrAllocable::Struct(struct_kind) => struct_kind.pretty_print(writer),
|
|
||||||
IrAllocable::Array(array_kind) => array_kind.pretty_print(writer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum IrArrayKind {
|
|
||||||
StaticSize(Box<IrStaticArrayKind>),
|
|
||||||
DynamicSize(Box<IrDynamicArrayKind>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IrArrayKind {
|
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
IrArrayKind::StaticSize(static_array_kind) => static_array_kind.pretty_print(writer),
|
|
||||||
IrArrayKind::DynamicSize(dynamic_array_kind) => dynamic_array_kind.pretty_print(writer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct IrStaticArrayKind {
|
|
||||||
inner_kind: Box<IrKind>,
|
|
||||||
size: usize,
|
size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrStaticArrayKind {
|
pub struct DvmIrDynamicArrayKind {
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
inner_kind: Box<DvmIrKind>,
|
||||||
writer.write("[")?;
|
size_expr: Box<DvmIrExpr>
|
||||||
self.inner_kind.pretty_print(writer)?;
|
|
||||||
writer.write(&format!("; {}]", self.size))?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IrDynamicArrayKind {
|
pub struct DvmIrAlloc {
|
||||||
inner_kind: Box<IrKind>,
|
declared_kind: Box<DvmIrAllocable>,
|
||||||
size_expr: Box<IrExpression>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IrDynamicArrayKind {
|
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
writer.write("[")?;
|
|
||||||
self.inner_kind.pretty_print(writer)?;
|
|
||||||
writer.write("; ")?;
|
|
||||||
self.size_expr.pretty_print(writer)?;
|
|
||||||
writer.write("]")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct IrAllocate {
|
|
||||||
name: String,
|
name: String,
|
||||||
declared_kind: Box<IrAllocable>,
|
kind_to_alloc: Box<DvmIrAllocable>,
|
||||||
kind_to_alloc: Box<IrAllocable>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrAllocate {
|
pub enum DvmIrConst {
|
||||||
pub fn name(&self) -> &str {
|
String(DvmIrStringConst),
|
||||||
&self.name
|
StringArray(DvmIrStringArrayConst),
|
||||||
}
|
|
||||||
|
|
||||||
pub fn declared_kind(&self) -> &IrAllocable {
|
|
||||||
&self.declared_kind
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind_to_alloc(&self) -> &IrAllocable {
|
|
||||||
&self.kind_to_alloc
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
writer.write_indented(&format!("let {}: ", self.name))?;
|
|
||||||
self.declared_kind.pretty_print(writer)?;
|
|
||||||
writer.write(" = alloc")?;
|
|
||||||
self.kind_to_alloc.pretty_print(writer)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IrBinaryOperation {
|
pub struct DvmIrStringConst {
|
||||||
destination: Box<IrVariable>,
|
|
||||||
left: Box<IrExpression>,
|
|
||||||
right: Box<IrExpression>,
|
|
||||||
operator: IrBinaryOperator,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IrBinaryOperation {
|
|
||||||
pub fn new(
|
|
||||||
destination: IrVariable,
|
|
||||||
left: IrExpression,
|
|
||||||
right: IrExpression,
|
|
||||||
operator: IrBinaryOperator,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
destination: destination.into(),
|
|
||||||
left: left.into(),
|
|
||||||
right: right.into(),
|
|
||||||
operator,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn destination(&self) -> &IrVariable {
|
|
||||||
&self.destination
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn left(&self) -> &IrExpression {
|
|
||||||
&self.left
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn right(&self) -> &IrExpression {
|
|
||||||
&self.right
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn operator(&self) -> &IrBinaryOperator {
|
|
||||||
&self.operator
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
writer.write_indented("")?;
|
|
||||||
self.destination.pretty_print(writer)?;
|
|
||||||
writer.write(" = ")?;
|
|
||||||
self.left.pretty_print(writer)?;
|
|
||||||
writer.write(&format!(" {} ", self.operator))?;
|
|
||||||
self.right.pretty_print(writer)?;
|
|
||||||
writer.writeln("")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum IrBinaryOperator {
|
|
||||||
Add,
|
|
||||||
Subtract,
|
|
||||||
Multiply,
|
|
||||||
Divide,
|
|
||||||
Exponent,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for IrBinaryOperator {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
IrBinaryOperator::Add => {
|
|
||||||
write!(f, "+")
|
|
||||||
}
|
|
||||||
IrBinaryOperator::Subtract => {
|
|
||||||
write!(f, "-")
|
|
||||||
}
|
|
||||||
IrBinaryOperator::Multiply => {
|
|
||||||
write!(f, "*")
|
|
||||||
}
|
|
||||||
IrBinaryOperator::Divide => {
|
|
||||||
write!(f, "/")
|
|
||||||
}
|
|
||||||
IrBinaryOperator::Exponent => {
|
|
||||||
write!(f, "^")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum IrConst {
|
|
||||||
String(IrStringConst),
|
|
||||||
StringArray(IrStringArrayConst),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IrConst {
|
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct IrStringConst {
|
|
||||||
name: String,
|
name: String,
|
||||||
value: String,
|
value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IrStringArrayConst {
|
pub struct DvmIrStringArrayConst {
|
||||||
name: String,
|
name: String,
|
||||||
value: Vec<String>,
|
value: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum IrExpression {
|
pub enum DvmIrExpr {
|
||||||
Variable(Box<IrVariable>),
|
Call(Box<DvmIrCallExpr>),
|
||||||
ConstRef(Box<IrConstRef>),
|
Variable(Box<DvmIrVariable>),
|
||||||
Literal(Box<IrLiteral>),
|
ConstRef(Box<DvmIrConstRef>),
|
||||||
|
Literal(Box<DvmIrLiteral>)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrExpression {
|
pub struct DvmIrVariable {
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
IrExpression::Variable(variable) => variable.pretty_print(writer),
|
|
||||||
IrExpression::ConstRef(const_ref) => const_ref.pretty_print(writer),
|
|
||||||
IrExpression::Literal(literal) => literal.pretty_print(writer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Hash, Eq, PartialEq)]
|
|
||||||
pub struct IrVariable {
|
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrVariable {
|
pub struct DvmIrConstRef {
|
||||||
pub fn new(name: &str) -> Self {
|
name: String,
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
writer.write(&self.name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IrConstRef {
|
pub enum DvmIrLiteral {
|
||||||
name: Rc<str>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IrConstRef {
|
|
||||||
pub fn new(name: Rc<str>) -> Self {
|
|
||||||
Self { name }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name_owned(&self) -> Rc<str> {
|
|
||||||
self.name.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
writer.write(&self.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum IrLiteral {
|
|
||||||
I8(i8),
|
I8(i8),
|
||||||
I16(i16),
|
I16(i16),
|
||||||
I32(i32),
|
I32(i32),
|
||||||
@ -542,161 +140,60 @@ pub enum IrLiteral {
|
|||||||
U128(u128),
|
U128(u128),
|
||||||
USize(usize),
|
USize(usize),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Float(f32),
|
|
||||||
Double(f64),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrLiteral {
|
pub struct DvmIrCallStmt {
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
declared_type: Box<DvmIrKind>,
|
||||||
match self {
|
name: String,
|
||||||
IrLiteral::I8(v) => writer.write(&format!("{}", v)),
|
call_expr: Box<DvmIrCallExpr>,
|
||||||
IrLiteral::I16(v) => writer.write(&format!("{}", v)),
|
|
||||||
IrLiteral::I32(v) => writer.write(&format!("{}", v)),
|
|
||||||
IrLiteral::I64(v) => writer.write(&format!("{}", v)),
|
|
||||||
IrLiteral::I128(v) => writer.write(&format!("{}", v)),
|
|
||||||
IrLiteral::ISize(v) => writer.write(&format!("{}", v)),
|
|
||||||
IrLiteral::U8(v) => writer.write(&format!("{}", v)),
|
|
||||||
IrLiteral::U16(v) => writer.write(&format!("{}", v)),
|
|
||||||
IrLiteral::U32(v) => writer.write(&format!("{}", v)),
|
|
||||||
IrLiteral::U64(v) => writer.write(&format!("{}", v)),
|
|
||||||
IrLiteral::U128(v) => writer.write(&format!("{}", v)),
|
|
||||||
IrLiteral::USize(v) => writer.write(&format!("{}", v)),
|
|
||||||
IrLiteral::Boolean(v) => writer.write(&format!("{}", v)),
|
|
||||||
IrLiteral::Float(v) => writer.write(&format!("{}", v)),
|
|
||||||
IrLiteral::Double(v) => writer.write(&format!("{}", v)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IrCall {
|
pub struct DvmIrCallExpr {
|
||||||
result_name: String,
|
name: String,
|
||||||
declared_type: Box<IrKind>,
|
arguments: Vec<Box<DvmIrExpr>>,
|
||||||
fqn: Rc<str>,
|
|
||||||
call_type: IrCallType,
|
|
||||||
arguments: Vec<IrExpression>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrCall {
|
pub struct DvmIrAssign {
|
||||||
pub fn new(
|
lhs: Box<DvmIrAssignLhs>,
|
||||||
result_name: &str,
|
rhs: Box<DvmIrExpr>
|
||||||
declared_type: Box<IrKind>,
|
|
||||||
fqn: &str,
|
|
||||||
call_type: IrCallType,
|
|
||||||
arguments: Vec<IrExpression>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
result_name: result_name.to_string(),
|
|
||||||
declared_type,
|
|
||||||
fqn: fqn.into(),
|
|
||||||
call_type,
|
|
||||||
arguments,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn result_name(&self) -> &str {
|
|
||||||
&self.result_name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn declared_type(&self) -> &IrKind {
|
|
||||||
&self.declared_type
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn function_name(&self) -> &str {
|
|
||||||
&self.fqn
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn function_name_owned(&self) -> Rc<str> {
|
|
||||||
self.fqn.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn call_type(&self) -> &IrCallType {
|
|
||||||
&self.call_type
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn arguments(&self) -> &[IrExpression] {
|
|
||||||
&self.arguments
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
writer.write_indented(&format!("{}: ", self.result_name))?;
|
|
||||||
self.declared_type.pretty_print(writer)?;
|
|
||||||
writer.write(&format!(" = call {}(", self.fqn))?;
|
|
||||||
for (i, argument) in self.arguments.iter().enumerate() {
|
|
||||||
argument.pretty_print(writer)?;
|
|
||||||
if i != self.arguments.len() - 1 {
|
|
||||||
writer.write(", ")?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writer.write(")\n")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum IrCallType {
|
pub struct DvmIrAssignLhs {
|
||||||
Static,
|
base: Box<DvmIrVariable>,
|
||||||
Object,
|
suffixes: Vec<Box<DvmIrAssignLhsSuffix>>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IrAssign {
|
pub enum DvmIrAssignLhsSuffix {
|
||||||
lhs: Box<IrVariable>,
|
Index(DvmIrAssignLhsIndex),
|
||||||
rhs: Box<IrExpression>,
|
Property(DvmIrAssignLhsProperty)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrAssign {
|
pub struct DvmIrAssignLhsIndex {
|
||||||
pub fn new(lhs: Box<IrVariable>, rhs: Box<IrExpression>) -> Self {
|
expr: Box<DvmIrExpr>,
|
||||||
Self { lhs, rhs }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn lhs(&self) -> &IrVariable {
|
|
||||||
&self.lhs
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rhs(&self) -> &IrExpression {
|
|
||||||
&self.rhs
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
writer.write_indented("")?;
|
|
||||||
self.lhs.pretty_print(writer)?;
|
|
||||||
writer.write(" = ")?;
|
|
||||||
self.rhs.pretty_print(writer)?;
|
|
||||||
writer.write("\n")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IrReturn {
|
pub struct DvmIrAssignLhsProperty {
|
||||||
expression: Box<IrExpression>,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrReturn {
|
pub struct DvmIrRet {
|
||||||
pub fn new(expression: Box<IrExpression>) -> Self {
|
value: Box<DvmIrReturnable>
|
||||||
Self { expression }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn expression(&self) -> &IrExpression {
|
|
||||||
&self.expression
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
|
||||||
writer.write_indented("return ")?;
|
|
||||||
self.expression.pretty_print(writer)?;
|
|
||||||
writer.write("\n")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IrMakeClosure {
|
pub enum DvmIrReturnable {
|
||||||
captures_kind: Option<Box<IrStructKind>>,
|
Variable(DvmIrVariable),
|
||||||
parameters: Vec<IrKind>,
|
Literal(DvmIrLiteral)
|
||||||
return_type: Box<IrKind>,
|
}
|
||||||
|
|
||||||
|
pub struct DvmIrMakeClosure {
|
||||||
|
captures_kind: Option<Box<DvmIrStructKind>>,
|
||||||
|
parameters: Vec<Box<DvmIrKind>>,
|
||||||
|
return_type: Box<DvmIrKind>,
|
||||||
name: String,
|
name: String,
|
||||||
fn_name: String,
|
fn_name: String,
|
||||||
captures_variable: Box<IrVariable>,
|
captures_variable: Box<DvmIrVariable>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrMakeClosure {
|
pub struct DvmIrDrop {
|
||||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
variable: Box<DvmIrVariable>,
|
||||||
todo!()
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -4,7 +4,6 @@
|
|||||||
#![allow(warnings)]
|
#![allow(warnings)]
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
||||||
pub mod asm;
|
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
pub mod diagnostic;
|
pub mod diagnostic;
|
||||||
pub mod ir;
|
pub mod ir;
|
||||||
|
|||||||
@ -1,13 +1,4 @@
|
|||||||
use crate::ast::node::{
|
use crate::ast::node::{AnySpaceSuffixOperator, AssignmentStatement, BacktickString, BoundSuffixOperator, Call, Closure, ClosureParameters, CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, DString, Expression, ExpressionList, ExpressionStatement, Function, FunctionAliasBody, FunctionBlockBody, FunctionBody, FunctionEqualsBody, GenericParameters, Identifier, IdentifierExpression, IdentifierOrFqn, LValue, LValueSuffix, Literal, ModuleLevelDeclaration, NoNewlineSuffixOperator, ObjectIndex, Parameter, Parameters, PlatformFunction, PrimitiveType, ReturnType, StarUseStatement, Statement, SuffixExpression, SuffixOperator, TypeUse, TypedArray, UseStatement, UseStatementIdentifier, UseStatementPrefix, VariableDeclaration};
|
||||||
AssignmentStatement, BacktickString, Call, Closure, ClosureParameters,
|
|
||||||
CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, DString, Expression,
|
|
||||||
ExpressionList, ExpressionStatement, Function, FunctionAliasBody, FunctionBlockBody,
|
|
||||||
FunctionBody, FunctionEqualsBody, GenericParameters, Identifier, IdentifierExpression,
|
|
||||||
IdentifierOrFqn, LValue, LValueSuffix, Literal, ModuleLevelDeclaration
|
|
||||||
, ObjectIndex, Parameter, Parameters, PlatformFunction, PrimitiveType,
|
|
||||||
ReturnType, StarUseStatement, Statement, SuffixExpression, SuffixOperator, TypeUse, TypedArray,
|
|
||||||
UseStatement, UseStatementIdentifier, UseStatementPrefix, VariableDeclaration,
|
|
||||||
};
|
|
||||||
use crate::diagnostic::DmDiagnostic;
|
use crate::diagnostic::DmDiagnostic;
|
||||||
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||||
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
|
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
|
||||||
@ -629,8 +620,7 @@ fn na_p2_expression(
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
Expression::Additive(additive) => {
|
Expression::Additive(additive) => {
|
||||||
na_p2_expression(additive.left_mut(), symbol_table, diagnostics);
|
todo!()
|
||||||
na_p2_expression(additive.rhs_mut().expression_mut(), symbol_table, diagnostics);
|
|
||||||
}
|
}
|
||||||
Expression::Multiplicative(multiplicative) => {
|
Expression::Multiplicative(multiplicative) => {
|
||||||
todo!()
|
todo!()
|
||||||
@ -678,16 +668,30 @@ fn na_p2_suffix_operator(
|
|||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
) {
|
) {
|
||||||
match suffix_operator {
|
match suffix_operator {
|
||||||
SuffixOperator::PlusPlus => {}
|
SuffixOperator::BoundSuffixOperator(bound_suffix) => {
|
||||||
SuffixOperator::MinusMinus => {}
|
match bound_suffix {
|
||||||
SuffixOperator::ObjectIndex(object_index) => {
|
BoundSuffixOperator::PlusPlus => {
|
||||||
na_p2_object_index(object_index, symbol_table, diagnostics);
|
// no-op
|
||||||
|
}
|
||||||
|
BoundSuffixOperator::MinusMinus => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SuffixOperator::Call(call) => {
|
SuffixOperator::NoNewlineSuffixOperator(no_newline_suffix) => match no_newline_suffix {
|
||||||
na_p2_call(call, symbol_table, diagnostics);
|
NoNewlineSuffixOperator::ObjectIndex(object_index) => {
|
||||||
}
|
na_p2_object_index(object_index, symbol_table, diagnostics);
|
||||||
SuffixOperator::ObjectProperty(object_property) => {
|
}
|
||||||
todo!()
|
NoNewlineSuffixOperator::Call(call) => {
|
||||||
|
na_p2_call(call, symbol_table, diagnostics);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
SuffixOperator::AnySpaceSuffixOperator(any_space_suffix) => {
|
||||||
|
match any_space_suffix {
|
||||||
|
AnySpaceSuffixOperator::ObjectProperty(_) => {
|
||||||
|
// no-op; this is checked during type checking
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,10 +50,6 @@ impl FunctionSymbol {
|
|||||||
return_type,
|
return_type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fqn_formatted(&self) -> String {
|
|
||||||
self.fqn_parts.join("::")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fqn_parts_owned(&self) -> Vec<Rc<str>> {
|
pub fn fqn_parts_owned(&self) -> Vec<Rc<str>> {
|
||||||
self.fqn_parts.to_vec()
|
self.fqn_parts.to_vec()
|
||||||
@ -82,10 +78,6 @@ impl FunctionSymbol {
|
|||||||
pub fn set_parameter_symbols(&mut self, parameter_symbols: Vec<Rc<RefCell<ParameterSymbol>>>) {
|
pub fn set_parameter_symbols(&mut self, parameter_symbols: Vec<Rc<RefCell<ParameterSymbol>>>) {
|
||||||
self.parameters = parameter_symbols;
|
self.parameters = parameter_symbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn return_type(&self) -> Option<&TypeSymbol> {
|
|
||||||
self.return_type.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_return_type(&mut self, type_symbol: TypeSymbol) {
|
pub fn set_return_type(&mut self, type_symbol: TypeSymbol) {
|
||||||
self.return_type = Some(type_symbol);
|
self.return_type = Some(type_symbol);
|
||||||
|
|||||||
@ -1158,34 +1158,23 @@ SuffixExpression:
|
|||||||
on_each:
|
on_each:
|
||||||
rule: SuffixOperator
|
rule: SuffixOperator
|
||||||
SuffixOperator:
|
SuffixOperator:
|
||||||
polymorphic_enum_inner_build:
|
tree_enum:
|
||||||
members:
|
|
||||||
- PlusPlus:
|
|
||||||
kind: leaf
|
|
||||||
- MinusMinus:
|
|
||||||
kind: leaf
|
|
||||||
- ObjectIndex
|
|
||||||
- Call
|
|
||||||
- ObjectProperty
|
|
||||||
rules:
|
rules:
|
||||||
- BoundSuffixOperator
|
- BoundSuffixOperator
|
||||||
- NoNewlineSuffixOperator
|
- NoNewlineSuffixOperator
|
||||||
- AnySpaceSuffixOperator
|
- AnySpaceSuffixOperator
|
||||||
BoundSuffixOperator:
|
BoundSuffixOperator:
|
||||||
polymorphic_leaf_enum:
|
leaf_enum:
|
||||||
kind: SuffixOperator
|
|
||||||
rules:
|
rules:
|
||||||
- PlusPlus
|
- PlusPlus
|
||||||
- MinusMinus
|
- MinusMinus
|
||||||
NoNewlineSuffixOperator:
|
NoNewlineSuffixOperator:
|
||||||
polymorphic_tree_enum:
|
tree_enum:
|
||||||
kind: SuffixOperator
|
|
||||||
rules:
|
rules:
|
||||||
- ObjectIndex
|
- ObjectIndex
|
||||||
- Call
|
- Call
|
||||||
AnySpaceSuffixOperator:
|
AnySpaceSuffixOperator:
|
||||||
polymorphic_tree_enum:
|
tree_enum:
|
||||||
kind: SuffixOperator
|
|
||||||
rules:
|
rules:
|
||||||
- ObjectProperty
|
- ObjectProperty
|
||||||
ObjectProperty:
|
ObjectProperty:
|
||||||
|
|||||||
@ -24,7 +24,7 @@ pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), Symbol
|
|||||||
true,
|
true,
|
||||||
None,
|
None,
|
||||||
&vec![Rc::new(RefCell::new(println_msg_symbol))],
|
&vec![Rc::new(RefCell::new(println_msg_symbol))],
|
||||||
Some(TypeSymbol::Primitive(PrimitiveTypeSymbol::Void)),
|
None,
|
||||||
);
|
);
|
||||||
symbol_table.register_function_symbol(println_symbol);
|
symbol_table.register_function_symbol(println_symbol);
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,6 @@ pub enum Instruction {
|
|||||||
Pop {
|
Pop {
|
||||||
destination_register: Option<usize>,
|
destination_register: Option<usize>,
|
||||||
},
|
},
|
||||||
PopFrame,
|
|
||||||
AllocateObject {
|
AllocateObject {
|
||||||
implementation_name: Rc<String>,
|
implementation_name: Rc<String>,
|
||||||
destination_register: usize,
|
destination_register: usize,
|
||||||
@ -118,21 +117,12 @@ pub enum Instruction {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Immediate {
|
pub enum Immediate {
|
||||||
I8(i8),
|
Byte(u8),
|
||||||
I16(i16),
|
Int(i32),
|
||||||
I32(i32),
|
Long(i64),
|
||||||
I64(i64),
|
|
||||||
I128(i128),
|
|
||||||
ISize(isize),
|
|
||||||
U8(u8),
|
|
||||||
U16(u16),
|
|
||||||
U32(u32),
|
|
||||||
U64(u64),
|
|
||||||
U128(u128),
|
|
||||||
USize(usize),
|
|
||||||
Boolean(bool),
|
|
||||||
Float(f32),
|
|
||||||
Double(f64),
|
Double(f64),
|
||||||
|
Usize(usize),
|
||||||
|
Boolean(bool),
|
||||||
Constant(DvmConstant),
|
Constant(DvmConstant),
|
||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
@ -140,10 +130,10 @@ pub enum Immediate {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Location {
|
pub enum Location {
|
||||||
Register(usize),
|
Register(usize),
|
||||||
FramePointer {
|
StackFrameBase {
|
||||||
offset: isize,
|
offset: isize,
|
||||||
},
|
},
|
||||||
StackPointer {
|
StackTop {
|
||||||
offset: isize,
|
offset: isize,
|
||||||
},
|
},
|
||||||
Field {
|
Field {
|
||||||
|
|||||||
@ -224,7 +224,7 @@ fn compute_index_with_offset(
|
|||||||
fn copy_from_source(state: &DvmState, source: &Location) -> DvmValue {
|
fn copy_from_source(state: &DvmState, source: &Location) -> DvmValue {
|
||||||
match source {
|
match source {
|
||||||
Location::Register(register) => state.registers[*register].clone(),
|
Location::Register(register) => state.registers[*register].clone(),
|
||||||
Location::FramePointer { offset } => {
|
Location::StackFrameBase { offset } => {
|
||||||
let index = if offset.is_negative() {
|
let index = if offset.is_negative() {
|
||||||
state.frame_base_index - offset.unsigned_abs()
|
state.frame_base_index - offset.unsigned_abs()
|
||||||
} else {
|
} else {
|
||||||
@ -232,7 +232,7 @@ fn copy_from_source(state: &DvmState, source: &Location) -> DvmValue {
|
|||||||
};
|
};
|
||||||
state.stack[index].clone()
|
state.stack[index].clone()
|
||||||
}
|
}
|
||||||
Location::StackPointer { offset } => {
|
Location::StackTop { offset } => {
|
||||||
if *offset >= 0 {
|
if *offset >= 0 {
|
||||||
dvm_panic!(
|
dvm_panic!(
|
||||||
state,
|
state,
|
||||||
@ -272,7 +272,7 @@ fn write_to_destination(state: &mut DvmState, destination: &Location, value: Dvm
|
|||||||
Location::Register(register) => {
|
Location::Register(register) => {
|
||||||
state.registers[*register] = value;
|
state.registers[*register] = value;
|
||||||
}
|
}
|
||||||
Location::FramePointer { offset } => {
|
Location::StackFrameBase { offset } => {
|
||||||
let index = if offset.is_negative() {
|
let index = if offset.is_negative() {
|
||||||
state.frame_base_index - offset.unsigned_abs()
|
state.frame_base_index - offset.unsigned_abs()
|
||||||
} else {
|
} else {
|
||||||
@ -280,7 +280,7 @@ fn write_to_destination(state: &mut DvmState, destination: &Location, value: Dvm
|
|||||||
};
|
};
|
||||||
state.stack[index] = value;
|
state.stack[index] = value;
|
||||||
}
|
}
|
||||||
Location::StackPointer { offset } => {
|
Location::StackTop { offset } => {
|
||||||
if *offset >= 0 {
|
if *offset >= 0 {
|
||||||
dvm_panic!(
|
dvm_panic!(
|
||||||
state,
|
state,
|
||||||
@ -344,7 +344,14 @@ fn constant_to_value(constant: &DvmConstant) -> DvmValue {
|
|||||||
|
|
||||||
fn immediate_to_value(immediate: &Immediate) -> DvmValue {
|
fn immediate_to_value(immediate: &Immediate) -> DvmValue {
|
||||||
match immediate {
|
match immediate {
|
||||||
_ => todo!()
|
Immediate::Byte(b) => DvmValue::Byte(*b),
|
||||||
|
Immediate::Int(i) => DvmValue::Int(*i),
|
||||||
|
Immediate::Long(l) => DvmValue::Long(*l),
|
||||||
|
Immediate::Double(d) => DvmValue::Double(*d),
|
||||||
|
Immediate::Usize(s) => DvmValue::USize(*s),
|
||||||
|
Immediate::Boolean(b) => DvmValue::Boolean(*b),
|
||||||
|
Immediate::Constant(c) => constant_to_value(c),
|
||||||
|
Immediate::Empty => DvmValue::Empty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,7 +411,6 @@ pub fn run(instructions: &[Instruction], state: &mut DvmState, context: &DvmCont
|
|||||||
state.registers[*register_index] = value;
|
state.registers[*register_index] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PopFrame => {}
|
|
||||||
AllocateObject {
|
AllocateObject {
|
||||||
implementation_name,
|
implementation_name,
|
||||||
destination_register,
|
destination_register,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user