Enable defining Symbol.iterator on classes

This commit is contained in:
Andrew Morris
2023-05-29 15:38:22 +10:00
parent 79b8523758
commit b949027501
4 changed files with 87 additions and 4 deletions

View File

@@ -15,6 +15,7 @@ mod name_allocator;
mod resolve_path;
mod scope;
mod scope_analysis;
mod static_eval_expr;
pub use assembler::assemble;
pub use assembly_parser::parse_module;

View File

@@ -14,9 +14,10 @@ use crate::asm::{
use crate::diagnostic::{Diagnostic, DiagnosticLevel};
use crate::expression_compiler::{CompiledExpression, ExpressionCompiler};
use crate::function_compiler::{FunctionCompiler, Functionish};
use crate::name_allocator::NameAllocator;
use crate::name_allocator::{ident_from_str, NameAllocator};
use crate::scope::OwnerId;
use crate::scope_analysis::ScopeAnalysis;
use crate::static_eval_expr::static_eval_expr;
struct DiagnosticCollector {
diagnostics: Arc<Mutex<Vec<Diagnostic>>>,
@@ -781,14 +782,28 @@ impl ModuleCompiler {
Constructor(_) => {}
Method(method) => {
let name = match &method.key {
swc_ecma_ast::PropName::Ident(ident) => ident.sym.to_string(),
swc_ecma_ast::PropName::Ident(ident) => Value::String(ident.sym.to_string()),
swc_ecma_ast::PropName::Computed(computed) => match static_eval_expr(&computed.expr) {
None => {
self.todo(
computed.span,
"Couldn't statically evaluate computed prop name",
);
continue;
}
Some(value) => value,
},
_ => {
self.todo(method.span, "Non-identifier method name");
continue;
}
};
let method_defn_name = self.allocate_defn(&format!("{}_{}", defn_name.name, name));
let method_defn_name = self.allocate_defn(&ident_from_str(&format!(
"{}_{}",
defn_name.name,
name.to_string()
)));
dependent_definitions.append(&mut self.compile_fn(
method_defn_name.clone(),
@@ -798,7 +813,7 @@ impl ModuleCompiler {
methods
.properties
.push((Value::String(name), Value::Pointer(method_defn_name)));
.push((name, Value::Pointer(method_defn_name)));
}
PrivateMethod(private_method) => self.todo(private_method.span, "PrivateMethod"),

View File

@@ -67,6 +67,43 @@ impl NameAllocator {
}
}
pub fn ident_from_str(str: &str) -> String {
let mut res = "".to_string();
let mut first = false;
let mut last_sep = false;
for c in str.chars() {
if first {
first = false;
if c.is_ascii_alphabetic() {
res.push(c);
continue;
}
res.push('_');
last_sep = true;
}
if !c.is_ascii_alphanumeric() {
if !last_sep {
res.push('_');
last_sep = true;
}
continue;
}
res.push(c);
last_sep = false;
}
match last_sep && res.len() > 1 {
false => res,
true => res[0..res.len() - 1].to_string(),
}
}
#[derive(Default)]
pub struct PointerAllocator {
alloc: NameAllocator,

View File

@@ -0,0 +1,30 @@
use crate::asm::{Builtin, Value};
pub fn static_eval_expr(expr: &swc_ecma_ast::Expr) -> Option<Value> {
let member_expr = match expr {
swc_ecma_ast::Expr::Member(member_expr) => member_expr,
_ => return None,
};
match &*member_expr.obj {
swc_ecma_ast::Expr::Ident(ident) => {
if ident.sym.to_string() != "Symbol" {
return None;
}
}
_ => return None,
};
match &member_expr.prop {
swc_ecma_ast::MemberProp::Ident(ident) => {
if ident.sym.to_string() != "iterator" {
return None;
}
}
_ => return None,
}
return Some(Value::Builtin(Builtin {
name: "SymbolIterator".to_string(),
}));
}