Compare commits

..

4 Commits

35 changed files with 2585 additions and 165 deletions

View File

@ -1,6 +1,7 @@
mod enum_ast_node;
mod leaf_enum_ast_node;
mod leaf_struct_ast_node;
mod polymorphic_enum_inner_build_ast_node;
mod polymorphic_enum_loop_ast_node;
mod polymorphic_type_ast_node;
mod struct_ast_node;
@ -8,6 +9,7 @@ mod struct_ast_node;
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_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_type_ast_node::make_polymorphic_type_ast_node_impl;
use crate::ast_node::struct_ast_node::make_struct_ast_node_impl;
@ -30,6 +32,11 @@ pub fn make_ast_node_impl(build_spec: &BuildSpec) -> Option<TokenStream> {
make_polymorphic_enum_loop_ast_node_impl(polymorphic_enum_loop),
),
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,
}
}
@ -48,6 +55,11 @@ fn make_type_ident(build_spec: &BuildSpec) -> Option<Ident> {
BuildSpec::PolymorphicPassThrough(_) => None,
BuildSpec::Production(_) => None,
BuildSpec::NodeProduction(_) => None,
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build) => {
Some(format_ident!("{}", polymorphic_enum_inner_build.name()))
}
BuildSpec::PolymorphicLeafEnum(_) => None,
BuildSpec::PolymorphicTreeEnum(_) => None,
}
}
@ -81,4 +93,4 @@ pub fn make_ast_node_ref_mut_unwrapper(build_spec: &BuildSpec) -> Option<TokenSt
AstNodeRefMut::#type_ident(inner) => *inner
}
})
}
}

View File

@ -0,0 +1,76 @@
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)
}
}
}
}

View File

@ -1,20 +1,26 @@
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 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 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_struct_build_fn;
mod node_production_build_fn;
mod polymorphic_enum_inner_build_build_fn;
mod polymorphic_enum_loop_build_fn;
mod polymorphic_leaf_enum_build_fn;
mod polymorphic_pass_through_build_fn;
mod polymorphic_tree_enum_build_fn;
mod polymorphic_type_build_fn;
mod production_build_fn;
mod struct_build_fn;
@ -39,5 +45,14 @@ pub fn make_build_fn(build_spec: &BuildSpec) -> TokenStream {
BuildSpec::PolymorphicPassThrough(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)
}
}
}

View File

@ -0,0 +1,30 @@
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!()
}
}
}
}

View File

@ -0,0 +1,29 @@
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!()
}
}
}
}

View File

@ -0,0 +1,33 @@
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!(),
}
}
}
}

View File

@ -1,8 +1,11 @@
mod leaf_enum_spec;
mod leaf_struct_spec;
mod node_production_spec;
mod polymorphic_enum_build_inner;
mod polymorphic_enum_loop_spec;
mod polymorphic_leaf_enum;
mod polymorphic_pass_through_spec;
mod polymorphic_tree_enum;
mod polymorphic_type_spec;
mod production_spec;
mod struct_spec;
@ -12,14 +15,17 @@ pub(crate) mod util;
use crate::deserialize::leaf_enum_spec::deserialize_leaf_enum;
use crate::deserialize::leaf_struct_spec::deserialize_leaf_struct;
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_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::production_spec::deserialize_production;
use crate::deserialize::struct_spec::deserialize_struct_spec;
use crate::deserialize::tree_enum_spec::deserialize_tree_enum;
use crate::spec::BuildSpec;
use yaml_rust2::{Yaml, YamlLoader};
use crate::deserialize::polymorphic_pass_through_spec::deserialize_polymorphic_pass_through;
use crate::deserialize::polymorphic_tree_enum::deserialize_polymorphic_tree_enum;
fn deserialize_build_spec(build_spec_name: &str, build_spec: &Yaml) -> BuildSpec {
if build_spec["struct"].is_hash() {
@ -67,6 +73,21 @@ fn deserialize_build_spec(build_spec_name: &str, build_spec: &Yaml) -> BuildSpec
build_spec_name,
&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 {
panic!("Missing or incorrect build type for {}", build_spec_name);
}

View File

@ -0,0 +1,59 @@
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)
}

View File

@ -0,0 +1,13 @@
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)
}

View File

@ -0,0 +1,12 @@
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)
}

View File

@ -65,6 +65,24 @@ fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
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);
let parsed: File = syn::parse2(token_stream.clone()).unwrap();

View File

@ -10,11 +10,56 @@ use crate::spec::BuildSpec;
use convert_case::{Case, Casing};
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use crate::spec::polymorphic_enum_inner_build::{PolymorphicEnumInnerBuild, PolymorphicEnumInnerBuildMember, PolymorphicEnumInnerBuildMemberKind};
fn make_result() -> TokenStream {
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 {
let type_ident = format_ident!("{}", spec.name());
let type_string = spec.name();
@ -285,5 +330,10 @@ pub fn make_pretty_print_impl(build_spec: &BuildSpec) -> Option<TokenStream> {
BuildSpec::PolymorphicEnumLoop(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,
}
}

View File

@ -1,18 +1,24 @@
use crate::spec::node_production_spec::NodeProductionBuildSpec;
use crate::spec::polymorphic_enum_loop_spec::PolymorphicEnumLoopBuildSpec;
use polymorphic_leaf_enum::PolymorphicLeafEnum;
use leaf_enum_spec::LeafEnumBuildSpec;
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 production_spec::ProductionBuildSpec;
use struct_spec::StructSpec;
use tree_enum_spec::TreeEnumBuildSpec;
use crate::spec::polymorphic_pass_through_spec::PolymorphicPassThroughBuildSpec;
use polymorphic_tree_enum_spec::PolymorphicTreeEnumSpec;
pub(crate) mod leaf_enum_spec;
pub(crate) mod leaf_struct_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_leaf_enum;
pub(crate) mod polymorphic_pass_through_spec;
pub(crate) mod polymorphic_tree_enum_spec;
pub(crate) mod polymorphic_type_spec;
pub(crate) mod production_spec;
pub(crate) mod struct_spec;
@ -27,5 +33,8 @@ pub enum BuildSpec {
NodeProduction(NodeProductionBuildSpec),
PolymorphicType(PolymorphicTypeBuildSpec),
PolymorphicEnumLoop(PolymorphicEnumLoopBuildSpec),
PolymorphicPassThrough(PolymorphicPassThroughBuildSpec)
PolymorphicPassThrough(PolymorphicPassThroughBuildSpec),
PolymorphicEnumInnerBuild(PolymorphicEnumInnerBuild),
PolymorphicLeafEnum(PolymorphicLeafEnum),
PolymorphicTreeEnum(PolymorphicTreeEnumSpec),
}

View File

@ -0,0 +1,76 @@
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
}
}

View File

@ -0,0 +1,27 @@
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)
}
}

View File

@ -0,0 +1,27 @@
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)
}
}

View File

@ -1,6 +1,7 @@
mod enum_type;
mod leaf_enum_type;
mod leaf_struct_type;
mod polymorphic_enum_inner_build_type;
mod polymorphic_enum_loop_type;
mod polymorphic_type_type;
mod struct_type;
@ -9,10 +10,11 @@ use crate::spec::BuildSpec;
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_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::struct_type::make_struct_type;
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> {
match build_spec {
@ -31,7 +33,12 @@ pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> {
}
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop_spec) => {
Some(make_polymorphic_enum_loop_type(polymorphic_enum_loop_spec))
},
}
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,
}
}

View File

@ -0,0 +1,25 @@
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,)*
}
}
}

8
examples/hello_42.dm Normal file
View File

@ -0,0 +1,8 @@
use std::core::println
fn main(args: Array<String>)
let hello = 42
let world = hello + 16
println(hello)
println(world)
end

260
src/asm/assemble_ir.rs Normal file
View File

@ -0,0 +1,260 @@
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 Normal file
View File

@ -0,0 +1,240 @@
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, "/")
}
}
}
}

35
src/bin/dmc/ir.rs Normal file
View File

@ -0,0 +1,35 @@
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)
}

View File

@ -1,3 +1,4 @@
mod ir;
mod name_analysis;
mod p3;
// mod unparse;
@ -8,6 +9,7 @@ use crate::name_analysis::name_analysis;
use crate::p3::pretty_print_parse;
// use crate::unparse::unparse;
use clap::{Parser, Subcommand};
use crate::ir::compile_to_ir;
#[derive(Debug, Parser)]
#[command(name = "dmc")]
@ -29,6 +31,9 @@ enum Commands {
NameAnalysis {
paths: Vec<PathBuf>,
},
Ir {
paths: Vec<PathBuf>,
}
}
fn main() {
@ -50,6 +55,12 @@ fn main() {
eprintln!("{}", e)
}
}
Commands::Ir { paths } => {
let result = compile_to_ir(&paths);
if let Err(e) = result {
eprintln!("{}", e)
}
}
_ => todo!(),
}
}

View File

@ -10,6 +10,7 @@ use pest::Parser;
use std::collections::HashMap;
use std::fmt::{Debug, Display, Formatter};
use std::path::PathBuf;
use deimos::ast::node::CompilationUnit;
struct ParseErrors {
errors: Vec<pest::error::Error<Rule>>,
@ -33,7 +34,7 @@ impl Display for ParseErrors {
impl std::error::Error for ParseErrors {}
pub fn name_analysis(paths: &[PathBuf]) -> Result<(), Box<dyn std::error::Error>> {
pub fn name_analysis(paths: &[PathBuf]) -> Result<Vec<CompilationUnit>, Box<dyn std::error::Error>> {
let mut paths_and_sources: HashMap<String, String> = HashMap::new();
for path in paths {
let src = std::fs::read_to_string(path).unwrap();
@ -79,5 +80,5 @@ pub fn name_analysis(paths: &[PathBuf]) -> Result<(), Box<dyn std::error::Error>
}
}
Ok(())
Ok(compilation_units)
}

View File

@ -87,7 +87,7 @@ fn main() {
// return 0
MoveImmediate {
destination_register: 2,
immediate: Immediate::Int(0),
immediate: Immediate::I32(0),
},
SetReturnValue { source_register: 2 },
Return, // explicit, not needed
@ -106,7 +106,7 @@ fn main() {
let foo_function_instructions = vec![
MoveImmediate {
destination_register: 0,
immediate: Immediate::Int(42),
immediate: Immediate::I32(42),
},
SetReturnValue { source_register: 0 },
Return, // explicit, not needed

669
src/ir/lower_ast.rs Normal file
View File

@ -0,0 +1,669 @@
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
}

134
src/ir/lower_ir.rs Normal file
View File

@ -0,0 +1,134 @@
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
}

View File

@ -1,29 +1,90 @@
pub enum DvmIr {
Struct(Box<DvmIrStruct>),
Function(DvmIrFunction),
Const(DvmIrConst),
use crate::ir::lower_ast::LocalsTable;
use crate::util::indent_writer::IndentWriter;
use std::fmt::{Display, Formatter};
use std::rc::Rc;
pub mod lower_ast;
pub mod lower_ir;
pub enum Ir {
Struct(Box<IrStruct>),
Function(Box<IrFunction>),
PlatformFunction(Box<IrPlatformFunction>),
Const(Box<IrConst>),
}
pub struct DvmIrStruct {
impl Ir {
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,
kind: Box<DvmIrKind>,
is_public: bool,
members: Vec<Box<DvmIrStructMember>>
members: Vec<IrStructMember>,
}
pub struct DvmIrStructMember {
impl IrStruct {
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,
kind: Box<DvmIrKind>,
kind: Box<IrKind>,
is_public: bool,
is_mut: bool,
}
pub enum DvmIrKind {
Primitive(Box<DvmIrPrimitiveKind>),
Struct(Box<DvmIrStructKind>),
impl IrStructMember {
fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
if self.is_public {
writer.write("pub ")?;
}
if self.is_mut {
writer.write("mut ")?;
}
writer.write(&self.name)?;
writer.write(": ")?;
self.kind.pretty_print(writer)?;
Ok(())
}
}
pub enum DvmIrPrimitiveKind {
pub enum IrKind {
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,
I16,
I32,
@ -36,97 +97,438 @@ pub enum DvmIrPrimitiveKind {
U64,
U128,
USize,
Float,
Double,
Boolean,
Array(Box<DvmIrKind>),
Array(Box<IrKind>),
String,
Closure(Box<DvmIrClosureKind>),
Ref(Box<DvmIrKind>),
Closure(Box<IrClosureKind>),
Ref(Box<IrKind>),
Any,
Void,
}
pub struct DvmIrStructKind {
impl IrPrimitiveKind {
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,
}
pub struct DvmIrClosureKind {
captures_name: String,
parameters: Vec<Box<DvmIrKind>>,
return_type: Box<DvmIrKind>,
impl IrStructKind {
pub fn new(name: &str) -> Self {
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 DvmIrFunction {
pub struct IrClosureKind {
captures_struct_name: String,
parameters: Vec<IrKind>,
return_type: Box<IrKind>,
}
pub struct IrFunction {
name: String,
parameters: Vec<Box<DvmIrKind>>,
return_type: Box<DvmIrKind>,
statements: Vec<Box<DvmIrStatement>>,
parameters: Vec<IrKind>,
return_type: Box<IrKind>,
statements: Vec<IrStatement>,
locals_table: Box<LocalsTable>,
}
pub enum DvmIrStatement {
Alloc(DvmIrAlloc),
Call(DvmIrCallStmt),
Ret(DvmIrRet),
Assign(DvmIrAssign),
MakeClosure(DvmIrMakeClosure),
Drop(DvmIrDrop),
impl IrFunction {
pub fn new(
name: String,
parameters: Vec<IrKind>,
return_type: Box<IrKind>,
statements: Vec<IrStatement>,
locals_table: Box<LocalsTable>,
) -> 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 enum DvmIrAllocable {
Struct(Box<DvmIrStructKind>),
Array(Box<DvmIrArrayKind>),
pub struct IrPlatformFunction {
name: String,
parameters: Vec<IrKind>,
return_type: Box<IrKind>,
}
pub enum DvmIrArrayKind {
StaticSize(Box<DvmIrStaticArrayKind>),
DynamicSize(Box<DvmIrDynamicArrayKind>)
impl IrPlatformFunction {
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
writer.write("platform 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")?;
Ok(())
}
}
pub struct DvmIrStaticArrayKind {
inner_kind: Box<DvmIrKind>,
pub enum IrStatement {
Allocate(IrAllocate),
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,
}
pub struct DvmIrDynamicArrayKind {
inner_kind: Box<DvmIrKind>,
size_expr: Box<DvmIrExpr>
impl IrStaticArrayKind {
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
writer.write("[")?;
self.inner_kind.pretty_print(writer)?;
writer.write(&format!("; {}]", self.size))?;
Ok(())
}
}
pub struct DvmIrAlloc {
declared_kind: Box<DvmIrAllocable>,
pub struct IrDynamicArrayKind {
inner_kind: Box<IrKind>,
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,
kind_to_alloc: Box<DvmIrAllocable>,
declared_kind: Box<IrAllocable>,
kind_to_alloc: Box<IrAllocable>,
}
pub enum DvmIrConst {
String(DvmIrStringConst),
StringArray(DvmIrStringArrayConst),
impl IrAllocate {
pub fn name(&self) -> &str {
&self.name
}
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 DvmIrStringConst {
pub struct IrBinaryOperation {
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,
value: String,
}
pub struct DvmIrStringArrayConst {
pub struct IrStringArrayConst {
name: String,
value: Vec<String>,
}
pub enum DvmIrExpr {
Call(Box<DvmIrCallExpr>),
Variable(Box<DvmIrVariable>),
ConstRef(Box<DvmIrConstRef>),
Literal(Box<DvmIrLiteral>)
pub enum IrExpression {
Variable(Box<IrVariable>),
ConstRef(Box<IrConstRef>),
Literal(Box<IrLiteral>),
}
pub struct DvmIrVariable {
impl IrExpression {
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,
}
pub struct DvmIrConstRef {
name: String,
impl IrVariable {
pub fn new(name: &str) -> Self {
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 enum DvmIrLiteral {
pub struct IrConstRef {
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),
I16(i16),
I32(i32),
@ -140,60 +542,161 @@ pub enum DvmIrLiteral {
U128(u128),
USize(usize),
Boolean(bool),
Float(f32),
Double(f64),
}
pub struct DvmIrCallStmt {
declared_type: Box<DvmIrKind>,
name: String,
call_expr: Box<DvmIrCallExpr>,
impl IrLiteral {
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
match self {
IrLiteral::I8(v) => writer.write(&format!("{}", v)),
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 DvmIrCallExpr {
name: String,
arguments: Vec<Box<DvmIrExpr>>,
pub struct IrCall {
result_name: String,
declared_type: Box<IrKind>,
fqn: Rc<str>,
call_type: IrCallType,
arguments: Vec<IrExpression>,
}
pub struct DvmIrAssign {
lhs: Box<DvmIrAssignLhs>,
rhs: Box<DvmIrExpr>
impl IrCall {
pub fn new(
result_name: &str,
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 struct DvmIrAssignLhs {
base: Box<DvmIrVariable>,
suffixes: Vec<Box<DvmIrAssignLhsSuffix>>
pub enum IrCallType {
Static,
Object,
}
pub enum DvmIrAssignLhsSuffix {
Index(DvmIrAssignLhsIndex),
Property(DvmIrAssignLhsProperty)
pub struct IrAssign {
lhs: Box<IrVariable>,
rhs: Box<IrExpression>,
}
pub struct DvmIrAssignLhsIndex {
expr: Box<DvmIrExpr>,
impl IrAssign {
pub fn new(lhs: Box<IrVariable>, rhs: Box<IrExpression>) -> Self {
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 DvmIrAssignLhsProperty {
name: String,
pub struct IrReturn {
expression: Box<IrExpression>,
}
pub struct DvmIrRet {
value: Box<DvmIrReturnable>
impl IrReturn {
pub fn new(expression: Box<IrExpression>) -> Self {
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 enum DvmIrReturnable {
Variable(DvmIrVariable),
Literal(DvmIrLiteral)
}
pub struct DvmIrMakeClosure {
captures_kind: Option<Box<DvmIrStructKind>>,
parameters: Vec<Box<DvmIrKind>>,
return_type: Box<DvmIrKind>,
pub struct IrMakeClosure {
captures_kind: Option<Box<IrStructKind>>,
parameters: Vec<IrKind>,
return_type: Box<IrKind>,
name: String,
fn_name: String,
captures_variable: Box<DvmIrVariable>,
captures_variable: Box<IrVariable>,
}
pub struct DvmIrDrop {
variable: Box<DvmIrVariable>,
}
impl IrMakeClosure {
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
todo!()
}
}

View File

@ -4,6 +4,7 @@
#![allow(warnings)]
extern crate core;
pub mod asm;
pub mod ast;
pub mod diagnostic;
pub mod ir;

View File

@ -1,4 +1,13 @@
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};
use crate::ast::node::{
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::name_analysis::symbol::source_definition::SourceDefinition;
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
@ -620,7 +629,8 @@ fn na_p2_expression(
todo!()
}
Expression::Additive(additive) => {
todo!()
na_p2_expression(additive.left_mut(), symbol_table, diagnostics);
na_p2_expression(additive.rhs_mut().expression_mut(), symbol_table, diagnostics);
}
Expression::Multiplicative(multiplicative) => {
todo!()
@ -668,30 +678,16 @@ fn na_p2_suffix_operator(
diagnostics: &mut Vec<DmDiagnostic>,
) {
match suffix_operator {
SuffixOperator::BoundSuffixOperator(bound_suffix) => {
match bound_suffix {
BoundSuffixOperator::PlusPlus => {
// no-op
}
BoundSuffixOperator::MinusMinus => {
// no-op
}
}
SuffixOperator::PlusPlus => {}
SuffixOperator::MinusMinus => {}
SuffixOperator::ObjectIndex(object_index) => {
na_p2_object_index(object_index, symbol_table, diagnostics);
}
SuffixOperator::NoNewlineSuffixOperator(no_newline_suffix) => match no_newline_suffix {
NoNewlineSuffixOperator::ObjectIndex(object_index) => {
na_p2_object_index(object_index, symbol_table, diagnostics);
}
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
}
}
SuffixOperator::Call(call) => {
na_p2_call(call, symbol_table, diagnostics);
}
SuffixOperator::ObjectProperty(object_property) => {
todo!()
}
}
}

View File

@ -50,6 +50,10 @@ impl FunctionSymbol {
return_type,
}
}
pub fn fqn_formatted(&self) -> String {
self.fqn_parts.join("::")
}
pub fn fqn_parts_owned(&self) -> Vec<Rc<str>> {
self.fqn_parts.to_vec()
@ -78,6 +82,10 @@ impl FunctionSymbol {
pub fn set_parameter_symbols(&mut self, parameter_symbols: Vec<Rc<RefCell<ParameterSymbol>>>) {
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) {
self.return_type = Some(type_symbol);

View File

@ -1158,23 +1158,34 @@ SuffixExpression:
on_each:
rule: SuffixOperator
SuffixOperator:
tree_enum:
polymorphic_enum_inner_build:
members:
- PlusPlus:
kind: leaf
- MinusMinus:
kind: leaf
- ObjectIndex
- Call
- ObjectProperty
rules:
- BoundSuffixOperator
- NoNewlineSuffixOperator
- AnySpaceSuffixOperator
BoundSuffixOperator:
leaf_enum:
polymorphic_leaf_enum:
kind: SuffixOperator
rules:
- PlusPlus
- MinusMinus
NoNewlineSuffixOperator:
tree_enum:
polymorphic_tree_enum:
kind: SuffixOperator
rules:
- ObjectIndex
- Call
AnySpaceSuffixOperator:
tree_enum:
polymorphic_tree_enum:
kind: SuffixOperator
rules:
- ObjectProperty
ObjectProperty:

View File

@ -24,7 +24,7 @@ pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), Symbol
true,
None,
&vec![Rc::new(RefCell::new(println_msg_symbol))],
None,
Some(TypeSymbol::Primitive(PrimitiveTypeSymbol::Void)),
);
symbol_table.register_function_symbol(println_symbol);

View File

@ -18,6 +18,7 @@ pub enum Instruction {
Pop {
destination_register: Option<usize>,
},
PopFrame,
AllocateObject {
implementation_name: Rc<String>,
destination_register: usize,
@ -117,12 +118,21 @@ pub enum Instruction {
#[derive(Debug, Clone)]
pub enum Immediate {
Byte(u8),
Int(i32),
Long(i64),
Double(f64),
Usize(usize),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
I128(i128),
ISize(isize),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
U128(u128),
USize(usize),
Boolean(bool),
Float(f32),
Double(f64),
Constant(DvmConstant),
Empty,
}
@ -130,10 +140,10 @@ pub enum Immediate {
#[derive(Debug, Clone)]
pub enum Location {
Register(usize),
StackFrameBase {
FramePointer {
offset: isize,
},
StackTop {
StackPointer {
offset: isize,
},
Field {

View File

@ -224,7 +224,7 @@ fn compute_index_with_offset(
fn copy_from_source(state: &DvmState, source: &Location) -> DvmValue {
match source {
Location::Register(register) => state.registers[*register].clone(),
Location::StackFrameBase { offset } => {
Location::FramePointer { offset } => {
let index = if offset.is_negative() {
state.frame_base_index - offset.unsigned_abs()
} else {
@ -232,7 +232,7 @@ fn copy_from_source(state: &DvmState, source: &Location) -> DvmValue {
};
state.stack[index].clone()
}
Location::StackTop { offset } => {
Location::StackPointer { offset } => {
if *offset >= 0 {
dvm_panic!(
state,
@ -272,7 +272,7 @@ fn write_to_destination(state: &mut DvmState, destination: &Location, value: Dvm
Location::Register(register) => {
state.registers[*register] = value;
}
Location::StackFrameBase { offset } => {
Location::FramePointer { offset } => {
let index = if offset.is_negative() {
state.frame_base_index - offset.unsigned_abs()
} else {
@ -280,7 +280,7 @@ fn write_to_destination(state: &mut DvmState, destination: &Location, value: Dvm
};
state.stack[index] = value;
}
Location::StackTop { offset } => {
Location::StackPointer { offset } => {
if *offset >= 0 {
dvm_panic!(
state,
@ -344,14 +344,7 @@ fn constant_to_value(constant: &DvmConstant) -> DvmValue {
fn immediate_to_value(immediate: &Immediate) -> DvmValue {
match immediate {
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,
_ => todo!()
}
}
@ -411,6 +404,7 @@ pub fn run(instructions: &[Instruction], state: &mut DvmState, context: &DvmCont
state.registers[*register_index] = value;
}
}
PopFrame => {}
AllocateObject {
implementation_name,
destination_register,