Skip to content

Commit

Permalink
Started with the module system
Browse files Browse the repository at this point in the history
  • Loading branch information
Razican committed Nov 26, 2022
1 parent 20ad700 commit 0eb350f
Show file tree
Hide file tree
Showing 81 changed files with 1,941 additions and 620 deletions.
59 changes: 59 additions & 0 deletions boa_ast/src/declaration/export.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//! Export declaration AST nodes.
//!
//! This module contains `export` declaration AST nodes.
//!
//! More information:
//! - [MDN documentation][mdn]
//! - [ECMAScript specification][spec]
//!
//! [spec]: https://tc39.es/ecma262/#sec-exports
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
use boa_interner::Sym;

/// An export declaration AST node.
///
/// More information:
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#prod-ExportDeclaration
#[derive(Debug, Clone, Copy)]
pub enum ExportDeclaration {
/// List of exports.
ExportList,
}

/// Export specifier
///
/// More information:
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#prod-ExportSpecifier
#[derive(Debug, Clone, Copy)]
pub struct ExportSpecifier {
export_name: Sym,
alias: Option<Sym>,
}

impl ExportSpecifier {
/// Creates a new [`ExportSpecifier`].
#[inline]
#[must_use]
pub const fn new(export_name: Sym, alias: Option<Sym>) -> Self {
Self { export_name, alias }
}

/// Gets the original export name.
#[inline]
#[must_use]
pub const fn export_name(self) -> Sym {
self.export_name
}

/// Gets an optional export alias for the export.
#[inline]
#[must_use]
pub const fn alias(self) -> Option<Sym> {
self.alias
}
}
144 changes: 144 additions & 0 deletions boa_ast/src/declaration/import.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
//! Import declaration AST nodes.
//!
//! This module contains `import` declaration AST nodes.
//!
//! More information:
//! - [MDN documentation][mdn]
//! - [ECMAScript specification][spec]
//!
//! [spec]: https://tc39.es/ecma262/#sec-imports
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
use crate::expression::Identifier;
use boa_interner::Sym;

/// An import declaration AST node.
///
/// More information:
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#prod-ImportDeclaration
#[derive(Debug, Clone)]
pub enum ImportDeclaration {
/// Full module import (`import "module-name"`).
Module(Sym),
/// Namespace import (`import * as name from "module-name"`), with an optional default export
/// binding.
Namespace {
/// Optional default export for the namespace import.
default_export: Option<Identifier>,
/// Alias for the namespace import.
alias: Identifier,
/// From clause.
from_clause: FromClause,
},
/// Import list (`import { export1, export2 as alias2} from "module-name"`), with an optional
/// default export binding.
ImportList {
/// Optional default export for the import list.
default_export: Option<Identifier>,
/// List of imports.
import_list: Box<[ImportSpecifier]>,
/// From clause.
from_clause: FromClause,
},
}

impl ImportDeclaration {
/// Creates a new namespace import declaration.
#[inline]
pub fn namespace<F>(
default_export: Option<Identifier>,
alias: Identifier,
from_clause: F,
) -> Self
where
F: Into<FromClause>,
{
Self::Namespace {
default_export,
alias,
from_clause: from_clause.into(),
}
}

/// Creates a new namespace import declaration.
#[inline]
pub fn import_list<L, F>(
default_export: Option<Identifier>,
import_list: L,
from_clause: F,
) -> Self
where
L: Into<Box<[ImportSpecifier]>>,
F: Into<FromClause>,
{
Self::ImportList {
default_export,
import_list: import_list.into(),
from_clause: from_clause.into(),
}
}
}

/// Import specifier
///
/// More information:
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#prod-ImportSpecifier
#[derive(Debug, Clone, Copy)]
pub struct ImportSpecifier {
import_name: Sym,
alias: Option<Identifier>,
}

impl ImportSpecifier {
/// Creates a new [`ImportSpecifier`].
#[inline]
#[must_use]
pub const fn new(import_name: Sym, alias: Option<Identifier>) -> Self {
Self { import_name, alias }
}

/// Gets the original import name.
#[inline]
#[must_use]
pub const fn import_name(self) -> Sym {
self.import_name
}

/// Gets an optional import alias for the import.
#[inline]
#[must_use]
pub const fn alias(self) -> Option<Identifier> {
self.alias
}
}

/// From clause AST node.
///
/// More information:
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#prod-FromClause
#[derive(Debug, Clone, Copy)]
pub struct FromClause {
module: Sym,
}

impl FromClause {
/// Gets the module specifier for the from clause.
#[inline]
#[must_use]
pub const fn module(self) -> Sym {
self.module
}
}

impl From<Sym> for FromClause {
#[inline]
fn from(s: Sym) -> Self {
Self { module: s }
}
}
4 changes: 4 additions & 0 deletions boa_ast/src/declaration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@ use super::function::{AsyncFunction, AsyncGenerator, Class, Function, Generator}
use boa_interner::{Interner, ToIndentedString, ToInternedString};
use core::ops::ControlFlow;

mod export;
mod import;
mod variable;

use crate::visitor::{VisitWith, Visitor, VisitorMut};
pub use export::*;
pub use import::*;
pub use variable::*;

/// The `Declaration` Parse Node.
Expand Down
2 changes: 2 additions & 0 deletions boa_ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ pub mod declaration;
pub mod expression;
pub mod function;
pub mod keyword;
pub mod module_item_list;
pub mod operations;
pub mod pattern;
pub mod property;
Expand All @@ -90,6 +91,7 @@ pub use self::{
declaration::Declaration,
expression::Expression,
keyword::Keyword,
module_item_list::{ModuleItem, ModuleItemList},
position::{Position, Span},
punctuator::Punctuator,
statement::Statement,
Expand Down
64 changes: 64 additions & 0 deletions boa_ast/src/module_item_list/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//! Module item list AST nodes.
//!
//! More information:
//! - [ECMAScript specification][spec]
//!
//! [spec]: https://tc39.es/ecma262/#sec-modules
use crate::{
declaration::{ExportDeclaration, ImportDeclaration},
StatementListItem,
};

/// Module item list AST node.
///
/// It contains a list of
///
/// More information:
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#prod-ModuleItemList
#[derive(Debug, Clone)]
pub struct ModuleItemList {
items: Box<[ModuleItem]>,
}

impl ModuleItemList {
/// Gets the list of module items.
#[inline]
#[must_use]
pub const fn items(&self) -> &[ModuleItem] {
&self.items
}
}

impl<T> From<T> for ModuleItemList
where
T: Into<Box<[ModuleItem]>>,
{
#[inline]
fn from(items: T) -> Self {
Self {
items: items.into(),
}
}
}

/// Module item AST node.
///
/// This is an extension over a [`StatementList`], which can also include multiple
/// [`ImportDeclaration`] and [`ExportDeclaration`] nodes.
///
/// More information:
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#prod-ModuleItem
#[derive(Debug, Clone)]
pub enum ModuleItem {
/// See [`ImportDeclaration`].
ImportDeclaration(ImportDeclaration),
/// See [`ExportDeclaration`].
ExportDeclaration(ExportDeclaration),
/// See [`StatementListItem`].
StatementListItem(StatementListItem),
}
8 changes: 4 additions & 4 deletions boa_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ where
{
let src_bytes = src.as_ref();
boa_parser::Parser::new(src_bytes)
.parse_all(context.interner_mut())
.map_err(|e| format!("ParsingError: {e}"))
.parse_script(context.interner_mut())
.map_err(|e| format!("Uncaught SyntaxError: {e}"))
}

/// Dumps the AST to stdout with format controlled by the given arguments.
Expand Down Expand Up @@ -276,7 +276,7 @@ fn main() -> Result<(), io::Error> {
Err(v) => eprintln!("Uncaught {v}"),
}
} else {
match context.eval(&buffer) {
match context.eval_script(&buffer) {
Ok(v) => println!("{}", v.display()),
Err(v) => eprintln!("Uncaught {v}"),
}
Expand Down Expand Up @@ -332,7 +332,7 @@ fn main() -> Result<(), io::Error> {
Err(v) => eprintln!("Uncaught {v}"),
}
} else {
match context.eval(line.trim_end()) {
match context.eval_script(line.trim_end()) {
Ok(v) => println!("{}", v.display()),
Err(v) => {
eprintln!("{}: {}", "Uncaught".red(), v.to_string().red());
Expand Down
10 changes: 5 additions & 5 deletions boa_engine/benches/full.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ macro_rules! full_benchmarks {
static CODE: &str = include_str!(concat!("bench_scripts/", stringify!($name), ".js"));
let mut context = Context::default();
c.bench_function(concat!($id, " (Parser)"), move |b| {
b.iter(|| context.parse(black_box(CODE)))
b.iter(|| context.parse_script(black_box(CODE)))
});
}
)*
Expand All @@ -32,10 +32,10 @@ macro_rules! full_benchmarks {
{
static CODE: &str = include_str!(concat!("bench_scripts/", stringify!($name), ".js"));
let mut context = Context::default();
let statement_list = context.parse(CODE).expect("parsing failed");
let statement_list = context.parse_script(CODE).expect("parsing failed");
c.bench_function(concat!($id, " (Compiler)"), move |b| {
b.iter(|| {
context.compile(black_box(&statement_list))
context.compile_script(black_box(&statement_list))
})
});
}
Expand All @@ -46,8 +46,8 @@ macro_rules! full_benchmarks {
{
static CODE: &str = include_str!(concat!("bench_scripts/", stringify!($name), ".js"));
let mut context = Context::default();
let statement_list = context.parse(CODE).expect("parsing failed");
let code_block = context.compile(&statement_list).unwrap();
let statement_list = context.parse_script(CODE).expect("parsing failed");
let code_block = context.compile_script(&statement_list).unwrap();
c.bench_function(concat!($id, " (Execution)"), move |b| {
b.iter(|| {
context.execute(black_box(code_block.clone())).unwrap()
Expand Down
Loading

0 comments on commit 0eb350f

Please sign in to comment.