diff --git a/src/ast/build.rs b/src/ast/build.rs new file mode 100644 index 0000000..5a1c549 --- /dev/null +++ b/src/ast/build.rs @@ -0,0 +1,421 @@ +use crate::ast::{ + BlockStatement, CompilationUnit, Declaration, Fqn, FunctionDeclaration, GenericArgument, + GenericParameter, Identifier, ImplCtor, ImplCtorArg, Parameter, TypeDeclaration, TypeUse, +}; +use crate::parser::{DeimosParser, Rule}; +use crate::vm::source_code_location::SourceCodeLocation; +use pest::iterators::Pair; +use pest::Parser; + +fn build_field(field_pair: Pair) -> Declaration { + todo!() +} + +fn build_prop(prop_pair: Pair) -> Declaration { + todo!() +} + +fn build_impl_ctor_arg(impl_ctor_arg_pair: Pair) -> ImplCtorArg { + let mut is_field = false; + let mut identifier: Option = None; + let mut r#type: Option = None; + + for pair in impl_ctor_arg_pair.into_inner() { + match pair.as_rule() { + Rule::fld => { + is_field = true; + } + Rule::identifier => { + identifier = Some(build_identifier(pair)); + } + Rule::type_use => { + r#type = Some(build_type_use(pair)); + } + _ => panic!("Unexpected rule: {}", pair), + } + } + + ImplCtorArg { + is_field, + identifier: identifier.unwrap(), + r#type, + } +} + +fn build_impl_ctor(impl_ctor_pair: Pair) -> ImplCtor { + let impl_ctor_args_pair = impl_ctor_pair.into_inner().next().unwrap(); + let mut args: Vec = vec![]; + + for pair in impl_ctor_args_pair.into_inner() { + match pair.as_rule() { + Rule::impl_ctor_arg => { + args.push(build_impl_ctor_arg(pair)); + } + _ => panic!("Unexpected rule: {}", pair), + } + } + + ImplCtor { args } +} + +fn build_generic_argument(generic_argument_pair: Pair) -> GenericArgument { + let fqn_pair = generic_argument_pair.into_inner().next().unwrap(); + GenericArgument { + fqn: build_fqn(fqn_pair), + } +} + +fn build_generic_arguments_declaration( + generic_arguments_declaration_pair: Pair, +) -> Vec { + let mut generic_arguments: Vec = vec![]; + for pair in generic_arguments_declaration_pair.into_inner() { + match pair.as_rule() { + Rule::generic_argument => { + generic_arguments.push(build_generic_argument(pair)); + } + _ => panic!("Expected only generic_argument rules. Found: {}", pair), + } + } + generic_arguments +} + +fn build_generic_parameter(generic_parameter_pair: Pair) -> GenericParameter { + let identifier_pair = generic_parameter_pair.into_inner().next().unwrap(); + GenericParameter { + identifier: build_identifier(identifier_pair), + bound: None, + } +} + +fn build_type_use(type_pair: Pair) -> TypeUse { + let mut fqn: Option = None; + let mut generic_arguments_declaration: Option> = None; + + for pair in type_pair.into_inner() { + match pair.as_rule() { + Rule::fqn => { + fqn = Some(build_fqn(pair)); + } + Rule::generic_arguments_declaration => { + generic_arguments_declaration = Some(build_generic_arguments_declaration(pair)); + } + _ => panic!( + "Expected only fqn or generic_arguments_declaration rules. Found: {}", + pair + ), + } + } + + TypeUse { + fqn: fqn.unwrap(), + generics: generic_arguments_declaration.unwrap_or(vec![]), + } +} + +fn build_generic_parameters_declaration( + generic_parameters_declaration_pair: Pair, +) -> Vec { + let mut parameters: Vec = vec![]; + for pair in generic_parameters_declaration_pair.into_inner() { + match pair.as_rule() { + Rule::generic_parameter => { + parameters.push(build_generic_parameter(pair)); + } + _ => panic!("Expected only generic_parameter rule. Found: {}", pair), + } + } + parameters +} + +fn build_extends_list(extends_list_pair: Pair) -> Vec { + let mut extensions: Vec = vec![]; + + for pair in extends_list_pair.into_inner() { + match pair.as_rule() { + Rule::type_use => { + extensions.push(build_type_use(pair)); + } + _ => panic!("Expected only type rule. Found: {}", pair), + } + } + + extensions +} + +fn build_interface(is_extern: bool, is_public: bool, interface_pair: Pair) -> Declaration { + let mut identifier: Option = None; + let mut generic_parameters: Option> = None; + let mut extends: Option> = None; + let mut declarations: Vec = vec![]; + + for pair in interface_pair.into_inner() { + match pair.as_rule() { + Rule::identifier => { + identifier = Some(build_identifier(pair)); + } + Rule::generic_parameters_declaration => { + generic_parameters = Some(build_generic_parameters_declaration(pair)); + } + Rule::extends_list => { + extends = Some(build_extends_list(pair)); + } + Rule::declaration => { + declarations.push(build_declaration(pair)); + }, + _ => panic!( + "Expected only identifier, generics_declaration, extends_list, or declaration rules. Found: {}", + pair + ) + } + } + + Declaration::Interface { + identifier: identifier.unwrap(), + is_extern, + is_public, + type_declaration: TypeDeclaration::new( + generic_parameters.unwrap_or(vec![]), + extends.unwrap_or(vec![]), + declarations, + ), + } +} + +fn build_implementation( + is_extern: bool, + is_public: bool, + implementation_pair: Pair, +) -> Declaration { + let mut identifier: Option = None; + let mut generic_parameters: Option> = None; + let mut impl_ctor: Option = None; + let mut extends: Option> = None; + let mut declarations: Vec = vec![]; + + for pair in implementation_pair.into_inner() { + match pair.as_rule() { + Rule::identifier => { + identifier = Some(build_identifier(pair)); + } + Rule::generic_parameters_declaration => { + generic_parameters = Some(build_generic_parameters_declaration(pair)); + } + Rule::impl_ctor => { + impl_ctor = Some(build_impl_ctor(pair)); + } + Rule::extends_list => { + extends = Some(build_extends_list(pair)); + } + Rule::declaration => { + declarations.push(build_declaration(pair)); + } + _ => panic!("Unexpected rule: {}", pair), + } + } + + Declaration::Implementation { + identifier: identifier.unwrap(), + is_extern, + is_public, + type_declaration: TypeDeclaration::new( + generic_parameters.unwrap_or(vec![]), + extends.unwrap_or(vec![]), + declarations, + ), + impl_ctor, + } +} + +fn build_module(is_extern: bool, is_public: bool, pair: Pair) -> Declaration { + todo!() +} + +fn build_parameter(pair: Pair) -> Parameter { + let mut identifier: Option = None; + let mut declared_type: Option = None; + for pair in pair.into_inner() { + match pair.as_rule() { + Rule::identifier => { + identifier = Some(build_identifier(pair)); + } + Rule::type_use => { + declared_type = Some(build_type_use(pair)); + } + _ => unreachable!(), + } + } + Parameter { + identifier: identifier.unwrap(), + declared_type, + } +} + +fn build_parameters_list(pair: Pair) -> Vec { + let mut parameters: Vec = vec![]; + for pair in pair.into_inner() { + match pair.as_rule() { + Rule::parameter => { + parameters.push(build_parameter(pair)); + } + _ => unreachable!(), + } + } + parameters +} + +fn build_function_body(pair: Pair) -> BlockStatement { + todo!() +} + +fn build_function_equals_body(pair: Pair) -> BlockStatement { + todo!() +} + +fn build_function(is_extern: bool, is_public: bool, pair: Pair) -> Declaration { + let mut generic_parameters: Option> = None; + let mut identifier: Option = None; + let mut parameters: Option> = None; + let mut return_type: Option = None; + let mut statement: Option = None; + + let (line, col) = pair.line_col(); + + for pair in pair.into_inner() { + match pair.as_rule() { + Rule::generic_parameters_declaration => { + generic_parameters = Some(build_generic_parameters_declaration(pair)); + } + Rule::identifier => { + identifier = Some(build_identifier(pair)); + } + Rule::parameters_list => { + parameters = Some(build_parameters_list(pair)); + } + Rule::type_use => { + return_type = Some(build_type_use(pair)); + } + Rule::function_body => { + statement = Some(build_function_body(pair)); + } + Rule::function_equals_body => { + statement = Some(build_function_equals_body(pair)); + } + _ => unreachable!(), + } + } + + Declaration::Function(FunctionDeclaration { + is_extern, + is_public, + identifier: identifier.unwrap(), + parameters: parameters.unwrap(), + declared_type: return_type, + block_statement: statement.unwrap(), + source_code_location: SourceCodeLocation { + source_file_name: "TODO".to_string(), + line, + col, + }, + }) +} + +fn build_declaration(declaration_pair: Pair) -> Declaration { + let mut is_extern = false; + let mut is_public = false; + let mut declaration: Option = None; + + for pair in declaration_pair.into_inner() { + match pair.as_rule() { + Rule::r#extern => { + is_extern = true; + } + Rule::r#pub => { + is_public = true; + } + Rule::interface => { + declaration = Some(build_interface(is_extern, is_public, pair)); + } + Rule::implementation => { + declaration = Some(build_implementation(is_extern, is_public, pair)); + } + Rule::module => { + declaration = Some(build_module(is_extern, is_public, pair)); + } + Rule::function => { + declaration = Some(build_function(is_extern, is_public, pair)); + } + Rule::prop => { + declaration = Some(build_prop(pair)); + } + Rule::field => { + declaration = Some(build_field(pair)); + } + _ => panic!( + "Expected only interface, implementation, module, or function rules; found {}", + pair + ), + } + } + declaration.expect("Expected declaration.") +} + +fn build_identifier(pair: Pair) -> Identifier { + match pair.as_rule() { + Rule::identifier => Identifier { + name: String::from(pair.as_str()), + }, + _ => panic!("Expected an identifier."), + } +} + +fn build_fqn(fqn_pair: Pair) -> Fqn { + let mut identifiers: Vec = vec![]; + for pair in fqn_pair.into_inner() { + match pair.as_rule() { + Rule::identifier => { + identifiers.push(build_identifier(pair)); + } + _ => panic!("Expected only identifiers."), + } + } + Fqn { identifiers } +} + +fn build_compilation_unit(pair: Pair) -> CompilationUnit { + let mut namespace: Option = None; + let mut declarations: Vec = vec![]; + + for pair in pair.into_inner() { + match pair.as_rule() { + Rule::namespace => { + let fqn_pair = pair.into_inner().next().unwrap(); + namespace = Some(build_fqn(fqn_pair)); + } + Rule::declaration => { + declarations.push(build_declaration(pair)); + } + Rule::EOI => {} // ignore + _ => panic!( + "Expected only namespace, declaration, or EOI rules, found: {}", + pair + ), + } + } + + CompilationUnit { + namespace, + declarations, + } +} + +pub fn build_ast(src: &str) -> CompilationUnit { + let pair = DeimosParser::parse(Rule::compilation_unit, src) + .expect("Unsuccessful parse.") + .next() + .expect("Expcted compilation_unit."); + match pair.as_rule() { + Rule::compilation_unit => build_compilation_unit(pair), + _ => panic!("Expected compilation_unit rule."), + } +} diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 39c6626..d8cb65a 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -1,5 +1,7 @@ -use crate::parser::{DeimosParser, Rule}; -use pest::{iterators::Pair, Parser}; +use crate::vm::source_code_location::SourceCodeLocation; +use pest::Parser; + +pub mod build; #[derive(Debug)] pub struct CompilationUnit { @@ -7,11 +9,39 @@ pub struct CompilationUnit { declarations: Vec, } +impl CompilationUnit { + pub fn namespace(&self) -> &Option { + &self.namespace + } + + pub fn declarations(&self) -> &Vec { + &self.declarations + } +} + #[derive(Debug)] pub struct Fqn { identifiers: Vec, } +impl Fqn { + pub fn new(identifiers: Vec) -> Self { + Fqn { identifiers } + } + + pub fn identifiers(&self) -> &Vec { + &self.identifiers + } + + pub fn push_identifier(&mut self, identifier: Identifier) { + self.identifiers.push(identifier); + } + + pub fn pop_identifier(&mut self) { + self.identifiers.pop(); + } +} + #[derive(Debug)] pub enum Declaration { Interface { @@ -33,18 +63,36 @@ pub enum Declaration { is_public: bool, declarations: Vec, }, - Function { - identifier: Identifier, - is_extern: bool, - is_public: bool, - parameters: Vec, - declared_type: Option, - statement: Statement, - }, + Function(FunctionDeclaration), Prop(Prop), Field(Field), } +#[derive(Debug)] +pub struct FunctionDeclaration { + source_code_location: SourceCodeLocation, + identifier: Identifier, + is_extern: bool, + is_public: bool, + parameters: Vec, + declared_type: Option, + block_statement: BlockStatement, +} + +impl FunctionDeclaration { + pub fn source_code_location(&self) -> &SourceCodeLocation { + &self.source_code_location + } + + pub fn identifier(&self) -> &Identifier { + &self.identifier + } + + pub fn block_statement(&self) -> &BlockStatement { + &self.block_statement + } +} + #[derive(Debug)] pub struct TypeDeclaration { generics: Vec, @@ -66,11 +114,17 @@ impl TypeDeclaration { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Identifier { name: String, } +impl Identifier { + pub fn name(&self) -> &str { + &self.name + } +} + #[derive(Debug)] pub struct GenericParameter { identifier: Identifier, @@ -118,11 +172,71 @@ pub struct Field { r#type: TypeUse, } +#[derive(Debug)] +pub struct BlockStatement { + statements: Vec, +} + +impl BlockStatement { + pub fn statements(&self) -> &Vec { + &self.statements + } +} + #[derive(Debug)] pub enum Statement { - BlockStatement { statements: Vec }, - CallStatement, - AssignmentStatement, + CallStatement(CallExpression), + AssignStatement(AssignExpression), +} + +#[derive(Debug)] +pub struct CallExpression { + receiver: Expression, + actuals_list: Vec, + source_code_location: SourceCodeLocation, +} + +impl CallExpression { + pub fn receiver(&self) -> &Expression { + &self.receiver + } + + pub fn actuals_list(&self) -> &Vec { + &self.actuals_list + } + + pub fn source_code_location(&self) -> &SourceCodeLocation { + &self.source_code_location + } +} + +#[derive(Debug)] +pub struct AssignExpression { + left: LValue, + right: Expression, +} + +#[derive(Debug)] +pub enum Expression { + CallExpression(Box), + AssignExpression(Box), + LValue(Box), + Literal(Box), +} + +#[derive(Debug)] +pub enum LValue { + Fqn(Fqn), +} + +#[derive(Debug)] +pub enum Literal { + IntegerLiteral(i32), + LongLiteral(i64), + DoubleLiteral(f64), + USizeLiteral(usize), + StringLiteral(String), + BooleanLiteral(bool), } #[derive(Debug)] @@ -130,409 +244,3 @@ pub struct Parameter { identifier: Identifier, declared_type: Option, } - -fn build_field(field_pair: Pair) -> Declaration { - todo!() -} - -fn build_prop(prop_pair: Pair) -> Declaration { - todo!() -} - -fn build_impl_ctor_arg(impl_ctor_arg_pair: Pair) -> ImplCtorArg { - let mut is_field = false; - let mut identifier: Option = None; - let mut r#type: Option = None; - - for pair in impl_ctor_arg_pair.into_inner() { - match pair.as_rule() { - Rule::fld => { - is_field = true; - } - Rule::identifier => { - identifier = Some(build_identifier(pair)); - } - Rule::type_use => { - r#type = Some(build_type_use(pair)); - } - _ => panic!("Unexpected rule: {}", pair), - } - } - - ImplCtorArg { - is_field, - identifier: identifier.unwrap(), - r#type, - } -} - -fn build_impl_ctor(impl_ctor_pair: Pair) -> ImplCtor { - let impl_ctor_args_pair = impl_ctor_pair.into_inner().next().unwrap(); - let mut args: Vec = vec![]; - - for pair in impl_ctor_args_pair.into_inner() { - match pair.as_rule() { - Rule::impl_ctor_arg => { - args.push(build_impl_ctor_arg(pair)); - } - _ => panic!("Unexpected rule: {}", pair), - } - } - - ImplCtor { args } -} - -fn build_generic_argument(generic_argument_pair: Pair) -> GenericArgument { - let fqn_pair = generic_argument_pair.into_inner().next().unwrap(); - GenericArgument { - fqn: build_fqn(fqn_pair), - } -} - -fn build_generic_arguments_declaration( - generic_arguments_declaration_pair: Pair, -) -> Vec { - let mut generic_arguments: Vec = vec![]; - for pair in generic_arguments_declaration_pair.into_inner() { - match pair.as_rule() { - Rule::generic_argument => { - generic_arguments.push(build_generic_argument(pair)); - } - _ => panic!("Expected only generic_argument rules. Found: {}", pair), - } - } - generic_arguments -} - -fn build_generic_parameter(generic_parameter_pair: Pair) -> GenericParameter { - let identifier_pair = generic_parameter_pair.into_inner().next().unwrap(); - GenericParameter { - identifier: build_identifier(identifier_pair), - bound: None, - } -} - -fn build_type_use(type_pair: Pair) -> TypeUse { - let mut fqn: Option = None; - let mut generic_arguments_declaration: Option> = None; - - for pair in type_pair.into_inner() { - match pair.as_rule() { - Rule::fqn => { - fqn = Some(build_fqn(pair)); - } - Rule::generic_arguments_declaration => { - generic_arguments_declaration = Some(build_generic_arguments_declaration(pair)); - } - _ => panic!( - "Expected only fqn or generic_arguments_declaration rules. Found: {}", - pair - ), - } - } - - TypeUse { - fqn: fqn.unwrap(), - generics: generic_arguments_declaration.unwrap_or(vec![]), - } -} - -fn build_generic_parameters_declaration( - generic_parameters_declaration_pair: Pair, -) -> Vec { - let mut parameters: Vec = vec![]; - for pair in generic_parameters_declaration_pair.into_inner() { - match pair.as_rule() { - Rule::generic_parameter => { - parameters.push(build_generic_parameter(pair)); - } - _ => panic!("Expected only generic_parameter rule. Found: {}", pair), - } - } - parameters -} - -fn build_extends_list(extends_list_pair: Pair) -> Vec { - let mut extensions: Vec = vec![]; - - for pair in extends_list_pair.into_inner() { - match pair.as_rule() { - Rule::type_use => { - extensions.push(build_type_use(pair)); - } - _ => panic!("Expected only type rule. Found: {}", pair), - } - } - - extensions -} - -fn build_interface(is_extern: bool, is_public: bool, interface_pair: Pair) -> Declaration { - let mut identifier: Option = None; - let mut generic_parameters: Option> = None; - let mut extends: Option> = None; - let mut declarations: Vec = vec![]; - - for pair in interface_pair.into_inner() { - match pair.as_rule() { - Rule::identifier => { - identifier = Some(build_identifier(pair)); - } - Rule::generic_parameters_declaration => { - generic_parameters = Some(build_generic_parameters_declaration(pair)); - } - Rule::extends_list => { - extends = Some(build_extends_list(pair)); - } - Rule::declaration => { - declarations.push(build_declaration(pair)); - }, - _ => panic!( - "Expected only identifier, generics_declaration, extends_list, or declaration rules. Found: {}", - pair - ) - } - } - - Declaration::Interface { - identifier: identifier.unwrap(), - is_extern, - is_public, - type_declaration: TypeDeclaration::new( - generic_parameters.unwrap_or(vec![]), - extends.unwrap_or(vec![]), - declarations, - ), - } -} - -fn build_implementation( - is_extern: bool, - is_public: bool, - implementation_pair: Pair, -) -> Declaration { - let mut identifier: Option = None; - let mut generic_parameters: Option> = None; - let mut impl_ctor: Option = None; - let mut extends: Option> = None; - let mut declarations: Vec = vec![]; - - for pair in implementation_pair.into_inner() { - match pair.as_rule() { - Rule::identifier => { - identifier = Some(build_identifier(pair)); - } - Rule::generic_parameters_declaration => { - generic_parameters = Some(build_generic_parameters_declaration(pair)); - } - Rule::impl_ctor => { - impl_ctor = Some(build_impl_ctor(pair)); - } - Rule::extends_list => { - extends = Some(build_extends_list(pair)); - } - Rule::declaration => { - declarations.push(build_declaration(pair)); - } - _ => panic!("Unexpected rule: {}", pair), - } - } - - Declaration::Implementation { - identifier: identifier.unwrap(), - is_extern, - is_public, - type_declaration: TypeDeclaration::new( - generic_parameters.unwrap_or(vec![]), - extends.unwrap_or(vec![]), - declarations, - ), - impl_ctor, - } -} - -fn build_module(is_extern: bool, is_public: bool, pair: Pair) -> Declaration { - todo!() -} - -fn build_parameter(pair: Pair) -> Parameter { - let mut identifier: Option = None; - let mut declared_type: Option = None; - for pair in pair.into_inner() { - match pair.as_rule() { - Rule::identifier => { - identifier = Some(build_identifier(pair)); - } - Rule::type_use => { - declared_type = Some(build_type_use(pair)); - } - _ => unreachable!(), - } - } - Parameter { - identifier: identifier.unwrap(), - declared_type, - } -} - -fn build_parameters_list(pair: Pair) -> Vec { - let mut parameters: Vec = vec![]; - for pair in pair.into_inner() { - match pair.as_rule() { - Rule::parameter => { - parameters.push(build_parameter(pair)); - } - _ => unreachable!(), - } - } - parameters -} - -fn build_function_body(pair: Pair) -> Statement { - todo!() -} - -fn build_function_equals_body(pair: Pair) -> Statement { - todo!() -} - -fn build_function(is_extern: bool, is_public: bool, pair: Pair) -> Declaration { - let mut generic_parameters: Option> = None; - let mut identifier: Option = None; - let mut parameters: Option> = None; - let mut return_type: Option = None; - let mut statement: Option = None; - - for pair in pair.into_inner() { - match pair.as_rule() { - Rule::generic_parameters_declaration => { - generic_parameters = Some(build_generic_parameters_declaration(pair)); - } - Rule::identifier => { - identifier = Some(build_identifier(pair)); - } - Rule::parameters_list => { - parameters = Some(build_parameters_list(pair)); - } - Rule::type_use => { - return_type = Some(build_type_use(pair)); - } - Rule::function_body => { - statement = Some(build_function_body(pair)); - } - Rule::function_equals_body => { - statement = Some(build_function_equals_body(pair)); - } - _ => unreachable!(), - } - } - - Declaration::Function { - is_extern, - is_public, - identifier: identifier.unwrap(), - parameters: parameters.unwrap(), - declared_type: return_type, - statement: statement.unwrap(), - } -} - -fn build_declaration(declaration_pair: Pair) -> Declaration { - let mut is_extern = false; - let mut is_public = false; - let mut declaration: Option = None; - - for pair in declaration_pair.into_inner() { - match pair.as_rule() { - Rule::r#extern => { - is_extern = true; - } - Rule::r#pub => { - is_public = true; - } - Rule::interface => { - declaration = Some(build_interface(is_extern, is_public, pair)); - } - Rule::implementation => { - declaration = Some(build_implementation(is_extern, is_public, pair)); - } - Rule::module => { - declaration = Some(build_module(is_extern, is_public, pair)); - } - Rule::function => { - declaration = Some(build_function(is_extern, is_public, pair)); - } - Rule::prop => { - declaration = Some(build_prop(pair)); - } - Rule::field => { - declaration = Some(build_field(pair)); - } - _ => panic!( - "Expected only interface, implementation, module, or function rules; found {}", - pair - ), - } - } - declaration.expect("Expected declaration.") -} - -fn build_identifier(pair: Pair) -> Identifier { - match pair.as_rule() { - Rule::identifier => Identifier { - name: String::from(pair.as_str()), - }, - _ => panic!("Expected an identifier."), - } -} - -fn build_fqn(fqn_pair: Pair) -> Fqn { - let mut identifiers: Vec = vec![]; - for pair in fqn_pair.into_inner() { - match pair.as_rule() { - Rule::identifier => { - identifiers.push(build_identifier(pair)); - } - _ => panic!("Expected only identifiers."), - } - } - Fqn { identifiers } -} - -fn build_compilation_unit(pair: Pair) -> CompilationUnit { - let mut namespace: Option = None; - let mut declarations: Vec = vec![]; - - for pair in pair.into_inner() { - match pair.as_rule() { - Rule::namespace => { - let fqn_pair = pair.into_inner().next().unwrap(); - namespace = Some(build_fqn(fqn_pair)); - } - Rule::declaration => { - declarations.push(build_declaration(pair)); - } - Rule::EOI => {} // ignore - _ => panic!( - "Expected only namespace, declaration, or EOI rules, found: {}", - pair - ), - } - } - - CompilationUnit { - namespace, - declarations, - } -} - -pub fn build_ast(src: &str) -> CompilationUnit { - let pair = DeimosParser::parse(Rule::compilation_unit, src) - .expect("Unsuccessful parse.") - .next() - .expect("Expcted compilation_unit."); - match pair.as_rule() { - Rule::compilation_unit => build_compilation_unit(pair), - _ => panic!("Expected compilation_unit rule."), - } -} diff --git a/src/bin/dmc/ast_dump.rs b/src/bin/dmc/ast_dump.rs index 4c07813..c4b1405 100644 --- a/src/bin/dmc/ast_dump.rs +++ b/src/bin/dmc/ast_dump.rs @@ -1,10 +1,9 @@ use std::path::PathBuf; -use deimos::ast::build_ast; +use deimos::ast::build::build_ast; pub fn dump_ast(path: &PathBuf) { - let src = std::fs::read_to_string(path) - .expect(&format!("Could not read {:?}", path)); + let src = std::fs::read_to_string(path).expect(&format!("Could not read {:?}", path)); let ast = build_ast(&src); println!("{:?}", ast); } diff --git a/src/bin/dmc/main.rs b/src/bin/dmc/main.rs index 2ff2d52..9ad4390 100644 --- a/src/bin/dmc/main.rs +++ b/src/bin/dmc/main.rs @@ -16,9 +16,7 @@ struct Cli { #[derive(Debug, Subcommand)] enum Commands { #[command(arg_required_else_help = true)] - AstDump { - paths: Vec - } + AstDump { paths: Vec }, } fn main() { @@ -31,4 +29,3 @@ fn main() { } } } - diff --git a/src/bin/dvm/main.rs b/src/bin/dvm/main.rs index 7fe620b..edd9c3f 100644 --- a/src/bin/dvm/main.rs +++ b/src/bin/dvm/main.rs @@ -37,7 +37,7 @@ fn main() { source_code_location: SourceCodeLocation { source_file_name: String::from("greeter.dm"), line: 4, - char: 5, + col: 5, }, }, // unwind from call @@ -54,10 +54,12 @@ fn main() { source_code_location: SourceCodeLocation { source_file_name: String::from("greeter.dm"), line: 5, - char: 13, + col: 13, }, }, - Pop { destination_register: Some(0) }, // restore r0 + Pop { + destination_register: Some(0), + }, // restore r0 TakeReturnValue { destination_register: 1, }, @@ -70,7 +72,7 @@ fn main() { source_code_location: SourceCodeLocation { source_file_name: String::from("greeter.dm"), line: 5, - char: 5, + col: 5, }, }, Pop { @@ -97,7 +99,7 @@ fn main() { SourceCodeLocation { source_file_name: String::from("greeter.dm"), line: 3, - char: 1, + col: 1, }, ); @@ -116,7 +118,7 @@ fn main() { SourceCodeLocation { source_file_name: String::from("greeter.dm"), line: 8, - char: 1, + col: 1, }, ); diff --git a/src/compile/declared_type.rs b/src/compile/declared_type.rs new file mode 100644 index 0000000..129d8d0 --- /dev/null +++ b/src/compile/declared_type.rs @@ -0,0 +1,10 @@ +pub enum DeclaredType { + Function(FunctionType), +} + +pub enum FunctionType { + StaticFunction, + ObjectFunction, + StaticPlatformFunction, + ObjectPlatformFunction, +} diff --git a/src/compile/mod.rs b/src/compile/mod.rs new file mode 100644 index 0000000..ca44059 --- /dev/null +++ b/src/compile/mod.rs @@ -0,0 +1,164 @@ +use crate::ast::{ + AssignExpression, BlockStatement, CallExpression, CompilationUnit, Declaration, Expression, + Fqn, FunctionDeclaration, Identifier, LValue, Statement, +}; +use crate::object_file::{DvmObjectFile, DvmPath}; +use crate::vm::function::DvmFunction; +use crate::vm::instruction::Instruction; +use declared_type::{DeclaredType, FunctionType}; +use std::rc::Rc; +use symbol_table::SymbolTable; + +mod declared_type; +mod symbol; +mod symbol_table; + +struct CompilationState { + fqn_part_stack: Vec, +} + +impl CompilationState { + fn push_fqn_identifier(&mut self, identifier: &Identifier) { + self.fqn_part_stack.push(identifier.clone()); + } + + fn pop_fqn_identifier(&mut self) { + self.fqn_part_stack.pop(); + } + + fn get_current_fqn(&self) -> Fqn { + Fqn::new(self.fqn_part_stack.clone()) + } +} + +struct CompilationContext { + source_file_name: String, + symbol_table: SymbolTable, +} + +fn compile_call_expression( + context: &CompilationContext, + call_expression: &CallExpression, + instructions: &mut Vec, +) { + match call_expression.receiver() { + Expression::LValue(lvalue) => { + let lvalue = &**lvalue; + if let LValue::Fqn(fqn) = lvalue { + let symbol = context.symbol_table.resolve(fqn); + match symbol.declared_type() { + DeclaredType::Function(function_type) => match function_type { + FunctionType::StaticFunction => { + instructions.push(Instruction::InvokeStatic { + function_name: Rc::new(convert_fqn(&fqn)), + source_code_location: call_expression + .source_code_location() + .clone(), + }); + } + _ => todo!(), + }, + } + } else { + todo!() + } + } + _ => todo!(), + } +} + +fn compile_assign_expression( + assign_expression: &AssignExpression, + instruction: &mut Vec, +) { + todo!() +} + +fn convert_statement( + context: &CompilationContext, + statement: &Statement, + instructions: &mut Vec, +) { + match statement { + Statement::CallStatement(call_expression) => { + compile_call_expression(context, call_expression, instructions); + } + Statement::AssignStatement(assign_expression) => { + compile_assign_expression(assign_expression, instructions); + } + } +} + +fn convert_block_statement( + context: &CompilationContext, + block_statement: &BlockStatement, +) -> Vec { + let mut instructions = vec![]; + for statement in block_statement.statements() { + convert_statement(context, statement, &mut instructions); + } + instructions +} + +fn convert_static_function( + compilation_state: &CompilationState, + context: &CompilationContext, + function_declaration: &FunctionDeclaration, +) -> DvmFunction { + let mut fqn = compilation_state.get_current_fqn(); + fqn.push_identifier(function_declaration.identifier().clone()); + + let instructions = convert_block_statement(context, function_declaration.block_statement()); + + DvmFunction::new( + &convert_fqn(&fqn), + &instructions, + function_declaration.source_code_location().clone(), + ) +} + +fn convert_fqn(fqn: &Fqn) -> String { + let mut as_string = String::new(); + let mut i = 0; + let identifiers = fqn.identifiers(); + while i < identifiers.len() { + as_string.push_str(identifiers[i].name()); + i += 1; + if i < identifiers.len() { + as_string.push_str("::"); + } + } + as_string +} + +fn make_path(file_name: &str, file_namespace: &Option) -> DvmPath { + if let Some(namespace) = file_namespace { + DvmPath::new(&convert_fqn(namespace), file_name) + } else { + DvmPath::new("", file_name) + } +} + +pub fn convert(file_name: &str, ast: CompilationUnit) -> DvmObjectFile { + let path = make_path(file_name, ast.namespace()); + let mut object_file = DvmObjectFile::new(path); + + let mut state = CompilationState { + fqn_part_stack: Vec::new(), + }; + let context = CompilationContext { + source_file_name: file_name.to_string(), + symbol_table: SymbolTable {}, + }; + + for declaration in ast.declarations() { + match declaration { + Declaration::Function(function_declaration) => { + let function = convert_static_function(&state, &context, function_declaration); + object_file.add_function(function); + } + _ => todo!("Unimplemented declaration {:?}", declaration), + } + } + object_file +} diff --git a/src/compile/symbol.rs b/src/compile/symbol.rs new file mode 100644 index 0000000..3a13dbe --- /dev/null +++ b/src/compile/symbol.rs @@ -0,0 +1,17 @@ +use crate::ast::Fqn; +use crate::compile::declared_type::DeclaredType; + +pub struct Symbol { + fqn: Fqn, + declared_type: DeclaredType, +} + +impl Symbol { + pub fn fqn(&self) -> &Fqn { + &self.fqn + } + + pub fn declared_type(&self) -> &DeclaredType { + &self.declared_type + } +} diff --git a/src/compile/symbol_table.rs b/src/compile/symbol_table.rs new file mode 100644 index 0000000..3897afa --- /dev/null +++ b/src/compile/symbol_table.rs @@ -0,0 +1,10 @@ +use crate::ast::Fqn; +use crate::compile::symbol::Symbol; + +pub struct SymbolTable {} + +impl SymbolTable { + pub fn resolve(&self, fqn: &Fqn) -> Symbol { + todo!() + } +} diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs deleted file mode 100644 index 33cf372..0000000 --- a/src/compiler/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::ast::CompilationUnit; -use crate::parser::{DeimosParser, Rule}; -use crate::module::DmModule; - -pub fn compile(module: &mut DmModule, compilation_unit: CompilationUnit) { - todo!() -} diff --git a/src/lib.rs b/src/lib.rs index 43dd3a1..c0a8b56 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ #![allow(warnings)] pub mod ast; -pub mod compiler; +pub mod compile; pub mod module; pub mod object_file; pub mod parser; diff --git a/src/vm/mod.rs b/src/vm/mod.rs index f30bea1..3fa6b74 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -176,7 +176,7 @@ impl Display for DvmCall { self.function_name, self.source_code_location.source_file_name, self.source_code_location.line, - self.source_code_location.char + self.source_code_location.col )) } } diff --git a/src/vm/source_code_location.rs b/src/vm/source_code_location.rs index 8b84819..b381eda 100644 --- a/src/vm/source_code_location.rs +++ b/src/vm/source_code_location.rs @@ -1,6 +1,16 @@ #[derive(Debug, Clone)] pub struct SourceCodeLocation { pub source_file_name: String, - pub line: i64, - pub char: i64, + pub line: usize, + pub col: usize, +} + +impl SourceCodeLocation { + pub fn new(source_file_name: &str, line: usize, col: usize) -> Self { + SourceCodeLocation { + source_file_name: source_file_name.to_string(), + line, + col + } + } }