deimos-lang/src/ast/build.rs
2025-04-16 09:12:48 -05:00

375 lines
12 KiB
Rust

use crate::ast::{
BlockStatement, CompilationUnit, Declaration, Fqn, FunctionDeclaration, GenericArgument,
GenericParameter, Identifier, ClassConstructor, 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<Rule>) -> Declaration {
todo!()
}
fn build_prop(prop_pair: Pair<Rule>) -> Declaration {
todo!()
}
fn build_generic_argument(generic_argument_pair: Pair<Rule>) -> 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<Rule>,
) -> Vec<GenericArgument> {
let mut generic_arguments: Vec<GenericArgument> = vec![];
for pair in generic_arguments_declaration_pair.into_inner() {
match pair.as_rule() {
Rule::GenericArguments => {
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<Rule>) -> 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<Rule>) -> TypeUse {
let mut fqn: Option<Fqn> = None;
let mut generic_arguments_declaration: Option<Vec<GenericArgument>> = None;
for pair in type_pair.into_inner() {
match pair.as_rule() {
Rule::FullyQualifiedName => {
fqn = Some(build_fqn(pair));
}
Rule::GenericArguments => {
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<Rule>,
) -> Vec<GenericParameter> {
let mut parameters: Vec<GenericParameter> = vec![];
for pair in generic_parameters_declaration_pair.into_inner() {
match pair.as_rule() {
Rule::Identifier => {
parameters.push(build_generic_parameter(pair));
}
_ => panic!("Expected only generic_parameter rule. Found: {}", pair),
}
}
parameters
}
fn build_extends_list(extends_list_pair: Pair<Rule>) -> Vec<TypeUse> {
let mut extensions: Vec<TypeUse> = vec![];
for pair in extends_list_pair.into_inner() {
match pair.as_rule() {
Rule::TypeUse => {
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<Rule>) -> Declaration {
let mut identifier: Option<Identifier> = None;
let mut generic_parameters: Option<Vec<GenericParameter>> = None;
let mut extends: Option<Vec<TypeUse>> = None;
let mut declarations: Vec<Declaration> = vec![];
for pair in interface_pair.into_inner() {
match pair.as_rule() {
Rule::Identifier => {
identifier = Some(build_identifier(pair));
}
Rule::GenericParameters => {
generic_parameters = Some(build_generic_parameters_declaration(pair));
}
Rule::ExtendsList => {
extends = Some(build_extends_list(pair));
}
Rule::InterfaceLevelDeclaration => {
declarations.push(build_module_level_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_class_constructor(class_constructor_pair: Pair<Rule>) -> ClassConstructor {
todo!()
}
fn build_implementation(
is_extern: bool,
is_public: bool,
implementation_pair: Pair<Rule>,
) -> Declaration {
let mut identifier: Option<Identifier> = None;
let mut generic_parameters: Option<Vec<GenericParameter>> = None;
let mut impl_ctor: Option<ClassConstructor> = None;
let mut extends: Option<Vec<TypeUse>> = None;
let mut declarations: Vec<Declaration> = vec![];
for pair in implementation_pair.into_inner() {
match pair.as_rule() {
Rule::Identifier => {
identifier = Some(build_identifier(pair));
}
Rule::GenericParameters => {
generic_parameters = Some(build_generic_parameters_declaration(pair));
}
Rule::ClassConstructor => {
impl_ctor = Some(build_class_constructor(pair));
}
Rule::ExtendsList => {
extends = Some(build_extends_list(pair));
}
Rule::ClassLevelDeclaration => {
declarations.push(build_module_level_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<Rule>) -> Declaration {
todo!()
}
fn build_parameter(pair: Pair<Rule>) -> Parameter {
let mut identifier: Option<Identifier> = None;
let mut declared_type: Option<TypeUse> = None;
for pair in pair.into_inner() {
match pair.as_rule() {
Rule::Identifier => {
identifier = Some(build_identifier(pair));
}
Rule::TypeAnnotation => {
declared_type = Some(build_type_use(pair));
}
_ => unreachable!(),
}
}
Parameter {
identifier: identifier.unwrap(),
declared_type,
}
}
fn build_parameters_list(pair: Pair<Rule>) -> Vec<Parameter> {
let mut parameters: Vec<Parameter> = vec![];
for pair in pair.into_inner() {
match pair.as_rule() {
Rule::Parameter => {
parameters.push(build_parameter(pair));
}
_ => unreachable!(),
}
}
parameters
}
fn build_block_statement(pair: Pair<Rule>) -> BlockStatement {
todo!()
}
fn build_function_equals_body(pair: Pair<Rule>) -> BlockStatement {
todo!()
}
fn build_function(is_extern: bool, is_public: bool, pair: Pair<Rule>) -> Declaration {
let mut is_implementation = false;
let mut generic_parameters: Option<Vec<GenericParameter>> = None;
let mut identifier: Option<Identifier> = None;
let mut parameters: Option<Vec<Parameter>> = None;
let mut return_type: Option<TypeUse> = None;
let mut statement: Option<BlockStatement> = None;
let (line, col) = pair.line_col();
for pair in pair.into_inner() {
match pair.as_rule() {
Rule::Implementation => {
is_implementation = true;
}
Rule::Identifier => {
identifier = Some(build_identifier(pair));
}
Rule::GenericParameters => {
generic_parameters = Some(build_generic_parameters_declaration(pair));
}
Rule::Parameters => {
parameters = Some(build_parameters_list(pair));
}
Rule::TypeUse => {
return_type = Some(build_type_use(pair));
}
Rule::BlockStatement => {
statement = Some(build_block_statement(pair));
}
Rule::FunctionEqualsBody => {
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_module_level_declaration(declaration_pair: Pair<Rule>) -> Declaration {
let mut is_extern = false;
let mut is_public = false;
let mut declaration: Option<Declaration> = None;
for pair in declaration_pair.into_inner() {
match pair.as_rule() {
Rule::Declare => {
is_extern = true;
}
Rule::Public => {
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));
}
_ => unreachable!(),
}
}
declaration.expect("Expected declaration.")
}
fn build_identifier(pair: Pair<Rule>) -> Identifier {
match pair.as_rule() {
Rule::Identifier => Identifier {
name: String::from(pair.as_str()),
},
_ => unreachable!(),
}
}
fn build_fqn(fqn_pair: Pair<Rule>) -> Fqn {
let mut identifiers: Vec<Identifier> = vec![];
for pair in fqn_pair.into_inner() {
match pair.as_rule() {
Rule::Identifier => {
identifiers.push(build_identifier(pair));
}
_ => unreachable!(),
}
}
Fqn { identifiers }
}
fn build_compilation_unit(pair: Pair<Rule>) -> CompilationUnit {
let mut namespace: Option<Fqn> = None;
let mut declarations: Vec<Declaration> = 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::ModuleLevelDeclaration => {
declarations.push(build_module_level_declaration(pair));
}
Rule::EOI => {} // ignore
_ => unreachable!(),
}
}
CompilationUnit {
namespace,
declarations,
}
}
pub fn build_ast(src: &str) -> CompilationUnit {
let pair = DeimosParser::parse(Rule::CompilationUnit, src)
.expect("Unsuccessful parse.")
.next()
.expect("Expected compilation_unit.");
match pair.as_rule() {
Rule::CompilationUnit => build_compilation_unit(pair),
_ => panic!("Expected compilation_unit rule."),
}
}